Merge branch 'rh/prompt-pcmode-avoid-eval-on-refname' into maint
[gitweb.git] / sha1_file.c
index e13bd2c3ee7edb4d157e499fbcea80535ec5752f..77dbb56946771d631ec544dc1958fcff9215c117 100644 (file)
@@ -105,50 +105,63 @@ 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 *pos = path + offset_1st_component(path);
-       struct stat st;
+       char *next_component = path + offset_1st_component(path);
+       enum scld_error ret = SCLD_OK;
+
+       while (ret == SCLD_OK && next_component) {
+               struct stat st;
+               char *slash = next_component, slash_character;
+
+               while (*slash && !is_dir_sep(*slash))
+                       slash++;
 
-       while (pos) {
-               pos = strchr(pos, '/');
-               if (!pos)
+               if (!*slash)
                        break;
-               while (*++pos == '/')
-                       ;
-               if (!*pos)
+
+               next_component = slash + 1;
+               while (is_dir_sep(*next_component))
+                       next_component++;
+               if (!*next_component)
                        break;
-               *--pos = '\0';
+
+               slash_character = *slash;
+               *slash = '\0';
                if (!stat(path, &st)) {
                        /* path exists */
-                       if (!S_ISDIR(st.st_mode)) {
-                               *pos = '/';
-                               return -3;
-                       }
-               }
-               else if (mkdir(path, 0777)) {
+                       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 {
-                               *pos = '/';
-                               return -1;
-                       }
-               }
-               else if (adjust_shared_perm(path)) {
-                       *pos = '/';
-                       return -2;
+                       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)) {
+                       ret = SCLD_PERMS;
                }
-               *pos++ = '/';
+               *slash = slash_character;
        }
-       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;
 }
@@ -774,7 +787,7 @@ void close_pack_index(struct packed_git *p)
  * contain the same set of objects as an existing one.  In that case
  * the resulting file might be different even if its name would be the
  * same.  It is best to close any reference to the old pack before it is
- * replaced on disk.  Of course no index pointers nor windows for given pack
+ * replaced on disk.  Of course no index pointers or windows for given pack
  * must subsist at this point.  If ever objects from this pack are requested
  * again, the new version of the pack will be reinitialized through
  * reprepare_packed_git().
@@ -1110,7 +1123,7 @@ static void report_helper(const struct string_list *list,
        const char *msg;
        switch (seen_bits) {
        case 0:
-               msg = "no corresponding .idx nor .pack";
+               msg = "no corresponding .idx or .pack";
                break;
        case 1:
                msg = "no corresponding .idx";