lock_ref_sha1_basic(): if locking fails with ENOENT, retry
[gitweb.git] / sha1_file.c
index 4dd16c38f6bfa3969796845db6c41ba10b63f7b8..ed814e546f809ac190a294220fd678b8f45459fb 100644 (file)
@@ -105,51 +105,59 @@ int mkdir_in_gitdir(const char *path)
        return adjust_shared_perm(path);
 }
 
-int safe_create_leading_directories(char *path)
+enum scld_error safe_create_leading_directories(char *path)
 {
        char *next_component = path + offset_1st_component(path);
+       enum scld_error ret = SCLD_OK;
 
-       while (next_component) {
+       while (ret == SCLD_OK && next_component) {
                struct stat st;
                char *slash = strchr(next_component, '/');
 
                if (!slash)
                        break;
-               while (*(slash + 1) == '/')
-                       slash++;
+
                next_component = slash + 1;
+               while (*next_component == '/')
+                       next_component++;
                if (!*next_component)
                        break;
 
                *slash = '\0';
                if (!stat(path, &st)) {
                        /* path exists */
-                       if (!S_ISDIR(st.st_mode)) {
-                               *slash = '/';
-                               return -3;
-                       }
+                       if (!S_ISDIR(st.st_mode))
+                               ret = SCLD_EXISTS;
                } else if (mkdir(path, 0777)) {
                        if (errno == EEXIST &&
-                           !stat(path, &st) && S_ISDIR(st.st_mode)) {
+                           !stat(path, &st) && S_ISDIR(st.st_mode))
                                ; /* somebody created it since we checked */
-                       } else {
-                               *slash = '/';
-                               return -1;
-                       }
+                       else if (errno == ENOENT)
+                               /*
+                                * Either mkdir() failed because
+                                * somebody just pruned the containing
+                                * directory, or stat() failed because
+                                * the file that was in our way was
+                                * just removed.  Either way, inform
+                                * the caller that it might be worth
+                                * trying again:
+                                */
+                               ret = SCLD_VANISHED;
+                       else
+                               ret = SCLD_FAILED;
                } else if (adjust_shared_perm(path)) {
-                       *slash = '/';
-                       return -2;
+                       ret = SCLD_PERMS;
                }
                *slash = '/';
        }
-       return 0;
+       return ret;
 }
 
-int safe_create_leading_directories_const(const char *path)
+enum scld_error safe_create_leading_directories_const(const char *path)
 {
        /* path points to cache entries, so xstrdup before messing with it */
        char *buf = xstrdup(path);
-       int result = safe_create_leading_directories(buf);
+       enum scld_error result = safe_create_leading_directories(buf);
        free(buf);
        return result;
 }