Merge branch 'jk/loose-object-fsck'
authorJunio C Hamano <gitster@pobox.com>
Mon, 24 Apr 2017 05:07:50 +0000 (22:07 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 24 Apr 2017 05:07:50 +0000 (22:07 -0700)
Code cleanup.

* jk/loose-object-fsck:
sha1_file: remove an used fd variable

1  2 
sha1_file.c
diff --combined sha1_file.c
index 1577e2d7dd4f38462b7b33c02b888eed3f4ca2c6,1356ecb874faf78c6537dfc3b4cfbd220f990881..59a4ed2ed32336b41ab8f3b1d4aca30f045aa084
  #include "mru.h"
  #include "list.h"
  #include "mergesort.h"
 -
 -#ifndef O_NOATIME
 -#if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
 -#define O_NOATIME 01000000
 -#else
 -#define O_NOATIME 0
 -#endif
 -#endif
 +#include "quote.h"
  
  #define SZ_FMT PRIuMAX
  static inline uintmax_t sz_fmt(size_t s) { return s; }
@@@ -129,10 -136,8 +129,10 @@@ enum scld_error safe_create_leading_dir
                *slash = '\0';
                if (!stat(path, &st)) {
                        /* path exists */
 -                      if (!S_ISDIR(st.st_mode))
 +                      if (!S_ISDIR(st.st_mode)) {
 +                              errno = ENOTDIR;
                                ret = SCLD_EXISTS;
 +                      }
                } else if (mkdir(path, 0777)) {
                        if (errno == EEXIST &&
                            !stat(path, &st) && S_ISDIR(st.st_mode))
  
  enum scld_error safe_create_leading_directories_const(const char *path)
  {
 +      int save_errno;
        /* path points to cache entries, so xstrdup before messing with it */
        char *buf = xstrdup(path);
        enum scld_error result = safe_create_leading_directories(buf);
 +
 +      save_errno = errno;
        free(buf);
 +      errno = save_errno;
        return result;
  }
  
 +int raceproof_create_file(const char *path, create_file_fn fn, void *cb)
 +{
 +      /*
 +       * The number of times we will try to remove empty directories
 +       * in the way of path. This is only 1 because if another
 +       * process is racily creating directories that conflict with
 +       * us, we don't want to fight against them.
 +       */
 +      int remove_directories_remaining = 1;
 +
 +      /*
 +       * The number of times that we will try to create the
 +       * directories containing path. We are willing to attempt this
 +       * more than once, because another process could be trying to
 +       * clean up empty directories at the same time as we are
 +       * trying to create them.
 +       */
 +      int create_directories_remaining = 3;
 +
 +      /* A scratch copy of path, filled lazily if we need it: */
 +      struct strbuf path_copy = STRBUF_INIT;
 +
 +      int ret, save_errno;
 +
 +      /* Sanity check: */
 +      assert(*path);
 +
 +retry_fn:
 +      ret = fn(path, cb);
 +      save_errno = errno;
 +      if (!ret)
 +              goto out;
 +
 +      if (errno == EISDIR && remove_directories_remaining-- > 0) {
 +              /*
 +               * A directory is in the way. Maybe it is empty; try
 +               * to remove it:
 +               */
 +              if (!path_copy.len)
 +                      strbuf_addstr(&path_copy, path);
 +
 +              if (!remove_dir_recursively(&path_copy, REMOVE_DIR_EMPTY_ONLY))
 +                      goto retry_fn;
 +      } else if (errno == ENOENT && create_directories_remaining-- > 0) {
 +              /*
 +               * Maybe the containing directory didn't exist, or
 +               * maybe it was just deleted by a process that is
 +               * racing with us to clean up empty directories. Try
 +               * to create it:
 +               */
 +              enum scld_error scld_result;
 +
 +              if (!path_copy.len)
 +                      strbuf_addstr(&path_copy, path);
 +
 +              do {
 +                      scld_result = safe_create_leading_directories(path_copy.buf);
 +                      if (scld_result == SCLD_OK)
 +                              goto retry_fn;
 +              } while (scld_result == SCLD_VANISHED && create_directories_remaining-- > 0);
 +      }
 +
 +out:
 +      strbuf_release(&path_copy);
 +      errno = save_errno;
 +      return ret;
 +}
 +
  static void fill_sha1_path(struct strbuf *buf, const unsigned char *sha1)
  {
        int i;
@@@ -277,26 -210,31 +277,26 @@@ static const char *alt_sha1_path(struc
        return buf->buf;
  }
  
 -/*
 - * Return the name of the pack or index file with the specified sha1
 - * in its filename.  *base and *name are scratch space that must be
 - * provided by the caller.  which should be "pack" or "idx".
 - */
 -static char *sha1_get_pack_name(const unsigned char *sha1,
 -                              struct strbuf *buf,
 -                              const char *which)
 + char *odb_pack_name(struct strbuf *buf,
 +                   const unsigned char *sha1,
 +                   const char *ext)
  {
        strbuf_reset(buf);
        strbuf_addf(buf, "%s/pack/pack-%s.%s", get_object_directory(),
 -                  sha1_to_hex(sha1), which);
 +                  sha1_to_hex(sha1), ext);
        return buf->buf;
  }
  
  char *sha1_pack_name(const unsigned char *sha1)
  {
        static struct strbuf buf = STRBUF_INIT;
 -      return sha1_get_pack_name(sha1, &buf, "pack");
 +      return odb_pack_name(&buf, sha1, "pack");
  }
  
  char *sha1_pack_index_name(const unsigned char *sha1)
  {
        static struct strbuf buf = STRBUF_INIT;
 -      return sha1_get_pack_name(sha1, &buf, "idx");
 +      return odb_pack_name(&buf, sha1, "idx");
  }
  
  struct alternate_object_database *alt_odb_list;
@@@ -353,7 -291,7 +353,7 @@@ static int link_alt_odb_entry(const cha
        struct strbuf pathbuf = STRBUF_INIT;
  
        if (!is_absolute_path(entry) && relative_base) {
 -              strbuf_addstr(&pathbuf, real_path(relative_base));
 +              strbuf_realpath(&pathbuf, relative_base, 1);
                strbuf_addch(&pathbuf, '/');
        }
        strbuf_addstr(&pathbuf, entry);
        return 0;
  }
  
 +static const char *parse_alt_odb_entry(const char *string,
 +                                     int sep,
 +                                     struct strbuf *out)
 +{
 +      const char *end;
 +
 +      strbuf_reset(out);
 +
 +      if (*string == '#') {
 +              /* comment; consume up to next separator */
 +              end = strchrnul(string, sep);
 +      } else if (*string == '"' && !unquote_c_style(out, string, &end)) {
 +              /*
 +               * quoted path; unquote_c_style has copied the
 +               * data for us and set "end". Broken quoting (e.g.,
 +               * an entry that doesn't end with a quote) falls
 +               * back to the unquoted case below.
 +               */
 +      } else {
 +              /* normal, unquoted path */
 +              end = strchrnul(string, sep);
 +              strbuf_add(out, string, end - string);
 +      }
 +
 +      if (*end)
 +              end++;
 +      return end;
 +}
 +
  static void link_alt_odb_entries(const char *alt, int len, int sep,
                                 const char *relative_base, int depth)
  {
 -      struct string_list entries = STRING_LIST_INIT_NODUP;
 -      char *alt_copy;
 -      int i;
        struct strbuf objdirbuf = STRBUF_INIT;
 +      struct strbuf entry = STRBUF_INIT;
  
        if (depth > 5) {
                error("%s: ignoring alternate object stores, nesting too deep.",
                die("unable to normalize object directory: %s",
                    objdirbuf.buf);
  
 -      alt_copy = xmemdupz(alt, len);
 -      string_list_split_in_place(&entries, alt_copy, sep, -1);
 -      for (i = 0; i < entries.nr; i++) {
 -              const char *entry = entries.items[i].string;
 -              if (entry[0] == '\0' || entry[0] == '#')
 +      while (*alt) {
 +              alt = parse_alt_odb_entry(alt, sep, &entry);
 +              if (!entry.len)
                        continue;
 -              link_alt_odb_entry(entry, relative_base, depth, objdirbuf.buf);
 +              link_alt_odb_entry(entry.buf, relative_base, depth, objdirbuf.buf);
        }
 -      string_list_clear(&entries, 0);
 -      free(alt_copy);
 +      strbuf_release(&entry);
        strbuf_release(&objdirbuf);
  }
  
@@@ -662,7 -576,7 +662,7 @@@ static int freshen_file(const char *fn
   * either does not exist on disk, or has a stale mtime and may be subject to
   * pruning).
   */
 -static int check_and_freshen_file(const char *fn, int freshen)
 +int check_and_freshen_file(const char *fn, int freshen)
  {
        if (access(fn, F_OK))
                return 0;
@@@ -1606,7 -1520,7 +1606,7 @@@ static void mark_bad_packed_object(stru
                if (!hashcmp(sha1, p->bad_object_sha1 + GIT_SHA1_RAWSZ * i))
                        return;
        p->bad_object_sha1 = xrealloc(p->bad_object_sha1,
 -                                    st_mult(GIT_SHA1_RAWSZ,
 +                                    st_mult(GIT_MAX_RAWSZ,
                                              st_add(p->num_bad_objects, 1)));
        hashcpy(p->bad_object_sha1 + GIT_SHA1_RAWSZ * p->num_bad_objects, sha1);
        p->num_bad_objects++;
@@@ -1672,31 -1586,31 +1672,31 @@@ int check_sha1_signature(const unsigne
        return hashcmp(sha1, real_sha1) ? -1 : 0;
  }
  
 -int git_open(const char *name)
 +int git_open_cloexec(const char *name, int flags)
  {
 -      static int sha1_file_open_flag = O_NOATIME | O_CLOEXEC;
 -
 -      for (;;) {
 -              int fd;
 -
 -              errno = 0;
 -              fd = open(name, O_RDONLY | sha1_file_open_flag);
 -              if (fd >= 0)
 -                      return fd;
 +      int fd;
 +      static int o_cloexec = O_CLOEXEC;
  
 +      fd = open(name, flags | o_cloexec);
 +      if ((o_cloexec & O_CLOEXEC) && fd < 0 && errno == EINVAL) {
                /* Try again w/o O_CLOEXEC: the kernel might not support it */
 -              if ((sha1_file_open_flag & O_CLOEXEC) && errno == EINVAL) {
 -                      sha1_file_open_flag &= ~O_CLOEXEC;
 -                      continue;
 -              }
 +              o_cloexec &= ~O_CLOEXEC;
 +              fd = open(name, flags | o_cloexec);
 +      }
  
 -              /* Might the failure be due to O_NOATIME? */
 -              if (errno != ENOENT && (sha1_file_open_flag & O_NOATIME)) {
 -                      sha1_file_open_flag &= ~O_NOATIME;
 -                      continue;
 +#if defined(F_GETFL) && defined(F_SETFL) && defined(FD_CLOEXEC)
 +      {
 +              static int fd_cloexec = FD_CLOEXEC;
 +
 +              if (!o_cloexec && 0 <= fd && fd_cloexec) {
 +                      /* Opened w/o O_CLOEXEC?  try with fcntl(2) to add it */
 +                      int flags = fcntl(fd, F_GETFL);
 +                      if (fcntl(fd, F_SETFL, flags | fd_cloexec))
 +                              fd_cloexec = 0;
                }
 -              return -1;
        }
 +#endif
 +      return fd;
  }
  
  /*
@@@ -2440,10 -2354,11 +2440,10 @@@ static inline void release_delta_base_c
  
  void clear_delta_base_cache(void)
  {
 -      struct hashmap_iter iter;
 -      struct delta_base_cache_entry *entry;
 -      for (entry = hashmap_iter_first(&delta_base_cache, &iter);
 -           entry;
 -           entry = hashmap_iter_next(&iter)) {
 +      struct list_head *lru, *tmp;
 +      list_for_each_safe(lru, tmp, &delta_base_cache_lru) {
 +              struct delta_base_cache_entry *entry =
 +                      list_entry(lru, struct delta_base_cache_entry, lru);
                release_delta_base_cache(entry);
        }
  }
@@@ -2601,7 -2516,6 +2601,7 @@@ void *unpack_entry(struct packed_git *p
        while (delta_stack_nr) {
                void *delta_data;
                void *base = data;
 +              void *external_base = NULL;
                unsigned long delta_size, base_size = size;
                int i;
  
                                      p->pack_name);
                                mark_bad_packed_object(p, base_sha1);
                                base = read_object(base_sha1, &type, &base_size);
 +                              external_base = base;
                        }
                }
  
                              "at offset %"PRIuMAX" from %s",
                              (uintmax_t)curpos, p->pack_name);
                        data = NULL;
 +                      free(external_base);
                        continue;
                }
  
                        error("failed to apply delta");
  
                free(delta_data);
 +              free(external_base);
        }
  
        *final_type = type;
@@@ -2701,17 -2612,6 +2701,17 @@@ const unsigned char *nth_packed_object_
        }
  }
  
 +const struct object_id *nth_packed_object_oid(struct object_id *oid,
 +                                            struct packed_git *p,
 +                                            uint32_t n)
 +{
 +      const unsigned char *hash = nth_packed_object_sha1(p, n);
 +      if (!hash)
 +              return NULL;
 +      hashcpy(oid->hash, hash);
 +      return oid;
 +}
 +
  void check_pack_index_ptr(const struct packed_git *p, const void *vptr)
  {
        const unsigned char *ptr = vptr;
@@@ -2952,7 -2852,7 +2952,7 @@@ static int sha1_loose_object_info(cons
        if (status && oi->typep)
                *oi->typep = status;
        strbuf_release(&hdrbuf);
 -      return 0;
 +      return (status < 0) ? status : 0;
  }
  
  int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi, unsigned flags)
@@@ -3481,8 -3381,6 +3481,8 @@@ int has_sha1_file_with_flags(const unsi
  {
        struct pack_entry e;
  
 +      if (!startup_info->have_repository)
 +              return 0;
        if (find_pack_entry(sha1, &e))
                return 1;
        if (has_loose_object(sha1))
@@@ -3760,15 -3658,15 +3760,15 @@@ static int for_each_file_in_obj_subdir(
                strbuf_setlen(path, baselen);
                strbuf_addf(path, "/%s", de->d_name);
  
 -              if (strlen(de->d_name) == 38)  {
 -                      char hex[41];
 -                      unsigned char sha1[20];
 +              if (strlen(de->d_name) == GIT_SHA1_HEXSZ - 2)  {
 +                      char hex[GIT_MAX_HEXSZ+1];
 +                      struct object_id oid;
  
 -                      snprintf(hex, sizeof(hex), "%02x%s",
 -                               subdir_nr, de->d_name);
 -                      if (!get_sha1_hex(hex, sha1)) {
 +                      xsnprintf(hex, sizeof(hex), "%02x%s",
 +                                subdir_nr, de->d_name);
 +                      if (!get_oid_hex(hex, &oid)) {
                                if (obj_cb) {
 -                                      r = obj_cb(sha1, path->buf, data);
 +                                      r = obj_cb(&oid, path->buf, data);
                                        if (r)
                                                break;
                                }
@@@ -3874,13 -3772,13 +3874,13 @@@ static int for_each_object_in_pack(stru
        int r = 0;
  
        for (i = 0; i < p->num_objects; i++) {
 -              const unsigned char *sha1 = nth_packed_object_sha1(p, i);
 +              struct object_id oid;
  
 -              if (!sha1)
 +              if (!nth_packed_object_oid(&oid, p, i))
                        return error("unable to get sha1 of object %u in %s",
                                     i, p->pack_name);
  
 -              r = cb(sha1, p, i, data);
 +              r = cb(&oid, p, i, data);
                if (r)
                        break;
        }
@@@ -3915,7 -3813,7 +3915,7 @@@ static int check_stream_sha1(git_zstrea
                             const unsigned char *expected_sha1)
  {
        git_SHA_CTX c;
 -      unsigned char real_sha1[GIT_SHA1_RAWSZ];
 +      unsigned char real_sha1[GIT_MAX_RAWSZ];
        unsigned char buf[4096];
        unsigned long total_read;
        int status = Z_OK;
@@@ -3972,7 -3870,6 +3972,6 @@@ int read_loose_object(const char *path
                      void **contents)
  {
        int ret = -1;
-       int fd = -1;
        void *map = NULL;
        unsigned long mapsize;
        git_zstream stream;
  out:
        if (map)
                munmap(map, mapsize);
-       if (fd >= 0)
-               close(fd);
        return ret;
  }