sha1_file.c: use ALLOC_GROW() in pretend_sha1_file()
[gitweb.git] / sha1_file.c
index e13bd2c3ee7edb4d157e499fbcea80535ec5752f..2af06f842324485191204b8c5e46436156feb903 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;
 }
@@ -2613,12 +2626,7 @@ int pretend_sha1_file(void *buf, unsigned long len, enum object_type type,
        hash_sha1_file(buf, len, typename(type), sha1);
        if (has_sha1_file(sha1) || find_cached_object(sha1))
                return 0;
-       if (cached_object_alloc <= cached_object_nr) {
-               cached_object_alloc = alloc_nr(cached_object_alloc);
-               cached_objects = xrealloc(cached_objects,
-                                         sizeof(*cached_objects) *
-                                         cached_object_alloc);
-       }
+       ALLOC_GROW(cached_objects, cached_object_nr + 1, cached_object_alloc);
        co = &cached_objects[cached_object_nr++];
        co->size = len;
        co->type = type;