diff: fix generation of the header of a removal patch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
diff --git a/src/diff.c b/src/diff.c
index 7d2ad59..b239031 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -232,9 +232,6 @@ static int diff_delta__from_two(
return 0;
}
-#define DIFF_SRC_PREFIX_DEFAULT "a/"
-#define DIFF_DST_PREFIX_DEFAULT "b/"
-
static char *diff_strdup_prefix(git_pool *pool, const char *prefix)
{
size_t len = strlen(prefix);
diff --git a/src/diff.h b/src/diff.h
index 4de18be..6c432c8 100644
--- a/src/diff.h
+++ b/src/diff.h
@@ -14,6 +14,9 @@
#include "repository.h"
#include "pool.h"
+#define DIFF_SRC_PREFIX_DEFAULT "a/"
+#define DIFF_DST_PREFIX_DEFAULT "b/"
+
enum {
GIT_DIFFCAPS_HAS_SYMLINKS = (1 << 0), /* symlinks on platform? */
GIT_DIFFCAPS_ASSUME_UNCHANGED = (1 << 1), /* use stat? */
diff --git a/src/diff_output.c b/src/diff_output.c
index f4c2143..7c5b6f2 100644
--- a/src/diff_output.c
+++ b/src/diff_output.c
@@ -553,9 +553,16 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress)
const char *oldpath = delta->old.path;
const char *newpfx = pi->diff->opts.dst_prefix;
const char *newpath = delta->new.path;
+ int result;
GIT_UNUSED(progress);
+ if (!oldpfx)
+ oldpfx = DIFF_SRC_PREFIX_DEFAULT;
+
+ if (!newpfx)
+ newpfx = DIFF_DST_PREFIX_DEFAULT;
+
git_buf_clear(pi->buf);
git_buf_printf(pi->buf, "diff --git %s%s %s%s\n", oldpfx, delta->old.path, newpfx, delta->new.path);
@@ -567,8 +574,8 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress)
oldpath = "/dev/null";
}
if (git_oid_iszero(&delta->new.oid)) {
- oldpfx = "";
- oldpath = "/dev/null";
+ newpfx = "";
+ newpath = "/dev/null";
}
if (delta->binary != 1) {
@@ -579,9 +586,12 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress)
if (git_buf_oom(pi->buf))
return -1;
- if (pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr) < 0 ||
- delta->binary != 1)
- return -1;
+ result = pi->print_cb(pi->cb_data, GIT_DIFF_LINE_FILE_HDR, pi->buf->ptr);
+ if (result < 0)
+ return result;
+
+ if (delta->binary != 1)
+ return 0;
git_buf_clear(pi->buf);
git_buf_printf(
diff --git a/tests-clar/diff/patch.c b/tests-clar/diff/patch.c
new file mode 100644
index 0000000..e257627
--- /dev/null
+++ b/tests-clar/diff/patch.c
@@ -0,0 +1,68 @@
+#include "clar_libgit2.h"
+#include "diff_helpers.h"
+
+static git_repository *g_repo = NULL;
+
+void test_diff_patch__initialize(void)
+{
+ g_repo = cl_git_sandbox_init("status");
+}
+
+void test_diff_patch__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+}
+
+#define EXPECTED_OUTPUT "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"
+
+static int check_removal_cb(
+ void *cb_data,
+ char line_origin,
+ const char *formatted_output)
+{
+ GIT_UNUSED(cb_data);
+
+ if (line_origin != 'F')
+ return 0;
+
+ if (strcmp(EXPECTED_OUTPUT, formatted_output) == 0)
+ return 0;
+
+ return -1;
+}
+
+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_list *diff;
+
+ 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(g_repo, NULL, one, another, &diff));
+
+ cl_git_pass(git_diff_print_patch(diff, NULL, check_removal_cb));
+
+ git_diff_list_free(diff);
+
+ git_tree_free(another);
+ git_tree_free(one);
+}