diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2015-01-14 18:47:00 -0500 |
---|---|---|
committer | Edward Thomson <ethomson@microsoft.com> | 2015-01-20 17:13:31 -0600 |
commit | e74340b0001247681bf0fe43f73622e87b52ccae (patch) | |
tree | 1e00d71efa79ac71a43851314475e27ac33c737b /src/fileops.c | |
parent | c2dee0fcb0d247ecb3a48709ae1c57d1b935d2ae (diff) | |
download | libgit2-e74340b0001247681bf0fe43f73622e87b52ccae.tar.gz |
checkout: remove files before writing new ones
On case insensitive filesystems, we may have files in the working
directory that case fold to a name we want to write. Remove those
files (by default) so that we will not end up with a filename that
has the unexpected case.
Diffstat (limited to 'src/fileops.c')
-rw-r--r-- | src/fileops.c | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/src/fileops.c b/src/fileops.c index ea0f4e1f7..2ee9535be 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -279,6 +279,48 @@ void git_futils_mmap_free(git_map *out) p_munmap(out); } +GIT_INLINE(int) validate_existing( + const char *make_path, + struct stat *st, + mode_t mode, + uint32_t flags, + struct git_futils_mkdir_perfdata *perfdata) +{ + if ((S_ISREG(st->st_mode) && (flags & GIT_MKDIR_REMOVE_FILES)) || + (S_ISLNK(st->st_mode) && (flags & GIT_MKDIR_REMOVE_SYMLINKS))) { + if (p_unlink(make_path) < 0) { + giterr_set(GITERR_OS, "Failed to remove %s '%s'", + S_ISLNK(st->st_mode) ? "symlink" : "file", make_path); + return GIT_EEXISTS; + } + + perfdata->mkdir_calls++; + + if (p_mkdir(make_path, mode) < 0) { + giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path); + return GIT_EEXISTS; + } + } + + else if (S_ISLNK(st->st_mode)) { + /* Re-stat the target, make sure it's a directory */ + perfdata->stat_calls++; + + if (p_stat(make_path, st) < 0) { + giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path); + return GIT_EEXISTS; + } + } + + else if (!S_ISDIR(st->st_mode)) { + giterr_set(GITERR_FILESYSTEM, + "Failed to make directory '%s': directory exists", make_path); + return GIT_EEXISTS; + } + + return 0; +} + int git_futils_mkdir_withperf( const char *path, const char *base, @@ -373,22 +415,9 @@ int git_futils_mkdir_withperf( goto done; } - if (S_ISLNK(st.st_mode)) { - perfdata->stat_calls++; - - /* Re-stat the target, make sure it's a directory */ - if (p_stat(make_path.ptr, &st) < 0) { - giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr); - error = GIT_EEXISTS; + if ((error = validate_existing( + make_path.ptr, &st, mode, flags, perfdata)) < 0) goto done; - } - } - - if (!S_ISDIR(st.st_mode)) { - giterr_set(GITERR_FILESYSTEM, "Failed to make directory '%s': directory exists", make_path.ptr); - error = GIT_EEXISTS; - goto done; - } } /* chmod if requested and necessary */ @@ -400,7 +429,8 @@ int git_futils_mkdir_withperf( if ((error = p_chmod(make_path.ptr, mode)) < 0 && lastch == '\0') { - giterr_set(GITERR_OS, "Failed to set permissions on '%s'", make_path.ptr); + giterr_set(GITERR_OS, "Failed to set permissions on '%s'", + make_path.ptr); goto done; } } @@ -414,7 +444,8 @@ int git_futils_mkdir_withperf( perfdata->stat_calls++; if (p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode)) { - giterr_set(GITERR_OS, "Path is not a directory '%s'", make_path.ptr); + giterr_set(GITERR_OS, "Path is not a directory '%s'", + make_path.ptr); error = GIT_ENOTFOUND; } } |