Commit b0b2dd5e by Vicent Martí

Merge pull request #475 from carlosmn/perms

Fix Windows permissions problems
parents 38068dc1 657a3951
......@@ -278,7 +278,7 @@ int git_filebuf_commit(git_filebuf *file, mode_t mode)
goto cleanup;
}
error = git_futils_mv_atomic(file->path_lock, file->path_original);
error = p_rename(file->path_lock, file->path_original);
cleanup:
git_filebuf_cleanup(file);
......
......@@ -8,29 +8,6 @@
#include "fileops.h"
#include <ctype.h>
int git_futils_mv_atomic(const char *from, const char *to)
{
#ifdef GIT_WIN32
/*
* Win32 POSIX compilance my ass. If the destination
* file exists, the `rename` call fails. This is as
* close as it gets with the Win32 API.
*/
return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR;
#else
/* Don't even try this on Win32 */
if (!link(from, to)) {
p_unlink(from);
return GIT_SUCCESS;
}
if (!rename(from, to))
return GIT_SUCCESS;
return GIT_ERROR;
#endif
}
int git_futils_mkpath2file(const char *file_path, const mode_t mode)
{
int error = GIT_SUCCESS;
......@@ -216,7 +193,7 @@ int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmod
if (git_futils_mkpath2file(to, dirmode) < GIT_SUCCESS)
return GIT_EOSERR; /* The callee already takes care of setting the correct error message. */
return git_futils_mv_atomic(from, to); /* The callee already takes care of setting the correct error message. */
return p_rename(from, to); /* The callee already takes care of setting the correct error message. */
}
int git_futils_mmap_ro(git_map *out, git_file fd, git_off_t begin, size_t len)
......
......@@ -39,6 +39,20 @@ int p_getcwd(char *buffer_out, size_t size)
return GIT_SUCCESS;
}
int p_rename(const char *from, const char *to)
{
if (!link(from, to)) {
p_unlink(from);
return GIT_SUCCESS;
}
if (!rename(from, to))
return GIT_SUCCESS;
return GIT_ERROR;
}
#endif
int p_read(git_file fd, void *buf, size_t cnt)
......
......@@ -45,6 +45,7 @@ extern int p_write(git_file fd, const void *buf, size_t cnt);
extern int p_open(const char *path, int flags);
extern int p_creat(const char *path, mode_t mode);
extern int p_getcwd(char *buffer_out, size_t size);
extern int p_rename(const char *from, const char *to);
#ifndef GIT_WIN32
......
......@@ -16,6 +16,8 @@
#define MAX_NESTING_LEVEL 5
#define GIT_PACKED_REFS_FILE_MODE 0644
enum {
GIT_PACKREF_HAS_PEEL = 1,
GIT_PACKREF_WAS_LOOSE = 2
......@@ -757,7 +759,7 @@ static int packed_write(git_repository *repo)
total_refs = repo->references.packfile->key_count;
if ((error =
git_vector_init(&packing_list, total_refs, packed_sort)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to write packed reference");
return git__rethrow(error, "Failed to init packed refernces list");
/* Load all the packfile into a vector */
{
......@@ -776,14 +778,14 @@ static int packed_write(git_repository *repo)
/* Now we can open the file! */
git_path_join(pack_file_path, repo->path_repository, GIT_PACKEDREFS_FILE);
if ((error = git_filebuf_open(&pack_file, pack_file_path, 0)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to write packed reference");
return git__rethrow(error, "Failed to write open packed references file");
/* Packfiles have a header... apparently
* This is in fact not required, but we might as well print it
* just for kicks */
if ((error =
git_filebuf_printf(&pack_file, "%s\n", GIT_PACKEDREFS_HEADER)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to write packed reference");
return git__rethrow(error, "Failed to write packed references file header");
for (i = 0; i < packing_list.length; ++i) {
struct packref *ref = (struct packref *)git_vector_get(&packing_list, i);
......@@ -802,7 +804,7 @@ cleanup:
/* if we've written all the references properly, we can commit
* the packfile to make the changes effective */
if (error == GIT_SUCCESS) {
error = git_filebuf_commit(&pack_file, GIT_PACK_FILE_MODE);
error = git_filebuf_commit(&pack_file, GIT_PACKED_REFS_FILE_MODE);
/* when and only when the packfile has been properly written,
* we can go ahead and remove the loose refs */
......@@ -821,7 +823,7 @@ cleanup:
return error == GIT_SUCCESS ?
GIT_SUCCESS :
git__rethrow(error, "Failed to write packed reference");
git__rethrow(error, "Failed to write packed references file");
}
static int _reference_available_cb(const char *ref, void *data)
......
......@@ -48,5 +48,6 @@ extern int p_fsync(int fd);
extern int p_open(const char *path, int flags);
extern int p_creat(const char *path, mode_t mode);
extern int p_getcwd(char *buffer_out, size_t size);
extern int p_rename(const char *from, const char *to);
#endif
......@@ -388,3 +388,17 @@ int p_access(const char* path, mode_t mode)
return ret;
}
extern int p_rename(const char *from, const char *to)
{
wchar_t *wfrom = gitwin_to_utf16(from);
wchar_t *wto = gitwin_to_utf16(to);
int ret;
ret = MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR;
git__free(wfrom);
git__free(wto);
return ret;
}
......@@ -71,7 +71,7 @@ void test_status_worktree__initialize(void)
* inside the fixtures folder in our libgit2 repo.
*/
cl_git_pass(
git_futils_mv_atomic("status/.gitted", "status/.git")
p_rename("status/.gitted", "status/.git")
);
/*
......
......@@ -136,7 +136,7 @@ BEGIN_TEST(statuscb0, "test retrieving status for worktree of repository")
struct status_entry_counts counts;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
must_pass(git_futils_mv_atomic(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
memset(&counts, 0x0, sizeof(struct status_entry_counts));
......@@ -223,7 +223,7 @@ BEGIN_TEST(statuscb2, "test retrieving status for a purged worktree of an valid
struct status_entry_counts counts;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
must_pass(git_futils_mv_atomic(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
/* Purging the working */
......@@ -309,12 +309,12 @@ BEGIN_TEST(statuscb3, "test retrieving status for a worktree where a file and a
struct status_entry_counts counts;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
must_pass(git_futils_mv_atomic(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
must_pass(git_futils_mv_atomic(TEMP_REPO_FOLDER "current_file", TEMP_REPO_FOLDER "swap"));
must_pass(git_futils_mv_atomic(TEMP_REPO_FOLDER "subdir", TEMP_REPO_FOLDER "current_file"));
must_pass(git_futils_mv_atomic(TEMP_REPO_FOLDER "swap", TEMP_REPO_FOLDER "subdir"));
must_pass(p_rename(TEMP_REPO_FOLDER "current_file", TEMP_REPO_FOLDER "swap"));
must_pass(p_rename(TEMP_REPO_FOLDER "subdir", TEMP_REPO_FOLDER "current_file"));
must_pass(p_rename(TEMP_REPO_FOLDER "swap", TEMP_REPO_FOLDER "subdir"));
must_pass(file_create(TEMP_REPO_FOLDER ".HEADER", "dummy"));
must_pass(file_create(TEMP_REPO_FOLDER "42-is-not-prime.sigh", "dummy"));
......@@ -341,7 +341,7 @@ BEGIN_TEST(singlestatus0, "test retrieving status for single file")
int i;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
must_pass(git_futils_mv_atomic(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
for (i = 0; i < ENTRY_COUNT0; ++i) {
......@@ -360,7 +360,7 @@ BEGIN_TEST(singlestatus1, "test retrieving status for nonexistent file")
int error;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
must_pass(git_futils_mv_atomic(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
// "nonexistent" does not exist in HEAD, Index or the worktree
......@@ -421,7 +421,7 @@ BEGIN_TEST(singlestatus4, "can't determine the status for a folder")
int error;
must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER));
must_pass(git_futils_mv_atomic(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(p_rename(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER));
must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER));
error = git_status_file(&status_flags, repo, "subdir");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment