@@ -739,6 +739,7 @@ struct packed_git *add_packed_git(char *path, int path_len, int local)
739739 p -> windows = NULL ;
740740 p -> pack_fd = -1 ;
741741 p -> pack_local = local ;
742+ p -> mtime = st .st_mtime ;
742743 if ((path_len > 44 ) && !get_sha1_hex (path + path_len - 44 , sha1 ))
743744 hashcpy (p -> sha1 , sha1 );
744745 return p ;
@@ -823,6 +824,60 @@ static void prepare_packed_git_one(char *objdir, int local)
823824 closedir (dir );
824825}
825826
827+ static int sort_pack (const void * a_ , const void * b_ )
828+ {
829+ struct packed_git * a = * ((struct packed_git * * )a_ );
830+ struct packed_git * b = * ((struct packed_git * * )b_ );
831+ int st ;
832+
833+ /*
834+ * Local packs tend to contain objects specific to our
835+ * variant of the project than remote ones. In addition,
836+ * remote ones could be on a network mounted filesystem.
837+ * Favor local ones for these reasons.
838+ */
839+ st = a -> pack_local - b -> pack_local ;
840+ if (st )
841+ return - st ;
842+
843+ /*
844+ * Younger packs tend to contain more recent objects,
845+ * and more recent objects tend to get accessed more
846+ * often.
847+ */
848+ if (a -> mtime < b -> mtime )
849+ return 1 ;
850+ else if (a -> mtime == b -> mtime )
851+ return 0 ;
852+ return -1 ;
853+ }
854+
855+ static void rearrange_packed_git (void )
856+ {
857+ struct packed_git * * ary , * p ;
858+ int i , n ;
859+
860+ for (n = 0 , p = packed_git ; p ; p = p -> next )
861+ n ++ ;
862+ if (n < 2 )
863+ return ;
864+
865+ /* prepare an array of packed_git for easier sorting */
866+ ary = xcalloc (n , sizeof (struct packed_git * ));
867+ for (n = 0 , p = packed_git ; p ; p = p -> next )
868+ ary [n ++ ] = p ;
869+
870+ qsort (ary , n , sizeof (struct packed_git * ), sort_pack );
871+
872+ /* link them back again */
873+ for (i = 0 ; i < n - 1 ; i ++ )
874+ ary [i ]-> next = ary [i + 1 ];
875+ ary [n - 1 ]-> next = NULL ;
876+ packed_git = ary [0 ];
877+
878+ free (ary );
879+ }
880+
826881static int prepare_packed_git_run_once = 0 ;
827882void prepare_packed_git (void )
828883{
@@ -837,6 +892,7 @@ void prepare_packed_git(void)
837892 prepare_packed_git_one (alt -> base , 0 );
838893 alt -> name [-1 ] = '/' ;
839894 }
895+ rearrange_packed_git ();
840896 prepare_packed_git_run_once = 1 ;
841897}
842898
0 commit comments