Merge branch 'ti/fetch-everything-local-optim' into next
authorJunio C Hamano <gitster@pobox.com>
Thu, 15 Mar 2018 22:10:58 +0000 (15:10 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 15 Mar 2018 22:10:58 +0000 (15:10 -0700)
A "git fetch" from a repository with insane number of refs into a
repository that is already up-to-date still wasted too many cycles
making many lstat(2) calls to see if these objects at the tips
exist as loose objects locally. These lstat(2) calls are optimized
away by enumerating all loose objects beforehand.

It is unknown if the new strategy negatively affects existing use
cases, fetching into a repository with many loose objects from a
repository with small number of refs.

* ti/fetch-everything-local-optim:
fetch-pack.c: use oidset to check existence of loose object

1  2 
cache.h
sha1_file.c
diff --combined cache.h
index 5593a657aaac8f85309cc5c2dcc4debee64f67d4,6a72f54d797268637f8e09cbe98b445489b78136..4859e2be1a2566687336135bff144155dbcb4551
+++ b/cache.h
@@@ -459,7 -459,7 +459,7 @@@ static inline enum object_type object_t
   */
  extern const char * const local_repo_env[];
  
 -extern void setup_git_env(void);
 +extern void setup_git_env(const char *git_dir);
  
  /*
   * Returns true iff we have a configured git repository (either via
@@@ -599,7 -599,6 +599,7 @@@ extern int read_index_unmerged(struct i
  
  /* For use with `write_locked_index()`. */
  #define COMMIT_LOCK           (1 << 0)
 +#define SKIP_IF_UNCHANGED     (1 << 1)
  
  /*
   * Write the index while holding an already-taken lock. Close the lock,
   * With `COMMIT_LOCK`, the lock is always committed or rolled back.
   * Without it, the lock is closed, but neither committed nor rolled
   * back.
 + *
 + * If `SKIP_IF_UNCHANGED` is given and the index is unchanged, nothing
 + * is written (and the lock is rolled back if `COMMIT_LOCK` is given).
   */
  extern int write_locked_index(struct index_state *, struct lock_file *lock, unsigned flags);
  
@@@ -1777,6 -1773,8 +1777,8 @@@ struct object_info 
  #define OBJECT_INFO_SKIP_CACHED 4
  /* Do not retry packed storage after checking packed and loose storage */
  #define OBJECT_INFO_QUICK 8
+ /* Do not check loose object */
+ #define OBJECT_INFO_IGNORE_LOOSE 16
  extern int sha1_object_info_extended(const unsigned char *, struct object_info *, unsigned flags);
  
  /*
diff --combined sha1_file.c
index 669aadf2e0464c5021aa1f2a2ad5ac81b9988d1d,c0a19794795caa8bf7c1e5fe8d4094ca57bde41f..6ec3f8d5734683942f518f53944e104de41f32b8
@@@ -665,11 -665,15 +665,11 @@@ int foreach_alt_odb(alt_odb_fn fn, voi
  
  void prepare_alt_odb(void)
  {
 -      const char *alt;
 -
        if (alt_odb_tail)
                return;
  
 -      alt = getenv(ALTERNATE_DB_ENVIRONMENT);
 -
        alt_odb_tail = &alt_odb_list;
 -      link_alt_odb_entries(alt, PATH_SEP, NULL, 0);
 +      link_alt_odb_entries(the_repository->alternate_db, PATH_SEP, NULL, 0);
  
        read_info_alternates(get_object_directory(), 0);
  }
@@@ -1258,16 -1262,17 +1258,19 @@@ int sha1_object_info_extended(const uns
                if (find_pack_entry(real, &e))
                        break;
  
+               if (flags & OBJECT_INFO_IGNORE_LOOSE)
+                       return -1;
                /* Most likely it's a loose object. */
                if (!sha1_loose_object_info(real, oi, flags))
                        return 0;
  
                /* Not a loose object; someone else may have just packed it. */
 -              reprepare_packed_git();
 -              if (find_pack_entry(real, &e))
 -                      break;
 +              if (!(flags & OBJECT_INFO_QUICK)) {
 +                      reprepare_packed_git();
 +                      if (find_pack_entry(real, &e))
 +                              break;
 +              }
  
                /* Check if it is a missing object */
                if (fetch_if_missing && repository_format_partial_clone &&