]> git.proxmox.com Git - libgit2.git/commitdiff
mkdir: walk up tree to mkdir
authorEdward Thomson <ethomson@microsoft.com>
Tue, 13 Jan 2015 17:18:02 +0000 (11:18 -0600)
committerEdward Thomson <ethomson@microsoft.com>
Tue, 20 Jan 2015 23:12:46 +0000 (17:12 -0600)
Walk up the tree to mkdir, which is less immediately efficient,
but allows us to look at intermediate directories that may need
attention.

include/git2/errors.h
src/fileops.c

index 9b4cc7c00f94f6f306396d077c187e0acd20f3d6..ef4fabb7da532d6076a4535940b0dc89c29f14a2 100644 (file)
@@ -93,6 +93,7 @@ typedef enum {
        GITERR_CHERRYPICK,
        GITERR_DESCRIBE,
        GITERR_REBASE,
+       GITERR_FILESYSTEM
 } git_error_t;
 
 /**
index 926813f5e5c02031677138aeead13d4250fab85e..ea0f4e1f725a62f64e1ed4ce2b2fe947c6b8cc5e 100644 (file)
@@ -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;
                        }