diff options
author | Edward Thomson <ethomson@microsoft.com> | 2015-01-13 11:18:02 -0600 |
---|---|---|
committer | Edward Thomson <ethomson@microsoft.com> | 2015-01-20 17:12:46 -0600 |
commit | fe598f0903012e361eca53c4cb65c27e4e8dfac9 (patch) | |
tree | c14afd12de1992426911040015cae5457ea0187b | |
parent | 1fbfcdfcd0f3b87e95cea15b3c90808ccd5f9a79 (diff) | |
download | libgit2-fe598f0903012e361eca53c4cb65c27e4e8dfac9.tar.gz |
mkdir: walk up tree to mkdir
Walk up the tree to mkdir, which is less immediately efficient,
but allows us to look at intermediate directories that may need
attention.
-rw-r--r-- | include/git2/errors.h | 1 | ||||
-rw-r--r-- | src/fileops.c | 36 |
2 files changed, 26 insertions, 11 deletions
diff --git a/include/git2/errors.h b/include/git2/errors.h index 9b4cc7c00..ef4fabb7d 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -93,6 +93,7 @@ typedef enum { GITERR_CHERRYPICK, GITERR_DESCRIBE, GITERR_REBASE, + GITERR_FILESYSTEM } git_error_t; /** diff --git a/src/fileops.c b/src/fileops.c index 926813f5e..ea0f4e1f7 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -352,26 +352,40 @@ int git_futils_mkdir_withperf( *tail = '\0'; st.st_mode = 0; - /* make directory */ - perfdata->mkdir_calls++; + /* See what's going on with this path component */ + perfdata->stat_calls++; + + if (p_lstat(make_path.ptr, &st) < 0) { + perfdata->mkdir_calls++; - if (p_mkdir(make_path.ptr, mode) < 0) { - int tmp_errno = giterr_system_last(); + if (errno != ENOENT || p_mkdir(make_path.ptr, mode) < 0) { + giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr); + error = GIT_EEXISTS; + goto done; + } + + giterr_clear(); + } else { + /* with exclusive create, existing dir is an error */ + if ((flags & GIT_MKDIR_EXCL) != 0) { + giterr_set(GITERR_FILESYSTEM, "Failed to make directory '%s': directory exists", make_path.ptr); + error = GIT_EEXISTS; + goto done; + } - /* ignore error if not at end or if directory already exists */ - if (lastch == '\0') { + if (S_ISLNK(st.st_mode)) { perfdata->stat_calls++; - if (p_stat(make_path.ptr, &st) < 0 || !S_ISDIR(st.st_mode)) { - giterr_system_set(tmp_errno); + /* 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; goto done; } } - /* with exclusive create, existing dir is an error */ - if ((flags & GIT_MKDIR_EXCL) != 0) { - giterr_set(GITERR_OS, "Directory already exists '%s'", make_path.ptr); + 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; } |