mirror of
https://git.proxmox.com/git/libgit2
synced 2026-01-04 21:21:02 +00:00
Merge pull request #3032 from jfultz/index-file-modes
Fix git_checkout_tree() to do index filemodes correctly on Windows.
This commit is contained in:
commit
27fa7477b0
18
src/index.c
18
src/index.c
@ -987,9 +987,10 @@ static int index_no_dups(void **old, void *new)
|
||||
* it, then it will return an error **and also free the entry**. When
|
||||
* it replaces an existing entry, it will update the entry_ptr with the
|
||||
* actual entry in the index (and free the passed in one).
|
||||
* trust_mode is whether we trust the mode in entry_ptr.
|
||||
*/
|
||||
static int index_insert(
|
||||
git_index *index, git_index_entry **entry_ptr, int replace)
|
||||
git_index *index, git_index_entry **entry_ptr, int replace, bool trust_mode)
|
||||
{
|
||||
int error = 0;
|
||||
size_t path_length, position;
|
||||
@ -1021,7 +1022,10 @@ static int index_insert(
|
||||
&position, index, entry->path, 0, GIT_IDXENTRY_STAGE(entry), false)) {
|
||||
existing = index->entries.contents[position];
|
||||
/* update filemode to existing values if stat is not trusted */
|
||||
entry->mode = index_merge_mode(index, existing, entry->mode);
|
||||
if (trust_mode)
|
||||
entry->mode = git_index__create_mode(entry->mode);
|
||||
else
|
||||
entry->mode = index_merge_mode(index, existing, entry->mode);
|
||||
}
|
||||
|
||||
/* look for tree / blob name collisions, removing conflicts if requested */
|
||||
@ -1122,7 +1126,7 @@ int git_index_add_frombuffer(
|
||||
git_oid_cpy(&entry->id, &id);
|
||||
entry->file_size = len;
|
||||
|
||||
if ((error = index_insert(index, &entry, 1)) < 0)
|
||||
if ((error = index_insert(index, &entry, 1, true)) < 0)
|
||||
return error;
|
||||
|
||||
/* Adding implies conflict was resolved, move conflict entries to REUC */
|
||||
@ -1142,7 +1146,7 @@ int git_index_add_bypath(git_index *index, const char *path)
|
||||
assert(index && path);
|
||||
|
||||
if ((ret = index_entry_init(&entry, index, path)) < 0 ||
|
||||
(ret = index_insert(index, &entry, 1)) < 0)
|
||||
(ret = index_insert(index, &entry, 1, false)) < 0)
|
||||
return ret;
|
||||
|
||||
/* Adding implies conflict was resolved, move conflict entries to REUC */
|
||||
@ -1182,7 +1186,7 @@ int git_index_add(git_index *index, const git_index_entry *source_entry)
|
||||
}
|
||||
|
||||
if ((ret = index_entry_dup(&entry, INDEX_OWNER(index), source_entry)) < 0 ||
|
||||
(ret = index_insert(index, &entry, 1)) < 0)
|
||||
(ret = index_insert(index, &entry, 1, true)) < 0)
|
||||
return ret;
|
||||
|
||||
git_tree_cache_invalidate_path(index->tree, entry->path);
|
||||
@ -1313,7 +1317,7 @@ int git_index_conflict_add(git_index *index,
|
||||
/* Make sure stage is correct */
|
||||
GIT_IDXENTRY_STAGE_SET(entries[i], i + 1);
|
||||
|
||||
if ((ret = index_insert(index, &entries[i], 1)) < 0)
|
||||
if ((ret = index_insert(index, &entries[i], 1, true)) < 0)
|
||||
goto on_error;
|
||||
|
||||
entries[i] = NULL; /* don't free if later entry fails */
|
||||
@ -2537,7 +2541,7 @@ int git_index_add_all(
|
||||
entry->id = blobid;
|
||||
|
||||
/* add working directory item to index */
|
||||
if ((error = index_insert(index, &entry, 1)) < 0)
|
||||
if ((error = index_insert(index, &entry, 1, false)) < 0)
|
||||
break;
|
||||
|
||||
git_tree_cache_invalidate_path(index->tree, wd->path);
|
||||
|
||||
@ -925,18 +925,43 @@ void test_checkout_tree__filemode_preserved_in_index(void)
|
||||
git_index *index;
|
||||
const git_index_entry *entry;
|
||||
|
||||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||||
|
||||
cl_git_pass(git_repository_index(&index, g_repo));
|
||||
|
||||
/* test a freshly added executable */
|
||||
cl_git_pass(git_oid_fromstr(&executable_oid, "afe4393b2b2a965f06acf2ca9658eaa01e0cd6b6"));
|
||||
cl_git_pass(git_commit_lookup(&commit, g_repo, &executable_oid));
|
||||
|
||||
opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
||||
|
||||
cl_git_pass(git_checkout_tree(g_repo, (const git_object *)commit, &opts));
|
||||
cl_assert(entry = git_index_get_bypath(index, "executable.txt", 0));
|
||||
cl_assert_equal_i(0100755, entry->mode);
|
||||
|
||||
git_commit_free(commit);
|
||||
|
||||
|
||||
/* Now start with a commit which has a text file */
|
||||
cl_git_pass(git_oid_fromstr(&executable_oid, "cf80f8de9f1185bf3a05f993f6121880dd0cfbc9"));
|
||||
cl_git_pass(git_commit_lookup(&commit, g_repo, &executable_oid));
|
||||
|
||||
cl_git_pass(git_checkout_tree(g_repo, (const git_object *)commit, &opts));
|
||||
cl_assert(entry = git_index_get_bypath(index, "a/b.txt", 0));
|
||||
cl_assert_equal_i(0100644, entry->mode);
|
||||
|
||||
git_commit_free(commit);
|
||||
|
||||
|
||||
/* And then check out to a commit which converts the text file to an executable */
|
||||
cl_git_pass(git_oid_fromstr(&executable_oid, "144344043ba4d4a405da03de3844aa829ae8be0e"));
|
||||
cl_git_pass(git_commit_lookup(&commit, g_repo, &executable_oid));
|
||||
|
||||
cl_git_pass(git_checkout_tree(g_repo, (const git_object *)commit, &opts));
|
||||
cl_assert(entry = git_index_get_bypath(index, "a/b.txt", 0));
|
||||
cl_assert_equal_i(0100755, entry->mode);
|
||||
|
||||
git_commit_free(commit);
|
||||
|
||||
|
||||
git_index_free(index);
|
||||
}
|
||||
|
||||
|
||||
@ -153,6 +153,85 @@ void test_index_filemodes__trusted(void)
|
||||
git_index_free(index);
|
||||
}
|
||||
|
||||
#define add_entry_and_check_mode(I,FF,X) add_entry_and_check_mode_(I,FF,X,__FILE__,__LINE__)
|
||||
|
||||
static void add_entry_and_check_mode_(
|
||||
git_index *index, bool from_file, git_filemode_t mode,
|
||||
const char *file, int line)
|
||||
{
|
||||
size_t pos;
|
||||
const git_index_entry* entry;
|
||||
git_index_entry new_entry;
|
||||
|
||||
/* If old_filename exists, we copy that to the new file, and test
|
||||
* git_index_add(), otherwise create a new entry testing git_index_add_frombuffer
|
||||
*/
|
||||
if (from_file)
|
||||
{
|
||||
clar__assert(!git_index_find(&pos, index, "exec_off"),
|
||||
file, line, "Cannot find original index entry", NULL, 1);
|
||||
|
||||
entry = git_index_get_byindex(index, pos);
|
||||
|
||||
memcpy(&new_entry, entry, sizeof(new_entry));
|
||||
}
|
||||
else
|
||||
memset(&new_entry, 0x0, sizeof(git_index_entry));
|
||||
|
||||
new_entry.path = "filemodes/explicit_test";
|
||||
new_entry.mode = mode;
|
||||
|
||||
if (from_file)
|
||||
{
|
||||
clar__assert(!git_index_add(index, &new_entry),
|
||||
file, line, "Cannot add index entry", NULL, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *content = "hey there\n";
|
||||
clar__assert(!git_index_add_frombuffer(index, &new_entry, content, strlen(content)),
|
||||
file, line, "Cannot add index entry from buffer", NULL, 1);
|
||||
}
|
||||
|
||||
clar__assert(!git_index_find(&pos, index, "filemodes/explicit_test"),
|
||||
file, line, "Cannot find new index entry", NULL, 1);
|
||||
|
||||
entry = git_index_get_byindex(index, pos);
|
||||
|
||||
clar__assert_equal(file, line, "Expected mode does not match index",
|
||||
1, "%07o", (unsigned int)entry->mode, (unsigned int)mode);
|
||||
}
|
||||
|
||||
void test_index_filemodes__explicit(void)
|
||||
{
|
||||
git_index *index;
|
||||
|
||||
/* These tests should run and work everywhere, as the filemode is
|
||||
* given explicitly to git_index_add or git_index_add_frombuffer
|
||||
*/
|
||||
cl_repo_set_bool(g_repo, "core.filemode", false);
|
||||
|
||||
cl_git_pass(git_repository_index(&index, g_repo));
|
||||
|
||||
/* Each of these tests keeps overwriting the same file in the index. */
|
||||
/* 1 - add new 0644 entry */
|
||||
add_entry_and_check_mode(index, true, GIT_FILEMODE_BLOB);
|
||||
|
||||
/* 2 - add 0755 entry over existing 0644 */
|
||||
add_entry_and_check_mode(index, true, GIT_FILEMODE_BLOB_EXECUTABLE);
|
||||
|
||||
/* 3 - add 0644 entry over existing 0755 */
|
||||
add_entry_and_check_mode(index, true, GIT_FILEMODE_BLOB);
|
||||
|
||||
/* 4 - add 0755 buffer entry over existing 0644 */
|
||||
add_entry_and_check_mode(index, false, GIT_FILEMODE_BLOB_EXECUTABLE);
|
||||
|
||||
/* 5 - add 0644 buffer entry over existing 0755 */
|
||||
add_entry_and_check_mode(index, false, GIT_FILEMODE_BLOB);
|
||||
|
||||
git_index_free(index);
|
||||
}
|
||||
|
||||
void test_index_filemodes__invalid(void)
|
||||
{
|
||||
git_index *index;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user