Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9d5efab

Browse files
committed
Merge pull request libgit2#3254 from ethomson/diff-binary-patch
Handle binary DIFFABLEness properly
2 parents c2f274c + 5407709 commit 9d5efab

File tree

3 files changed

+69
-12
lines changed

3 files changed

+69
-12
lines changed

src/diff_patch.c

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,35 @@ GIT_INLINE(bool) should_skip_binary(git_patch *patch, git_diff_file *file)
121121
return (file->flags & GIT_DIFF_FLAG_BINARY) != 0;
122122
}
123123

124+
static bool diff_patch_diffable(git_patch *patch)
125+
{
126+
size_t olen, nlen;
127+
128+
if (patch->delta->status == GIT_DELTA_UNMODIFIED)
129+
return false;
130+
131+
/* if we've determined this to be binary (and we are not showing binary
132+
* data) then we have skipped loading the map data. instead, query the
133+
* file data itself.
134+
*/
135+
if ((patch->delta->flags & GIT_DIFF_FLAG_BINARY) != 0 &&
136+
(patch->diff_opts.flags & GIT_DIFF_SHOW_BINARY) == 0) {
137+
olen = (size_t)patch->ofile.file->size;
138+
nlen = (size_t)patch->nfile.file->size;
139+
} else {
140+
olen = patch->ofile.map.len;
141+
nlen = patch->nfile.map.len;
142+
}
143+
144+
/* if both sides are empty, files are identical */
145+
if (!olen && !nlen)
146+
return false;
147+
148+
/* otherwise, check the file sizes and the oid */
149+
return (olen != nlen ||
150+
!git_oid_equal(&patch->ofile.file->id, &patch->nfile.file->id));
151+
}
152+
124153
static int diff_patch_load(git_patch *patch, git_diff_output *output)
125154
{
126155
int error = 0;
@@ -186,18 +215,7 @@ static int diff_patch_load(git_patch *patch, git_diff_output *output)
186215
diff_patch_update_binary(patch);
187216

188217
if (!error) {
189-
bool skip_binary =
190-
(patch->delta->flags & GIT_DIFF_FLAG_BINARY) != 0 &&
191-
(patch->diff_opts.flags & GIT_DIFF_SHOW_BINARY) == 0;
192-
193-
/* patch is diffable only for non-binary, modified files where
194-
* at least one side has data and the data actually changed
195-
*/
196-
if (!skip_binary &&
197-
patch->delta->status != GIT_DELTA_UNMODIFIED &&
198-
(patch->ofile.map.len || patch->nfile.map.len) &&
199-
(patch->ofile.map.len != patch->nfile.map.len ||
200-
!git_oid_equal(&patch->ofile.file->id, &patch->nfile.file->id)))
218+
if (diff_patch_diffable(patch))
201219
patch->flags |= GIT_DIFF_PATCH_DIFFABLE;
202220

203221
patch->flags |= GIT_DIFF_PATCH_LOADED;

src/diff_patch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ enum {
2424
GIT_DIFF_PATCH_ALLOCATED = (1 << 0),
2525
GIT_DIFF_PATCH_INITIALIZED = (1 << 1),
2626
GIT_DIFF_PATCH_LOADED = (1 << 2),
27+
/* the two sides are different */
2728
GIT_DIFF_PATCH_DIFFABLE = (1 << 3),
29+
/* the difference between the two sides has been computed */
2830
GIT_DIFF_PATCH_DIFFED = (1 << 4),
2931
GIT_DIFF_PATCH_FLATTENED = (1 << 5),
3032
};

tests/diff/binary.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "clar_libgit2.h"
22

3+
#include "git2/sys/diff.h"
4+
35
#include "buffer.h"
46
#include "filebuf.h"
57

@@ -49,6 +51,11 @@ void test_patch(
4951

5052
cl_assert_equal_s(expected, actual.ptr);
5153

54+
git_buf_clear(&actual);
55+
cl_git_pass(git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, git_diff_print_callback__to_buf, &actual));
56+
57+
cl_assert_equal_s(expected, actual.ptr);
58+
5259
git_buf_free(&actual);
5360
git_patch_free(patch);
5461
git_diff_free(diff);
@@ -262,6 +269,36 @@ void test_diff_binary__delta_append(void)
262269
git_index_free(index);
263270
}
264271

272+
void test_diff_binary__empty_for_no_diff(void)
273+
{
274+
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
275+
git_oid id;
276+
git_commit *commit;
277+
git_tree *tree;
278+
git_diff *diff;
279+
git_buf actual = GIT_BUF_INIT;
280+
const char *expected = "";
281+
282+
opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
283+
opts.id_abbrev = GIT_OID_HEXSZ;
284+
285+
repo = cl_git_sandbox_init("renames");
286+
287+
cl_git_pass(git_oid_fromstr(&id, "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13"));
288+
cl_git_pass(git_commit_lookup(&commit, repo, &id));
289+
cl_git_pass(git_commit_tree(&tree, commit));
290+
291+
cl_git_pass(git_diff_tree_to_tree(&diff, repo, tree, tree, &opts));
292+
cl_git_pass(git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, git_diff_print_callback__to_buf, &actual));
293+
294+
cl_assert_equal_s("", actual.ptr);
295+
296+
git_buf_free(&actual);
297+
git_diff_free(diff);
298+
git_commit_free(commit);
299+
git_tree_free(tree);
300+
}
301+
265302
void test_diff_binary__index_to_workdir(void)
266303
{
267304
git_index *index;

0 commit comments

Comments
 (0)