mirror of
https://git.proxmox.com/git/libgit2
synced 2025-08-06 14:33:18 +00:00
Add more diff rename detection tests
This adds a bunch more rename detection tests including checks vs the working directory, the new exact match options, some more whitespace variants, etc. This also adds a git_futils_writebuffer helper function and uses it in checkout. This is mainly added because I wanted an easy way to write out a git_buf to disk inside my test code.
This commit is contained in:
parent
9be5be47fb
commit
4742148d54
@ -676,33 +676,26 @@ static int buffer_to_file(
|
|||||||
int file_open_flags,
|
int file_open_flags,
|
||||||
mode_t file_mode)
|
mode_t file_mode)
|
||||||
{
|
{
|
||||||
int fd, error;
|
int error;
|
||||||
|
|
||||||
if ((error = git_futils_mkpath2file(path, dir_mode)) < 0)
|
if ((error = git_futils_mkpath2file(path, dir_mode)) < 0)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if ((fd = p_open(path, file_open_flags, file_mode)) < 0) {
|
if ((error = git_futils_writebuffer(
|
||||||
giterr_set(GITERR_OS, "Could not open '%s' for writing", path);
|
buffer, path, file_open_flags, file_mode)) < 0)
|
||||||
return fd;
|
return error;
|
||||||
|
|
||||||
|
if (st != NULL && (error = p_stat(path, st)) < 0) {
|
||||||
|
giterr_set(GITERR_OS, "Error while statting '%s'", path);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = p_write(fd, git_buf_cstr(buffer), git_buf_len(buffer))) < 0) {
|
if ((file_mode & 0100) != 0 && (error = p_chmod(path, file_mode)) < 0) {
|
||||||
giterr_set(GITERR_OS, "Could not write to '%s'", path);
|
|
||||||
(void)p_close(fd);
|
|
||||||
} else {
|
|
||||||
if ((error = p_close(fd)) < 0)
|
|
||||||
giterr_set(GITERR_OS, "Error while closing '%s'", path);
|
|
||||||
|
|
||||||
if ((error = p_stat(path, st)) < 0)
|
|
||||||
giterr_set(GITERR_OS, "Error while statting '%s'", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!error &&
|
|
||||||
(file_mode & 0100) != 0 &&
|
|
||||||
(error = p_chmod(path, file_mode)) < 0)
|
|
||||||
giterr_set(GITERR_OS, "Failed to set permissions on '%s'", path);
|
giterr_set(GITERR_OS, "Failed to set permissions on '%s'", path);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
return error;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int blob_content_to_file(
|
static int blob_content_to_file(
|
||||||
|
@ -202,6 +202,32 @@ int git_futils_readbuffer(git_buf *buf, const char *path)
|
|||||||
return git_futils_readbuffer_updated(buf, path, NULL, NULL, NULL);
|
return git_futils_readbuffer_updated(buf, path, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_futils_writebuffer(
|
||||||
|
const git_buf *buf, const char *path, int flags, mode_t mode)
|
||||||
|
{
|
||||||
|
int fd, error = 0;
|
||||||
|
|
||||||
|
if (flags <= 0)
|
||||||
|
flags = O_CREAT | O_TRUNC | O_WRONLY;
|
||||||
|
if (!mode)
|
||||||
|
mode = GIT_FILEMODE_BLOB;
|
||||||
|
|
||||||
|
if ((fd = p_open(path, flags, mode)) < 0) {
|
||||||
|
giterr_set(GITERR_OS, "Could not open '%s' for writing", path);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((error = p_close(fd)) < 0)
|
||||||
|
giterr_set(GITERR_OS, "Error while closing '%s'", path);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmode)
|
int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmode)
|
||||||
{
|
{
|
||||||
if (git_futils_mkpath2file(to, dirmode) < 0)
|
if (git_futils_mkpath2file(to, dirmode) < 0)
|
||||||
|
@ -22,6 +22,9 @@ extern int git_futils_readbuffer_updated(
|
|||||||
git_buf *obj, const char *path, time_t *mtime, size_t *size, int *updated);
|
git_buf *obj, const char *path, time_t *mtime, size_t *size, int *updated);
|
||||||
extern int git_futils_readbuffer_fd(git_buf *obj, git_file fd, size_t len);
|
extern int git_futils_readbuffer_fd(git_buf *obj, git_file fd, size_t len);
|
||||||
|
|
||||||
|
extern int git_futils_writebuffer(
|
||||||
|
const git_buf *buf, const char *path, int open_flags, mode_t mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File utils
|
* File utils
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "clar_libgit2.h"
|
#include "clar_libgit2.h"
|
||||||
#include "diff_helpers.h"
|
#include "diff_helpers.h"
|
||||||
|
#include "buf_text.h"
|
||||||
|
|
||||||
static git_repository *g_repo = NULL;
|
static git_repository *g_repo = NULL;
|
||||||
|
|
||||||
@ -388,9 +389,152 @@ void test_diff_rename__handles_small_files(void)
|
|||||||
|
|
||||||
void test_diff_rename__working_directory_changes(void)
|
void test_diff_rename__working_directory_changes(void)
|
||||||
{
|
{
|
||||||
/* let's rewrite some files in the working directory on demand */
|
const char *sha0 = "2bc7f351d20b53f1c72c16c4b036e491c478c49a";
|
||||||
|
const char *blobsha = "66311f5cfbe7836c27510a3ba2f43e282e2c8bba";
|
||||||
|
git_oid id;
|
||||||
|
git_tree *tree;
|
||||||
|
git_blob *blob;
|
||||||
|
git_diff_list *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;;
|
||||||
|
|
||||||
/* and with / without CRLF changes */
|
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(3, exp.file_status[GIT_DELTA_UNTRACKED]);
|
||||||
|
cl_assert_equal_i(2, exp.file_status[GIT_DELTA_DELETED]);
|
||||||
|
|
||||||
|
/* 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(3, exp.file_status[GIT_DELTA_RENAMED]);
|
||||||
|
cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]);
|
||||||
|
|
||||||
|
git_diff_list_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(3, exp.file_status[GIT_DELTA_RENAMED]);
|
||||||
|
cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]);
|
||||||
|
|
||||||
|
git_diff_list_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;
|
||||||
|
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_list_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_list_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), 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));
|
||||||
|
|
||||||
|
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(2, exp.file_status[GIT_DELTA_RENAMED]);
|
||||||
|
cl_assert_equal_i(2, exp.file_status[GIT_DELTA_UNTRACKED]);
|
||||||
|
|
||||||
|
git_diff_list_free(diff);
|
||||||
|
|
||||||
|
git_tree_free(tree);
|
||||||
|
git_buf_free(&content);
|
||||||
|
git_buf_free(&old_content);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_diff_rename__patch(void)
|
void test_diff_rename__patch(void)
|
||||||
|
Loading…
Reference in New Issue
Block a user