#include "diff_helpers.h"
#include "repository.h"
#include "git2/sys/diff.h"
+#include "../checkout/checkout_helpers.h"
static git_repository *g_repo = NULL;
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
else
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
/* to generate these values:
* - cd to tests/resources/status,
/* Adding an entry that represents a rename gets two files in conflict */
our_entry.path = "subdir/modified_file";
our_entry.mode = 0100644;
+ git_oid_fromstr(&our_entry.id, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf");
their_entry.path = "subdir/rename_conflict";
their_entry.mode = 0100644;
+ git_oid_fromstr(&their_entry.id, "2bd0a343aeef7a2cf0d158478966a6e587ff3863");
cl_git_pass(git_repository_index(&index, g_repo));
cl_git_pass(git_index_conflict_add(index, NULL, &our_entry, &their_entry));
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &opts));
cl_git_pass(diff_foreach_via_iterator(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(9, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(8, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
cl_assert_equal_i(4, exp.file_status[GIT_DELTA_DELETED]);
cl_assert((iep = git_index_get_bypath(idx, "modified_file", 0)) != NULL);
memcpy(&ie, iep, sizeof(ie));
- ie.flags |= GIT_IDXENTRY_VALID;
+ ie.flags |= GIT_INDEX_ENTRY_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;
+ ie.flags |= GIT_INDEX_ENTRY_VALID;
cl_git_pass(git_index_add(idx, &ie));
cl_git_pass(git_index_write(idx));
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(6, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
cl_assert_equal_i(3, exp.file_status[GIT_DELTA_DELETED]);
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
else
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(14, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
else
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(15, exp.files);
cl_assert_equal_i(2, exp.file_status[GIT_DELTA_ADDED]);
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
else
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(16, exp.files);
cl_assert_equal_i(5, exp.file_status[GIT_DELTA_ADDED]);
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(16, exp.files);
cl_assert_equal_i(5, exp.file_status[GIT_DELTA_DELETED]);
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff, diff_file_cb, NULL, NULL, &exp));
+ diff, diff_file_cb, NULL, NULL, NULL, &exp));
else
- cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp));
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(13, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff, diff_file_cb, NULL, NULL, &exp));
+ diff, diff_file_cb, NULL, NULL, NULL, &exp));
else
- cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp));
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff, diff_file_cb, NULL, NULL, &exp));
+ diff, diff_file_cb, NULL, NULL, NULL, &exp));
else
- cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp));
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(3, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff, diff_file_cb, NULL, NULL, &exp));
+ diff, diff_file_cb, NULL, NULL, NULL, &exp));
else
- cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp));
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(2, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
git_diff_free(diff);
}
+void test_diff_workdir__to_index_with_pathlist_disabling_fnmatch(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 |
+ GIT_DIFF_DISABLE_PATHSPEC_MATCH;
+ opts.pathspec.strings = &pathspec;
+ opts.pathspec.count = 0;
+
+ /* ensure that an empty pathspec list is ignored */
+ 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, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
+
+ cl_assert_equal_i(13, exp.files);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
+ 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);
+
+ /* ensure that a single NULL pathspec is filtered out (like when using
+ * fnmatch filtering)
+ */
+
+ 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, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
+
+ cl_assert_equal_i(13, exp.files);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
+ 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, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
+
+ cl_assert_equal_i(1, exp.files);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
+ 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);
+
+ /* ensure that subdirs can be specified */
+ 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, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
+
+ cl_assert_equal_i(3, exp.files);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
+ 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);
+
+ /* ensure that subdirs can be specified with a trailing slash */
+ 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, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
+
+ cl_assert_equal_i(3, exp.files);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
+ 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);
+
+ /* ensure that fnmatching is completely disabled */
+ 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, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &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.file_status[GIT_DELTA_IGNORED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]);
+ }
+
+ git_diff_free(diff);
+
+ /* ensure that the prefix matching isn't completely braindead */
+ pathspec = "subdi";
+
+ 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, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &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.file_status[GIT_DELTA_IGNORED]);
+ cl_assert_equal_i(0, exp.file_status[GIT_DELTA_UNTRACKED]);
+ }
+
+ git_diff_free(diff);
+
+ /* ensure that fnmatching isn't working at all */
+ 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, NULL, &exp));
+ else
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &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.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;
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
else
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(0, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
else
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(0, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL));
memset(&exp, 0, sizeof(exp));
- cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ cl_git_pass(git_diff_foreach(diff,
+ diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(0, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff_i2t, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
else
cl_git_pass(git_diff_foreach(
- diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff_i2t, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff_w2i, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff_w2i, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
else
cl_git_pass(git_diff_foreach(
- diff_w2i, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff_w2i, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff_i2t, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
else
cl_git_pass(git_diff_foreach(
- diff_i2t, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff_i2t, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
else
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(0, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
else
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
else
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
/* so "git diff 873585" returns:
* M .gitmodules
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(exp.files, exp.file_status[GIT_DELTA_UNTRACKED]);
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);
+ err = git_error_last();
+ cl_assert_equal_i(GIT_ERROR_INVALID, err->klass);
- giterr_clear();
+ git_error_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);
+ err = git_error_last();
+ cl_assert_equal_i(GIT_ERROR_INVALID, err->klass);
}
void test_diff_workdir__can_diff_empty_file(void)
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(0, exp.files);
cl_assert_equal_i(0, exp.hunks);
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_MODIFIED]);
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(0, exp.files);
cl_assert_equal_i(0, exp.hunks);
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(0, exp.files);
cl_assert_equal_i(0, exp.hunks);
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
- cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp));
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(3, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
- cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp));
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(4, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
- cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp));
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(4, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
- cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp));
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(4, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
- cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp));
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(4, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
- cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp));
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(4, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
- cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp));
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(4, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
- cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp));
+ cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(4, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
cl_assert_equal_s(expected_patience, buf.ptr);
git_buf_clear(&buf);
- git_buf_free(&buf);
+ git_buf_dispose(&buf);
git_patch_free(patch);
git_diff_free(diff);
}
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(17, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
- diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
git_diff_free(diff);
static int touch_file(void *payload, git_buf *path)
{
- int fd;
- char b;
+ struct stat st;
+ struct p_timeval times[2];
GIT_UNUSED(payload);
if (git_path_isdir(path->ptr))
return 0;
- cl_assert((fd = p_open(path->ptr, O_RDWR)) >= 0);
- cl_assert_equal_i(1, p_read(fd, &b, 1));
- cl_must_pass(p_lseek(fd, 0, SEEK_SET));
- cl_must_pass(p_write(fd, &b, 1));
- cl_must_pass(p_close(fd));
+ cl_must_pass(p_stat(path->ptr, &st));
+
+ times[0].tv_sec = st.st_mtime + 3;
+ times[0].tv_usec = 0;
+ times[1].tv_sec = st.st_mtime + 3;
+ times[1].tv_usec = 0;
+ cl_must_pass(p_utimes(path->ptr, times));
return 0;
}
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
- *out, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
+ *out, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(13, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_diff *diff = NULL;
git_diff_perfdata perf = GIT_DIFF_PERFDATA_INIT;
+ git_index *index;
g_repo = cl_git_sandbox_init("status");
git_buf path = GIT_BUF_INIT;
cl_git_pass(git_buf_sets(&path, "status"));
cl_git_pass(git_path_direach(&path, 0, touch_file, NULL));
- git_buf_free(&path);
+ git_buf_dispose(&path);
}
opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED;
/* now allow diff to update stat cache */
opts.flags |= GIT_DIFF_UPDATE_INDEX;
+ /* advance a tick for the index so we don't re-calculate racily-clean entries */
+ cl_git_pass(git_repository_index__weakptr(&index, g_repo));
+ tick_index(index);
+
basic_diff_status(&diff, &opts);
cl_git_pass(git_diff_get_perfdata(&perf, diff));
/* now if we do it again, we should see fewer OID calculations */
+ /* tick again as the index updating from the previous diff might have reset the timestamp */
+ tick_index(index);
basic_diff_status(&diff, &opts);
cl_git_pass(git_diff_get_perfdata(&perf, diff));
git_buf b = GIT_BUF_INIT;
int i;
git_buf data[10] = {
- { "1234567890", 0, 0 }, /* 0 - all ascii text control */
- { "\xC3\x85\xC3\xBC\xE2\x80\xA0\x48\xC3\xB8\xCF\x80\xCE\xA9", 0, 0 }, /* 1 - UTF-8 multibyte text */
- { "\xEF\xBB\xBF\xC3\x9C\xE2\xA4\x92\xC6\x92\x38\xC2\xA3\xE2\x82\xAC", 0, 0 }, /* 2 - UTF-8 with BOM */
+ { "1234567890", 0, 10 }, /* 0 - all ascii text control */
+ { "\xC3\x85\xC3\xBC\xE2\x80\xA0\x48\xC3\xB8\xCF\x80\xCE\xA9", 0, 14 }, /* 1 - UTF-8 multibyte text */
+ { "\xEF\xBB\xBF\xC3\x9C\xE2\xA4\x92\xC6\x92\x38\xC2\xA3\xE2\x82\xAC", 0, 16 }, /* 2 - UTF-8 with BOM */
{ STR999Z, 0, 1000 }, /* 3 - ASCII with NUL at 1000 */
{ STR3999Z, 0, 4000 }, /* 4 - ASCII with NUL at 4000 */
{ STR4000 STR3999Z "x", 0, 8001 }, /* 5 - ASCII with NUL at 8000 */
cl_git_write2file(
b.ptr, data[i].ptr, data[i].size, O_WRONLY|O_TRUNC, 0664);
}
- git_index_write(idx);
+ cl_git_pass(git_index_write(idx));
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL));
cl_git_write2file(b.ptr, "baseline\n", 9, O_WRONLY|O_TRUNC, 0664);
}
- git_index_write(idx);
+ cl_git_pass(git_index_write(idx));
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, NULL));
git_diff_free(diff);
git_index_free(idx);
- git_buf_free(&b);
+ git_buf_dispose(&b);
+}
+
+void test_diff_workdir__to_index_conflicted(void) {
+ const char *a_commit = "26a125ee1bf"; /* the current HEAD */
+ git_index_entry ancestor = {{0}}, ours = {{0}}, theirs = {{0}};
+ git_tree *a;
+ git_index *index;
+ git_diff *diff1, *diff2;
+ const git_diff_delta *delta;
+
+ g_repo = cl_git_sandbox_init("status");
+ a = resolve_commit_oid_to_tree(g_repo, a_commit);
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+
+ ancestor.path = ours.path = theirs.path = "_file";
+ ancestor.mode = ours.mode = theirs.mode = 0100644;
+ git_oid_fromstr(&ancestor.id, "d427e0b2e138501a3d15cc376077a3631e15bd46");
+ git_oid_fromstr(&ours.id, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf");
+ git_oid_fromstr(&theirs.id, "2bd0a343aeef7a2cf0d158478966a6e587ff3863");
+ cl_git_pass(git_index_conflict_add(index, &ancestor, &ours, &theirs));
+
+ cl_git_pass(git_diff_tree_to_index(&diff1, g_repo, a, index, NULL));
+ cl_git_pass(git_diff_index_to_workdir(&diff2, g_repo, index, NULL));
+ cl_git_pass(git_diff_merge(diff1, diff2));
+
+ cl_assert_equal_i(git_diff_num_deltas(diff1), 12);
+ delta = git_diff_get_delta(diff1, 0);
+ cl_assert_equal_s(delta->old_file.path, "_file");
+ cl_assert_equal_i(delta->nfiles, 1);
+ cl_assert_equal_i(delta->status, GIT_DELTA_CONFLICTED);
+
+ git_diff_free(diff2);
+ git_diff_free(diff1);
+ git_index_free(index);
+ git_tree_free(a);
+}
+
+void test_diff_workdir__only_writes_index_when_necessary(void)
+{
+ git_index *index;
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+ git_diff *diff = NULL;
+ git_reference *head;
+ git_object *head_object;
+ git_oid initial, first, second;
+ git_buf path = GIT_BUF_INIT;
+ struct stat st;
+ struct p_timeval times[2];
+
+ opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_UPDATE_INDEX;
+
+ g_repo = cl_git_sandbox_init("status");
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+ cl_git_pass(git_repository_head(&head, g_repo));
+ cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJECT_COMMIT));
+
+ cl_git_pass(git_reset(g_repo, head_object, GIT_RESET_HARD, NULL));
+
+ git_oid_cpy(&initial, git_index_checksum(index));
+
+ /* update the index timestamp to avoid raciness */
+ cl_must_pass(p_stat("status/.git/index", &st));
+
+ times[0].tv_sec = st.st_mtime + 5;
+ times[0].tv_usec = 0;
+ times[1].tv_sec = st.st_mtime + 5;
+ times[1].tv_usec = 0;
+
+ cl_must_pass(p_utimes("status/.git/index", times));
+
+ /* ensure diff doesn't touch the index */
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+ git_diff_free(diff);
+
+ git_oid_cpy(&first, git_index_checksum(index));
+ cl_assert(!git_oid_equal(&initial, &first));
+
+ /* touch all the files so stat times are different */
+ cl_git_pass(git_buf_sets(&path, "status"));
+ cl_git_pass(git_path_direach(&path, 0, touch_file, NULL));
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+ git_diff_free(diff);
+
+ /* ensure the second diff did update the index */
+ git_oid_cpy(&second, git_index_checksum(index));
+ cl_assert(!git_oid_equal(&first, &second));
+
+ git_buf_dispose(&path);
+ git_object_free(head_object);
+ git_reference_free(head);
+ git_index_free(index);
+}
+
+void test_diff_workdir__to_index_pathlist(void)
+{
+ git_index *index;
+ git_diff *diff;
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+ git_vector pathlist = GIT_VECTOR_INIT;
+
+ git_vector_insert(&pathlist, "foobar/asdf");
+ git_vector_insert(&pathlist, "subdir/asdf");
+ git_vector_insert(&pathlist, "ignored/asdf");
+
+ g_repo = cl_git_sandbox_init("status");
+
+ cl_git_mkfile("status/.gitignore", ".gitignore\n" "ignored/\n");
+
+ cl_must_pass(p_mkdir("status/foobar", 0777));
+ cl_git_mkfile("status/foobar/one", "one\n");
+
+ cl_must_pass(p_mkdir("status/ignored", 0777));
+ cl_git_mkfile("status/ignored/one", "one\n");
+ cl_git_mkfile("status/ignored/two", "two\n");
+ cl_git_mkfile("status/ignored/three", "three\n");
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+
+ opts.flags = GIT_DIFF_INCLUDE_IGNORED;
+ opts.pathspec.strings = (char **)pathlist.contents;
+ opts.pathspec.count = pathlist.length;
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &opts));
+ cl_assert_equal_i(0, git_diff_num_deltas(diff));
+ git_diff_free(diff);
+
+ opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, index, &opts));
+ cl_assert_equal_i(0, git_diff_num_deltas(diff));
+ git_diff_free(diff);
+
+ git_index_free(index);
+ git_vector_free(&pathlist);
+}
+
+void test_diff_workdir__symlink_changed_on_non_symlink_platform(void)
+{
+ git_tree *tree;
+ git_diff *diff;
+ diff_expects exp = {0};
+ const git_diff_delta *delta;
+ const char *commit = "7fccd7";
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+ git_vector pathlist = GIT_VECTOR_INIT;
+ int symlinks;
+
+ g_repo = cl_git_sandbox_init("unsymlinked.git");
+
+ cl_git_pass(git_repository__configmap_lookup(&symlinks, g_repo, GIT_CONFIGMAP_SYMLINKS));
+
+ if (symlinks)
+ cl_skip();
+
+ cl_git_pass(git_vector_insert(&pathlist, "include/Nu/Nu.h"));
+
+ opts.pathspec.strings = (char **)pathlist.contents;
+ opts.pathspec.count = pathlist.length;
+
+ cl_must_pass(p_mkdir("symlink", 0777));
+ cl_git_pass(git_repository_set_workdir(g_repo, "symlink", false));
+
+ cl_assert((tree = resolve_commit_oid_to_tree(g_repo, commit)) != NULL);
+
+ /* first, do the diff with the original contents */
+
+ cl_git_pass(git_futils_mkpath2file("symlink/include/Nu/Nu.h", 0755));
+ cl_git_mkfile("symlink/include/Nu/Nu.h", "../../objc/Nu.h");
+
+ cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
+ cl_assert_equal_i(0, git_diff_num_deltas(diff));
+ git_diff_free(diff);
+
+ /* now update the contents and expect a difference, but that the file
+ * mode has persisted as a symbolic link.
+ */
+
+ cl_git_rewritefile("symlink/include/Nu/Nu.h", "awesome content\n");
+
+ cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
+
+ cl_git_pass(git_diff_foreach(
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
+ cl_assert_equal_i(1, exp.files);
+
+ cl_assert_equal_i(1, git_diff_num_deltas(diff));
+ delta = git_diff_get_delta(diff, 0);
+ cl_assert_equal_i(GIT_FILEMODE_LINK, delta->old_file.mode);
+ cl_assert_equal_i(GIT_FILEMODE_LINK, delta->new_file.mode);
+
+ git_diff_free(diff);
+
+ cl_git_pass(git_futils_rmdir_r("symlink", NULL, GIT_RMDIR_REMOVE_FILES));
+
+ git_tree_free(tree);
+ git_vector_free(&pathlist);
+}
+
+void test_diff_workdir__order(void)
+{
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+ git_buf patch = GIT_BUF_INIT;
+ git_oid tree_oid, blob_oid;
+ git_treebuilder *builder;
+ git_tree *tree;
+ git_diff *diff;
+
+ g_repo = cl_git_sandbox_init("empty_standard_repo");
+
+ /* Build tree with a single file "abc.txt" */
+ cl_git_pass(git_blob_create_from_buffer(&blob_oid, g_repo, "foo\n", 4));
+ cl_git_pass(git_treebuilder_new(&builder, g_repo, NULL));
+ cl_git_pass(git_treebuilder_insert(NULL, builder, "abc.txt", &blob_oid, GIT_FILEMODE_BLOB));
+ cl_git_pass(git_treebuilder_write(&tree_oid, builder));
+ cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_oid));
+
+ /* Create a directory that sorts before and one that sorts after "abc.txt" */
+ cl_git_mkfile("empty_standard_repo/abc.txt", "bar\n");
+ cl_must_pass(p_mkdir("empty_standard_repo/abb", 0777));
+ cl_must_pass(p_mkdir("empty_standard_repo/abd", 0777));
+
+ opts.flags = GIT_DIFF_INCLUDE_UNTRACKED;
+ cl_git_pass(git_diff_tree_to_workdir(&diff, g_repo, tree, &opts));
+
+ cl_assert_equal_i(1, git_diff_num_deltas(diff));
+ cl_git_pass(git_diff_to_buf(&patch, diff, GIT_DIFF_FORMAT_PATCH));
+ cl_assert_equal_s(patch.ptr,
+ "diff --git a/abc.txt b/abc.txt\n"
+ "index 257cc56..5716ca5 100644\n"
+ "--- a/abc.txt\n"
+ "+++ b/abc.txt\n"
+ "@@ -1 +1 @@\n"
+ "-foo\n"
+ "+bar\n");
+
+ git_treebuilder_free(builder);
+ git_buf_dispose(&patch);
+ git_diff_free(diff);
+ git_tree_free(tree);
}