@@ -596,7 +596,8 @@ static int unuse_one_window(struct packed_git *current, int keep_fd)
596596 lru_l -> next = lru_w -> next ;
597597 else {
598598 lru_p -> windows = lru_w -> next ;
599- if (!lru_p -> windows && lru_p -> pack_fd != keep_fd ) {
599+ if (!lru_p -> windows && lru_p -> pack_fd != -1
600+ && lru_p -> pack_fd != keep_fd ) {
600601 close (lru_p -> pack_fd );
601602 pack_open_fds -- ;
602603 lru_p -> pack_fd = -1 ;
@@ -812,14 +813,13 @@ unsigned char *use_pack(struct packed_git *p,
812813{
813814 struct pack_window * win = * w_cursor ;
814815
815- if (p -> pack_fd == -1 && open_packed_git (p ))
816- die ("packfile %s cannot be accessed" , p -> pack_name );
817-
818816 /* Since packfiles end in a hash of their content and it's
819817 * pointless to ask for an offset into the middle of that
820818 * hash, and the in_window function above wouldn't match
821819 * don't allow an offset too close to the end of the file.
822820 */
821+ if (!p -> pack_size && p -> pack_fd == -1 && open_packed_git (p ))
822+ die ("packfile %s cannot be accessed" , p -> pack_name );
823823 if (offset > (p -> pack_size - 20 ))
824824 die ("offset beyond end of packfile (truncated pack?)" );
825825
@@ -833,6 +833,10 @@ unsigned char *use_pack(struct packed_git *p,
833833 if (!win ) {
834834 size_t window_align = packed_git_window_size / 2 ;
835835 off_t len ;
836+
837+ if (p -> pack_fd == -1 && open_packed_git (p ))
838+ die ("packfile %s cannot be accessed" , p -> pack_name );
839+
836840 win = xcalloc (1 , sizeof (* win ));
837841 win -> offset = (offset / window_align ) * window_align ;
838842 len = p -> pack_size - win -> offset ;
@@ -850,6 +854,12 @@ unsigned char *use_pack(struct packed_git *p,
850854 die ("packfile %s cannot be mapped: %s" ,
851855 p -> pack_name ,
852856 strerror (errno ));
857+ if (!win -> offset && win -> len == p -> pack_size
858+ && !p -> do_not_close ) {
859+ close (p -> pack_fd );
860+ pack_open_fds -- ;
861+ p -> pack_fd = -1 ;
862+ }
853863 pack_mmap_calls ++ ;
854864 pack_open_windows ++ ;
855865 if (pack_mapped > peak_pack_mapped )
@@ -1950,6 +1960,27 @@ off_t find_pack_entry_one(const unsigned char *sha1,
19501960 return 0 ;
19511961}
19521962
1963+ static int is_pack_valid (struct packed_git * p )
1964+ {
1965+ /* An already open pack is known to be valid. */
1966+ if (p -> pack_fd != -1 )
1967+ return 1 ;
1968+
1969+ /* If the pack has one window completely covering the
1970+ * file size, the pack is known to be valid even if
1971+ * the descriptor is not currently open.
1972+ */
1973+ if (p -> windows ) {
1974+ struct pack_window * w = p -> windows ;
1975+
1976+ if (!w -> offset && w -> len == p -> pack_size )
1977+ return 1 ;
1978+ }
1979+
1980+ /* Force the pack to open to prove its valid. */
1981+ return !open_packed_git (p );
1982+ }
1983+
19531984static int find_pack_entry (const unsigned char * sha1 , struct pack_entry * e )
19541985{
19551986 static struct packed_git * last_found = (void * )1 ;
@@ -1979,7 +2010,7 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
19792010 * it may have been deleted since the index
19802011 * was loaded!
19812012 */
1982- if (p -> pack_fd == -1 && open_packed_git (p )) {
2013+ if (! is_pack_valid (p )) {
19832014 error ("packfile %s cannot be accessed" , p -> pack_name );
19842015 goto next ;
19852016 }
0 commit comments