summaryrefslogtreecommitdiff
path: root/src/fileops.c
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@microsoft.com>2015-02-03 01:46:01 -0500
committerEdward Thomson <ethomson@edwardthomson.com>2015-02-04 14:15:13 +0000
commit500ec5431564d9167985a02909823e1286136d5b (patch)
treea1bf00580026a74fe044567b8aec10e26be2a347 /src/fileops.c
parentf58cc280c9ddeff6fd85f56e70073c3ed4fb0650 (diff)
downloadlibgit2-500ec5431564d9167985a02909823e1286136d5b.tar.gz
checkout: hold seen dir paths in a map
Diffstat (limited to 'src/fileops.c')
-rw-r--r--src/fileops.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/src/fileops.c b/src/fileops.c
index 2ee9535be..ff2acfc2b 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -7,11 +7,14 @@
#include "common.h"
#include "fileops.h"
#include "global.h"
+#include "strmap.h"
#include <ctype.h>
#if GIT_WIN32
#include "win32/findfile.h"
#endif
+GIT__USE_STRMAP;
+
int git_futils_mkpath2file(const char *file_path, const mode_t mode)
{
return git_futils_mkdir(
@@ -321,12 +324,12 @@ GIT_INLINE(int) validate_existing(
return 0;
}
-int git_futils_mkdir_withperf(
+int git_futils_mkdir_ext(
const char *path,
const char *base,
mode_t mode,
uint32_t flags,
- struct git_futils_mkdir_perfdata *perfdata)
+ struct git_futils_mkdir_options *opts)
{
int error = -1;
git_buf make_path = GIT_BUF_INIT;
@@ -394,11 +397,14 @@ int git_futils_mkdir_withperf(
*tail = '\0';
st.st_mode = 0;
+ if (opts->dir_map && git_strmap_exists(opts->dir_map, make_path.ptr))
+ continue;
+
/* See what's going on with this path component */
- perfdata->stat_calls++;
+ opts->perfdata.stat_calls++;
if (p_lstat(make_path.ptr, &st) < 0) {
- perfdata->mkdir_calls++;
+ opts->perfdata.mkdir_calls++;
if (errno != ENOENT || p_mkdir(make_path.ptr, mode) < 0) {
giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr);
@@ -416,7 +422,7 @@ int git_futils_mkdir_withperf(
}
if ((error = validate_existing(
- make_path.ptr, &st, mode, flags, perfdata)) < 0)
+ make_path.ptr, &st, mode, flags, &opts->perfdata)) < 0)
goto done;
}
@@ -425,7 +431,7 @@ int git_futils_mkdir_withperf(
(lastch == '\0' && (flags & GIT_MKDIR_CHMOD) != 0)) &&
st.st_mode != mode) {
- perfdata->chmod_calls++;
+ opts->perfdata.chmod_calls++;
if ((error = p_chmod(make_path.ptr, mode)) < 0 &&
lastch == '\0') {
@@ -434,6 +440,17 @@ int git_futils_mkdir_withperf(
goto done;
}
}
+
+ if (opts->dir_map && opts->pool) {
+ char *cache_path = git_pool_malloc(opts->pool, make_path.size + 1);
+ GITERR_CHECK_ALLOC(cache_path);
+
+ memcpy(cache_path, make_path.ptr, make_path.size + 1);
+
+ git_strmap_insert(opts->dir_map, cache_path, cache_path, error);
+ if (error < 0)
+ goto done;
+ }
}
error = 0;
@@ -441,7 +458,7 @@ int git_futils_mkdir_withperf(
/* check that full path really is a directory if requested & needed */
if ((flags & GIT_MKDIR_VERIFY_DIR) != 0 &&
lastch != '\0') {
- perfdata->stat_calls++;
+ opts->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'",
@@ -461,8 +478,8 @@ int git_futils_mkdir(
mode_t mode,
uint32_t flags)
{
- struct git_futils_mkdir_perfdata perfdata = {0};
- return git_futils_mkdir_withperf(path, base, mode, flags, &perfdata);
+ struct git_futils_mkdir_options options = {0};
+ return git_futils_mkdir_ext(path, base, mode, flags, &options);
}
int git_futils_mkdir_r(const char *path, const char *base, const mode_t mode)