diff options
21 files changed, 144 insertions, 17 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f58eb0e7..92e0081ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,13 +137,13 @@ FUNCTION(TARGET_OS_LIBRARIES target) ENDIF() ENDFUNCTION() -# For the MSVC IDE, this function splits up the source files like windows -# 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" for the git2.dll -FUNCTION(MSVC_SPLIT_SOURCES target) - IF(MSVC_IDE) +# This function splits the sources files up into their appropriate +# subdirectories. This is especially useful for IDEs like Xcode and +# Visual Studio, so that you can navigate into the libgit2_clar project, +# and see the folders within the tests folder (instead of just seeing all +# source and tests in a single folder.) +FUNCTION(IDE_SPLIT_SOURCES target) + IF(MSVC_IDE OR CMAKE_GENERATOR STREQUAL Xcode) GET_TARGET_PROPERTY(sources ${target} SOURCES) FOREACH(source ${sources}) IF(source MATCHES ".*/") @@ -560,7 +560,7 @@ IF(MSVC AND GIT_ARCH_64 AND NOT BUILD_SHARED_LIBS) SET_TARGET_PROPERTIES(git2 PROPERTIES STATIC_LIBRARY_FLAGS "/MACHINE:x64") ENDIF() -MSVC_SPLIT_SOURCES(git2) +IDE_SPLIT_SOURCES(git2) IF (SONAME) SET_TARGET_PROPERTIES(git2 PROPERTIES VERSION ${LIBGIT2_VERSION_STRING}) @@ -629,7 +629,7 @@ IF (BUILD_CLAR) TARGET_LINK_LIBRARIES(libgit2_clar ${GSSAPI_LIBRARIES}) TARGET_LINK_LIBRARIES(libgit2_clar ${ICONV_LIBRARIES}) TARGET_OS_LIBRARIES(libgit2_clar) - MSVC_SPLIT_SOURCES(libgit2_clar) + IDE_SPLIT_SOURCES(libgit2_clar) IF (MSVC_IDE) # Precompiled headers diff --git a/include/git2/errors.h b/include/git2/errors.h index 4698366d8..1b528cf25 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -49,6 +49,7 @@ typedef enum { GIT_EINVALID = -21, /**< Invalid operation or input */ GIT_EUNCOMMITTED = -22, /**< Uncommitted changes in index prevented operation */ GIT_EDIRECTORY = -23, /**< The operation is not valid for a directory */ + GIT_EMERGECONFLICT = -24, /**< A merge conflict exists and cannot continue */ GIT_PASSTHROUGH = -30, /**< Internal only */ GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */ diff --git a/include/git2/merge.h b/include/git2/merge.h index 5fef452b9..ced9e51ff 100644 --- a/include/git2/merge.h +++ b/include/git2/merge.h @@ -72,6 +72,13 @@ typedef enum { * the ability to merge between a modified and renamed file. */ GIT_MERGE_TREE_FIND_RENAMES = (1 << 0), + + /** + * If a conflict occurs, exit immediately instead of attempting to + * continue resolving conflicts. The merge operation will fail with + * GIT_EMERGECONFLICT and no index will be returned. + */ + GIT_MERGE_TREE_FAIL_ON_CONFLICT = (1 << 1), } git_merge_tree_flag_t; /** diff --git a/src/diff.c b/src/diff.c index d97dcd9d2..d98a28966 100644 --- a/src/diff.c +++ b/src/diff.c @@ -493,8 +493,10 @@ static int diff_list_apply_options( /* Don't set GIT_DIFFCAPS_USE_DEV - compile time option in core git */ - /* Set GIT_DIFFCAPS_TRUST_NANOSECS on a platform basis */ + /* Don't trust nanoseconds; we do not load nanos from disk */ +#ifdef GIT_USE_NSEC diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_TRUST_NANOSECS; +#endif /* If not given explicit `opts`, check `diff.xyz` configs */ if (!opts) { diff --git a/src/merge.c b/src/merge.c index 930457bdb..3bed0fd3b 100644 --- a/src/merge.c +++ b/src/merge.c @@ -1701,8 +1701,15 @@ int git_merge__iterators( if ((error = merge_conflict_resolve(&resolved, diff_list, conflict, opts.file_favor, opts.file_flags)) < 0) goto done; - if (!resolved) + if (!resolved) { + if ((opts.tree_flags & GIT_MERGE_TREE_FAIL_ON_CONFLICT)) { + giterr_set(GITERR_MERGE, "merge conflicts exist"); + error = GIT_EMERGECONFLICT; + goto done; + } + git_vector_insert(&diff_list->conflicts, conflict); + } } if (!given_opts || !given_opts->metric) diff --git a/src/xdiff/xdiff.h b/src/xdiff/xdiff.h index db5d59884..f08f72e16 100644 --- a/src/xdiff/xdiff.h +++ b/src/xdiff/xdiff.h @@ -20,7 +20,7 @@ * */ -#include "util.h" +#include "../util.h" #if !defined(XDIFF_H) #define XDIFF_H diff --git a/tests/index/nsec.c b/tests/index/nsec.c new file mode 100644 index 000000000..5004339f0 --- /dev/null +++ b/tests/index/nsec.c @@ -0,0 +1,78 @@ +#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 "nsecs" + +// Fixture setup and teardown +void test_index_nsec__initialize(void) +{ + repo = cl_git_sandbox_init("nsecs"); + git_repository_index(&repo_index, repo); +} + +void test_index_nsec__cleanup(void) +{ + git_index_free(repo_index); + repo_index = NULL; + + cl_git_sandbox_cleanup(); +} + +static bool has_nsecs(void) +{ + const git_index_entry *entry; + size_t i; + bool has_nsecs = false; + + for (i = 0; i < git_index_entrycount(repo_index); i++) { + entry = git_index_get_byindex(repo_index, i); + + if (entry->ctime.nanoseconds || entry->mtime.nanoseconds) { + has_nsecs = true; + break; + } + } + + return has_nsecs; +} + +void test_index_nsec__has_nanos(void) +{ + cl_assert_equal_b(true, has_nsecs()); +} + +void test_index_nsec__staging_maintains_other_nanos(void) +{ + const git_index_entry *entry; + + cl_git_rewritefile("nsecs/a.txt", "This is file A"); + cl_git_pass(git_index_add_bypath(repo_index, "a.txt")); + cl_git_pass(git_index_write(repo_index)); + + cl_git_pass(git_index_write(repo_index)); + + git_index_read(repo_index, 1); + cl_assert_equal_b(true, has_nsecs()); + + cl_assert((entry = git_index_get_bypath(repo_index, "a.txt", 0))); + cl_assert_equal_i(0, entry->ctime.nanoseconds); + cl_assert_equal_i(0, entry->mtime.nanoseconds); +} + +void test_index_nsec__status_doesnt_clear_nsecs(void) +{ + git_status_list *statuslist; + + cl_git_pass(git_status_list_new(&statuslist, repo, NULL)); + + git_index_read(repo_index, 1); + cl_assert_equal_b(true, has_nsecs()); + + git_status_list_free(statuslist); +} diff --git a/tests/merge/merge_helpers.c b/tests/merge/merge_helpers.c index f81471424..986a365db 100644 --- a/tests/merge/merge_helpers.c +++ b/tests/merge/merge_helpers.c @@ -40,7 +40,7 @@ int merge_trees_from_branches( 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)); + error = git_merge_trees(index, repo, ancestor_tree, our_tree, their_tree, opts); git_buf_free(&branch_buf); git_tree_free(our_tree); @@ -50,7 +50,7 @@ int merge_trees_from_branches( git_commit_free(their_commit); git_commit_free(ancestor_commit); - return 0; + return error; } int merge_commits_from_branches( @@ -61,6 +61,7 @@ int merge_commits_from_branches( git_commit *our_commit, *their_commit; git_oid our_oid, their_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)); @@ -71,13 +72,13 @@ int merge_commits_from_branches( 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_commits(index, repo, our_commit, their_commit, opts)); + error = git_merge_commits(index, repo, our_commit, their_commit, opts); git_buf_free(&branch_buf); git_commit_free(our_commit); git_commit_free(their_commit); - return 0; + return error; } int merge_branches(git_repository *repo, diff --git a/tests/merge/trees/commits.c b/tests/merge/trees/commits.c index c4e470997..2e3c4578b 100644 --- a/tests/merge/trees/commits.c +++ b/tests/merge/trees/commits.c @@ -94,7 +94,6 @@ void test_merge_trees_commits__no_ancestor(void) git_index_free(index); } - void test_merge_trees_commits__df_conflict(void) { git_index *index; @@ -129,3 +128,20 @@ void test_merge_trees_commits__df_conflict(void) git_index_free(index); } + +void test_merge_trees_commits__fail_on_conflict(void) +{ + git_index *index; + git_merge_options opts = GIT_MERGE_OPTIONS_INIT; + + opts.tree_flags |= GIT_MERGE_TREE_FAIL_ON_CONFLICT; + + cl_git_fail_with(GIT_EMERGECONFLICT, + merge_trees_from_branches(&index, repo, "df_side1", "df_side2", &opts)); + + cl_git_fail_with(GIT_EMERGECONFLICT, + merge_commits_from_branches(&index, repo, "master", "unrelated", &opts)); + cl_git_fail_with(GIT_EMERGECONFLICT, + merge_commits_from_branches(&index, repo, "master", "branch", &opts)); +} + diff --git a/tests/resources/nsecs/.gitted/HEAD b/tests/resources/nsecs/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/nsecs/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/nsecs/.gitted/config b/tests/resources/nsecs/.gitted/config new file mode 100644 index 000000000..78387c50b --- /dev/null +++ b/tests/resources/nsecs/.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/nsecs/.gitted/index b/tests/resources/nsecs/.gitted/index Binary files differnew file mode 100644 index 000000000..9233f1b11 --- /dev/null +++ b/tests/resources/nsecs/.gitted/index diff --git a/tests/resources/nsecs/.gitted/objects/03/1986a8372d1442cfe9e3b54906a9aadc524a7e b/tests/resources/nsecs/.gitted/objects/03/1986a8372d1442cfe9e3b54906a9aadc524a7e new file mode 100644 index 000000000..a813b7424 --- /dev/null +++ b/tests/resources/nsecs/.gitted/objects/03/1986a8372d1442cfe9e3b54906a9aadc524a7e @@ -0,0 +1,2 @@ +xA +0D]J4DMu-/"FHFf
PaʠZrnX*4kUixK-#%y Z20;Џ;
ŰJZ7FRBy?g?<^@]f˔GvܵNUOKv
\ No newline at end of file diff --git a/tests/resources/nsecs/.gitted/objects/03/9afd91c98f82c14e425bb6796d8ca98e9c8cac b/tests/resources/nsecs/.gitted/objects/03/9afd91c98f82c14e425bb6796d8ca98e9c8cac Binary files differnew file mode 100644 index 000000000..74bb7d3fe --- /dev/null +++ b/tests/resources/nsecs/.gitted/objects/03/9afd91c98f82c14e425bb6796d8ca98e9c8cac diff --git a/tests/resources/nsecs/.gitted/objects/6d/8b18077cc99abd8dda05a6062c646406abb2d4 b/tests/resources/nsecs/.gitted/objects/6d/8b18077cc99abd8dda05a6062c646406abb2d4 Binary files differnew file mode 100644 index 000000000..7bf3a956c --- /dev/null +++ b/tests/resources/nsecs/.gitted/objects/6d/8b18077cc99abd8dda05a6062c646406abb2d4 diff --git a/tests/resources/nsecs/.gitted/objects/c5/12b6c64656b87ea8caf37a32bc5a562d797745 b/tests/resources/nsecs/.gitted/objects/c5/12b6c64656b87ea8caf37a32bc5a562d797745 Binary files differnew file mode 100644 index 000000000..dcf4c8ccb --- /dev/null +++ b/tests/resources/nsecs/.gitted/objects/c5/12b6c64656b87ea8caf37a32bc5a562d797745 diff --git a/tests/resources/nsecs/.gitted/objects/df/78d3d51c369e1d2f1eadb73464aadd931d56b4 b/tests/resources/nsecs/.gitted/objects/df/78d3d51c369e1d2f1eadb73464aadd931d56b4 Binary files differnew file mode 100644 index 000000000..df45d3314 --- /dev/null +++ b/tests/resources/nsecs/.gitted/objects/df/78d3d51c369e1d2f1eadb73464aadd931d56b4 diff --git a/tests/resources/nsecs/.gitted/refs/heads/master b/tests/resources/nsecs/.gitted/refs/heads/master new file mode 100644 index 000000000..3dda65b65 --- /dev/null +++ b/tests/resources/nsecs/.gitted/refs/heads/master @@ -0,0 +1 @@ +031986a8372d1442cfe9e3b54906a9aadc524a7e diff --git a/tests/resources/nsecs/a.txt b/tests/resources/nsecs/a.txt new file mode 100644 index 000000000..be4c1ee68 --- /dev/null +++ b/tests/resources/nsecs/a.txt @@ -0,0 +1 @@ +File A
diff --git a/tests/resources/nsecs/b.txt b/tests/resources/nsecs/b.txt new file mode 100644 index 000000000..19a0af40f --- /dev/null +++ b/tests/resources/nsecs/b.txt @@ -0,0 +1 @@ +File B
diff --git a/tests/resources/nsecs/c.txt b/tests/resources/nsecs/c.txt new file mode 100644 index 000000000..31d776008 --- /dev/null +++ b/tests/resources/nsecs/c.txt @@ -0,0 +1 @@ +File C
|