Merge branch 'mh/object-code-cleanup'
authorJunio C Hamano <gitster@pobox.com>
Fri, 14 Mar 2014 21:26:29 +0000 (14:26 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 14 Mar 2014 21:26:29 +0000 (14:26 -0700)
* mh/object-code-cleanup:
sha1_file.c: document a bunch of functions defined in the file
sha1_file_name(): declare to return a const string
find_pack_entry(): document last_found_pack
replace_object: use struct members instead of an array

1  2 
cache.h
http.c
sha1_file.c
diff --combined cache.h
index 5ce6dfeddb7ba356b7c469fcf86d00ecef83be9c,d2ca541fcca5138d0bc18b5f4464fee94b247ad3..00ba6bf08eaf0b6f3dbbea709922a6cfce49c86d
+++ b/cache.h
@@@ -3,7 -3,7 +3,7 @@@
  
  #include "git-compat-util.h"
  #include "strbuf.h"
 -#include "hash.h"
 +#include "hashmap.h"
  #include "advice.h"
  #include "gettext.h"
  #include "convert.h"
@@@ -130,12 -130,12 +130,12 @@@ struct stat_data 
  };
  
  struct cache_entry {
 +      struct hashmap_entry ent;
        struct stat_data ce_stat_data;
        unsigned int ce_mode;
        unsigned int ce_flags;
        unsigned int ce_namelen;
        unsigned char sha1[20];
 -      struct cache_entry *next;
        char name[FLEX_ARRAY]; /* more */
  };
  
  #define CE_ADDED             (1 << 19)
  
  #define CE_HASHED            (1 << 20)
 -#define CE_UNHASHED          (1 << 21)
  #define CE_WT_REMOVE         (1 << 22) /* remove in work directory */
  #define CE_CONFLICTED        (1 << 23)
  
@@@ -194,18 -195,17 +194,18 @@@ struct pathspec
   * Copy the sha1 and stat state of a cache entry from one to
   * another. But we never change the name, or the hash state!
   */
 -#define CE_STATE_MASK (CE_HASHED | CE_UNHASHED)
  static inline void copy_cache_entry(struct cache_entry *dst,
                                    const struct cache_entry *src)
  {
 -      unsigned int state = dst->ce_flags & CE_STATE_MASK;
 +      unsigned int state = dst->ce_flags & CE_HASHED;
  
        /* Don't copy hash chain and name */
 -      memcpy(dst, src, offsetof(struct cache_entry, next));
 +      memcpy(&dst->ce_stat_data, &src->ce_stat_data,
 +                      offsetof(struct cache_entry, name) -
 +                      offsetof(struct cache_entry, ce_stat_data));
  
        /* Restore the hash state */
 -      dst->ce_flags = (dst->ce_flags & ~CE_STATE_MASK) | state;
 +      dst->ce_flags = (dst->ce_flags & ~CE_HASHED) | state;
  }
  
  static inline unsigned create_ce_flags(unsigned stage)
@@@ -277,8 -277,8 +277,8 @@@ struct index_state 
        struct cache_time timestamp;
        unsigned name_hash_initialized : 1,
                 initialized : 1;
 -      struct hash_table name_hash;
 -      struct hash_table dir_hash;
 +      struct hashmap name_hash;
 +      struct hashmap dir_hash;
  };
  
  extern struct index_state the_index;
@@@ -316,6 -316,7 +316,6 @@@ extern void free_name_hash(struct index
  #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
  #define cache_dir_exists(name, namelen) index_dir_exists(&the_index, (name), (namelen))
  #define cache_file_exists(name, namelen, igncase) index_file_exists(&the_index, (name), (namelen), (igncase))
 -#define cache_name_exists(name, namelen, igncase) index_name_exists(&the_index, (name), (namelen), (igncase))
  #define cache_name_is_other(name, namelen) index_name_is_other(&the_index, (name), (namelen))
  #define resolve_undo_clear() resolve_undo_clear_index(&the_index)
  #define unmerge_cache_entry_at(at) unmerge_index_entry_at(&the_index, at)
@@@ -433,7 -434,6 +433,7 @@@ extern int set_git_dir_init(const char 
  extern int init_db(const char *template_dir, unsigned int flags);
  
  extern void sanitize_stdfds(void);
 +extern int daemonize(void);
  
  #define alloc_nr(x) (((x)+16)*3/2)
  
@@@ -467,6 -467,7 +467,6 @@@ extern int unmerged_index(const struct 
  extern int verify_path(const char *path);
  extern struct cache_entry *index_dir_exists(struct index_state *istate, const char *name, int namelen);
  extern struct cache_entry *index_file_exists(struct index_state *istate, const char *name, int namelen, int igncase);
 -extern struct cache_entry *index_name_exists(struct index_state *istate, const char *name, int namelen, int igncase);
  extern int index_name_pos(const struct index_state *, const char *name, int namelen);
  #define ADD_CACHE_OK_TO_ADD 1         /* Ok to add */
  #define ADD_CACHE_OK_TO_REPLACE 2     /* Ok to replace file/directory */
@@@ -483,11 -484,11 +483,11 @@@ extern int remove_file_from_index(struc
  #define ADD_CACHE_IGNORE_ERRORS       4
  #define ADD_CACHE_IGNORE_REMOVAL 8
  #define ADD_CACHE_INTENT 16
 -#define ADD_CACHE_IMPLICIT_DOT 32     /* internal to "git add -u/-A" */
  extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
  extern int add_file_to_index(struct index_state *, const char *path, int flags);
 -extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);
 +extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, unsigned int refresh_options);
  extern int ce_same_name(const struct cache_entry *a, const struct cache_entry *b);
 +extern void set_object_name_for_intent_to_add_entry(struct cache_entry *ce);
  extern int index_name_is_other(const struct index_state *, const char *, int);
  extern void *read_blob_data_from_index(struct index_state *, const char *, unsigned long *);
  
  #define CE_MATCH_RACY_IS_DIRTY                02
  /* do stat comparison even if CE_SKIP_WORKTREE is true */
  #define CE_MATCH_IGNORE_SKIP_WORKTREE 04
 +/* ignore non-existent files during stat update  */
 +#define CE_MATCH_IGNORE_MISSING               0x08
 +/* enable stat refresh */
 +#define CE_MATCH_REFRESH              0x10
  extern int ie_match_stat(const struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
  extern int ie_modified(const struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
  
 -extern int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec);
 -
  #define HASH_WRITE_OBJECT 1
  #define HASH_FORMAT_CHECK 2
  extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
@@@ -660,9 -659,28 +660,28 @@@ extern char *git_path(const char *fmt, 
  extern char *git_path_submodule(const char *path, const char *fmt, ...)
        __attribute__((format (printf, 2, 3)));
  
- extern char *sha1_file_name(const unsigned char *sha1);
+ /*
+  * Return the name of the file in the local object database that would
+  * be used to store a loose object with the specified sha1.  The
+  * return value is a pointer to a statically allocated buffer that is
+  * overwritten each time the function is called.
+  */
+ extern const char *sha1_file_name(const unsigned char *sha1);
+ /*
+  * Return the name of the (local) packfile with the specified sha1 in
+  * its name.  The return value is a pointer to memory that is
+  * overwritten each time this function is called.
+  */
  extern char *sha1_pack_name(const unsigned char *sha1);
+ /*
+  * Return the name of the (local) pack index file with the specified
+  * sha1 in its name.  The return value is a pointer to memory that is
+  * overwritten each time this function is called.
+  */
  extern char *sha1_pack_index_name(const unsigned char *sha1);
  extern const char *find_unique_abbrev(const unsigned char *sha1, int);
  extern const unsigned char null_sha1[20];
  
@@@ -809,7 -827,6 +828,7 @@@ extern int hash_sha1_file(const void *b
  extern int write_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *return_sha1);
  extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
  extern int force_object_loose(const unsigned char *sha1, time_t mtime);
 +extern int git_open_noatime(const char *name);
  extern void *map_sha1_file(const unsigned char *sha1, unsigned long *size);
  extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
  extern int parse_sha1_header(const char *hdr, unsigned long *sizep);
@@@ -822,7 -839,19 +841,19 @@@ extern int check_sha1_signature(const u
  extern int move_temp_to_file(const char *tmpfile, const char *filename);
  
  extern int has_sha1_pack(const unsigned char *sha1);
+ /*
+  * Return true iff we have an object named sha1, whether local or in
+  * an alternate object database, and whether packed or loose.  This
+  * function does not respect replace references.
+  */
  extern int has_sha1_file(const unsigned char *sha1);
+ /*
+  * Return true iff an alternate object database has a loose object
+  * with the specified name.  This function does not respect replace
+  * references.
+  */
  extern int has_loose_object_nonlocal(const unsigned char *sha1);
  
  extern int has_pack_index(const unsigned char *sha1);
@@@ -961,7 -990,6 +992,7 @@@ void datestamp(char *buf, int bufsize)
  unsigned long approxidate_careful(const char *, int *);
  unsigned long approxidate_relative(const char *date, const struct timeval *now);
  enum date_mode parse_date_format(const char *format);
 +int date_overflows(unsigned long date);
  
  #define IDENT_STRICT         1
  #define IDENT_NO_DATE        2
@@@ -1086,17 -1114,46 +1117,46 @@@ extern struct packed_git *find_sha1_pac
                                         struct packed_git *packs);
  
  extern void pack_report(void);
+ /*
+  * mmap the index file for the specified packfile (if it is not
+  * already mmapped).  Return 0 on success.
+  */
  extern int open_pack_index(struct packed_git *);
+ /*
+  * munmap the index file for the specified packfile (if it is
+  * currently mmapped).
+  */
  extern void close_pack_index(struct packed_git *);
  extern unsigned char *use_pack(struct packed_git *, struct pack_window **, off_t, unsigned long *);
  extern void close_pack_windows(struct packed_git *);
  extern void unuse_pack(struct pack_window **);
  extern void free_pack_by_name(const char *);
  extern void clear_delta_base_cache(void);
  extern struct packed_git *add_packed_git(const char *, int, int);
- extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t);
- extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t);
- extern off_t find_pack_entry_one(const unsigned char *, struct packed_git *);
+ /*
+  * Return the SHA-1 of the nth object within the specified packfile.
+  * Open the index if it is not already open.  The return value points
+  * at the SHA-1 within the mmapped index.  Return NULL if there is an
+  * error.
+  */
+ extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t n);
+ /*
+  * Return the offset of the nth object within the specified packfile.
+  * The index must already be opened.
+  */
+ extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t n);
+ /*
+  * If the object named sha1 is present in the specified packfile,
+  * return its offset within the packfile; otherwise, return 0.
+  */
+ extern off_t find_pack_entry_one(const unsigned char *sha1, struct packed_git *);
  extern int is_pack_valid(struct packed_git *);
  extern void *unpack_entry(struct packed_git *, off_t, enum object_type *, unsigned long *);
  extern unsigned long unpack_object_header_buffer(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
@@@ -1149,12 -1206,6 +1209,12 @@@ extern int update_server_info(int)
  #define CONFIG_INVALID_PATTERN 6
  #define CONFIG_GENERIC_ERROR 7
  
 +struct git_config_source {
 +      unsigned int use_stdin:1;
 +      const char *file;
 +      const char *blob;
 +};
 +
  typedef int (*config_fn_t)(const char *, const char *, void *);
  extern int git_default_config(const char *, const char *, void *);
  extern int git_config_from_file(config_fn_t fn, const char *, void *);
@@@ -1164,7 -1215,8 +1224,7 @@@ extern void git_config_push_parameter(c
  extern int git_config_from_parameters(config_fn_t fn, void *data);
  extern int git_config(config_fn_t fn, void *);
  extern int git_config_with_options(config_fn_t fn, void *,
 -                                 const char *filename,
 -                                 const char *blob_ref,
 +                                 struct git_config_source *config_source,
                                   int respect_includes);
  extern int git_config_early(config_fn_t fn, void *, const char *repo_config);
  extern int git_parse_ulong(const char *, unsigned long *);
diff --combined http.c
index 1212c587afbc4df6100f6a099939550eabeb5ebf,faa9dc8f82ba42809979e65f163811294e40e3dc..94e1afdee7890825dfda0946b999f524265603fc
--- 1/http.c
--- 2/http.c
+++ b/http.c
@@@ -880,20 -880,6 +880,20 @@@ int handle_curl_result(struct slot_resu
        }
  }
  
 +int run_one_slot(struct active_request_slot *slot,
 +               struct slot_results *results)
 +{
 +      slot->results = results;
 +      if (!start_active_slot(slot)) {
 +              snprintf(curl_errorstr, sizeof(curl_errorstr),
 +                       "failed to start HTTP request");
 +              return HTTP_START_FAILED;
 +      }
 +
 +      run_active_slot(slot);
 +      return handle_curl_result(results);
 +}
 +
  static CURLcode curlinfo_strbuf(CURL *curl, CURLINFO info, struct strbuf *buf)
  {
        char *ptr;
@@@ -921,6 -907,7 +921,6 @@@ static int http_request(const char *url
        int ret;
  
        slot = get_active_slot();
 -      slot->results = &results;
        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
  
        if (result == NULL) {
        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "gzip");
  
 -      if (start_active_slot(slot)) {
 -              run_active_slot(slot);
 -              ret = handle_curl_result(&results);
 -      } else {
 -              snprintf(curl_errorstr, sizeof(curl_errorstr),
 -                       "failed to start HTTP request");
 -              ret = HTTP_START_FAILED;
 -      }
 +      ret = run_one_slot(slot, &results);
  
        if (options && options->content_type)
                curlinfo_strbuf(slot->curl, CURLINFO_CONTENT_TYPE,
@@@ -1390,7 -1384,7 +1390,7 @@@ struct http_object_request *new_http_ob
        unsigned char *sha1)
  {
        char *hex = sha1_to_hex(sha1);
-       char *filename;
+       const char *filename;
        char prevfile[PATH_MAX];
        int prevlocal;
        char prev_buf[PREV_BUF_SIZE];
diff --combined sha1_file.c
index 019628add50f4957c21f32abb99c06fc6e5f5d2c,bb9f09764a47f48cb2112cf394f3bc14ac75fb24..b37c6f67e4d97b95b4fb070aa03992eb92506421
@@@ -60,6 -60,12 +60,12 @@@ static struct cached_object empty_tree 
        0
  };
  
+ /*
+  * A pointer to the last packed_git in which an object was found.
+  * When an object is sought, we look in this packfile first, because
+  * objects that are looked up at similar times are often in the same
+  * packfile as one another.
+  */
  static struct packed_git *last_found_pack;
  
  static struct cached_object *find_cached_object(const unsigned char *sha1)
@@@ -178,17 -184,7 +184,7 @@@ static void fill_sha1_path(char *pathbu
        }
  }
  
- /*
-  * NOTE! This returns a statically allocated buffer, so you have to be
-  * careful about using it. Do an "xstrdup()" if you need to save the
-  * filename.
-  *
-  * Also note that this returns the location for creating.  Reading
-  * SHA1 file can happen from any alternate directory listed in the
-  * DB_ENVIRONMENT environment variable if it is not found in
-  * the primary object database.
-  */
- char *sha1_file_name(const unsigned char *sha1)
+ const char *sha1_file_name(const unsigned char *sha1)
  {
        static char buf[PATH_MAX];
        const char *objdir;
        return 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,
                                char **name, char **base, const char *which)
  {
@@@ -252,6 -253,8 +253,6 @@@ char *sha1_pack_index_name(const unsign
  struct alternate_object_database *alt_odb_list;
  static struct alternate_object_database **alt_odb_tail;
  
 -static int git_open_noatime(const char *name);
 -
  /*
   * Prepare alternate object database registry.
   *
@@@ -436,8 -439,7 +437,7 @@@ void prepare_alt_odb(void
  
  static int has_loose_object_local(const unsigned char *sha1)
  {
-       char *name = sha1_file_name(sha1);
-       return !access(name, F_OK);
+       return !access(sha1_file_name(sha1), F_OK);
  }
  
  int has_loose_object_nonlocal(const unsigned char *sha1)
@@@ -489,7 -491,12 +489,12 @@@ void pack_report(void
                sz_fmt(pack_mapped), sz_fmt(peak_pack_mapped));
  }
  
- static int check_packed_git_idx(const char *path,  struct packed_git *p)
+ /*
+  * Open and mmap the index file at path, perform a couple of
+  * consistency checks, then record its information to p.  Return 0 on
+  * success.
+  */
+ static int check_packed_git_idx(const char *path, struct packed_git *p)
  {
        void *idx_map;
        struct pack_idx_header *hdr;
@@@ -1230,7 -1237,6 +1235,7 @@@ static void prepare_packed_git_one(cha
  
                if (has_extension(de->d_name, ".idx") ||
                    has_extension(de->d_name, ".pack") ||
 +                  has_extension(de->d_name, ".bitmap") ||
                    has_extension(de->d_name, ".keep"))
                        string_list_append(&garbage, path);
                else
@@@ -1315,6 -1321,7 +1320,6 @@@ void prepare_packed_git(void
  
  void reprepare_packed_git(void)
  {
 -      discard_revindex();
        prepare_packed_git_run_once = 0;
        prepare_packed_git();
  }
@@@ -1391,7 -1398,7 +1396,7 @@@ int check_sha1_signature(const unsigne
        return hashcmp(sha1, real_sha1) ? -1 : 0;
  }
  
 -static int git_open_noatime(const char *name)
 +int git_open_noatime(const char *name)
  {
        static int sha1_file_open_flag = O_NOATIME;
  
  
  static int stat_sha1_file(const unsigned char *sha1, struct stat *st)
  {
-       char *name = sha1_file_name(sha1);
        struct alternate_object_database *alt;
  
-       if (!lstat(name, st))
+       if (!lstat(sha1_file_name(sha1), st))
                return 0;
  
        prepare_alt_odb();
        errno = ENOENT;
        for (alt = alt_odb_list; alt; alt = alt->next) {
-               name = alt->name;
-               fill_sha1_path(name, sha1);
+               fill_sha1_path(alt->name, sha1);
                if (!lstat(alt->base, st))
                        return 0;
        }
  static int open_sha1_file(const unsigned char *sha1)
  {
        int fd;
-       char *name = sha1_file_name(sha1);
        struct alternate_object_database *alt;
  
-       fd = git_open_noatime(name);
+       fd = git_open_noatime(sha1_file_name(sha1));
        if (fd >= 0)
                return fd;
  
        prepare_alt_odb();
        errno = ENOENT;
        for (alt = alt_odb_list; alt; alt = alt->next) {
-               name = alt->name;
-               fill_sha1_path(name, sha1);
+               fill_sha1_path(alt->name, sha1);
                fd = git_open_noatime(alt->base);
                if (fd >= 0)
                        return fd;
@@@ -2446,6 -2449,10 +2447,10 @@@ static int fill_pack_entry(const unsign
        return 1;
  }
  
+ /*
+  * Iff a pack file contains the object named by sha1, return true and
+  * store its location to e.
+  */
  static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
  {
        struct packed_git *p;
                return 1;
  
        for (p = packed_git; p; p = p->next) {
-               if (p == last_found_pack || !fill_pack_entry(sha1, e, p))
-                       continue;
+               if (p == last_found_pack)
+                       continue; /* we already checked this one */
  
-               last_found_pack = p;
-               return 1;
+               if (fill_pack_entry(sha1, e, p)) {
+                       last_found_pack = p;
+                       return 1;
+               }
        }
        return 0;
  }
@@@ -2677,7 -2686,6 +2684,6 @@@ void *read_sha1_file_extended(const uns
                              unsigned flag)
  {
        void *data;
-       char *path;
        const struct packed_git *p;
        const unsigned char *repl = lookup_replace_object_extended(sha1, flag);
  
                    sha1_to_hex(repl), sha1_to_hex(sha1));
  
        if (has_loose_object(repl)) {
-               path = sha1_file_name(sha1);
+               const char *path = sha1_file_name(sha1);
                die("loose object %s (stored in %s) is corrupt",
                    sha1_to_hex(repl), path);
        }
@@@ -2893,10 -2902,9 +2900,9 @@@ static int write_loose_object(const uns
        git_zstream stream;
        git_SHA_CTX c;
        unsigned char parano_sha1[20];
-       char *filename;
        static char tmp_file[PATH_MAX];
+       const char *filename = sha1_file_name(sha1);
  
-       filename = sha1_file_name(sha1);
        fd = create_tmpfile(tmp_file, sizeof(tmp_file), filename);
        if (fd < 0) {
                if (errno == EACCES)