1313#include "odb.h"
1414#include "pack.h"
1515
16- #define GIT_MIDX_FILE_MODE 0444
17-
1816#define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
1917#define MIDX_VERSION 1
2018#define MIDX_OBJECT_ID_VERSION 1
@@ -116,7 +114,7 @@ static int midx_parse_oid_lookup(
116114 return midx_error ("missing OID Lookup chunk" );
117115 if (chunk_oid_lookup -> length == 0 )
118116 return midx_error ("empty OID Lookup chunk" );
119- if (chunk_oid_lookup -> length != idx -> num_objects * 20 )
117+ if (chunk_oid_lookup -> length != idx -> num_objects * GIT_OID_RAWSZ )
120118 return midx_error ("OID Lookup chunk has wrong length" );
121119
122120 idx -> oid_lookup = oid = (git_oid * )(data + chunk_oid_lookup -> offset );
@@ -183,7 +181,7 @@ int git_midx_parse(
183181
184182 GIT_ASSERT_ARG (idx );
185183
186- if (size < sizeof (struct git_midx_header ) + 20 )
184+ if (size < sizeof (struct git_midx_header ) + GIT_OID_RAWSZ )
187185 return midx_error ("multi-pack index is too short" );
188186
189187 hdr = ((struct git_midx_header * )data );
@@ -203,7 +201,7 @@ int git_midx_parse(
203201 last_chunk_offset =
204202 sizeof (struct git_midx_header ) +
205203 (1 + hdr -> chunks ) * 12 ;
206- trailer_offset = size - 20 ;
204+ trailer_offset = size - GIT_OID_RAWSZ ;
207205 if (trailer_offset < last_chunk_offset )
208206 return midx_error ("wrong index size" );
209207 git_oid_cpy (& idx -> checksum , (git_oid * )(data + trailer_offset ));
@@ -309,6 +307,10 @@ int git_midx_open(
309307 idx = git__calloc (1 , sizeof (git_midx_file ));
310308 GIT_ERROR_CHECK_ALLOC (idx );
311309
310+ error = git_buf_sets (& idx -> filename , path );
311+ if (error < 0 )
312+ return error ;
313+
312314 error = git_futils_mmap_ro (& idx -> index_map , fd , 0 , idx_size );
313315 p_close (fd );
314316 if (error < 0 ) {
@@ -325,6 +327,46 @@ int git_midx_open(
325327 return 0 ;
326328}
327329
330+ bool git_midx_needs_refresh (
331+ const git_midx_file * idx ,
332+ const char * path )
333+ {
334+ git_file fd = -1 ;
335+ struct stat st ;
336+ ssize_t bytes_read ;
337+ git_oid idx_checksum = {{0 }};
338+
339+ /* TODO: properly open the file without access time using O_NOATIME */
340+ fd = git_futils_open_ro (path );
341+ if (fd < 0 )
342+ return true;
343+
344+ if (p_fstat (fd , & st ) < 0 ) {
345+ p_close (fd );
346+ return true;
347+ }
348+
349+ if (!S_ISREG (st .st_mode ) ||
350+ !git__is_sizet (st .st_size ) ||
351+ (size_t )st .st_size != idx -> index_map .len ) {
352+ p_close (fd );
353+ return true;
354+ }
355+
356+ if (p_lseek (fd , - GIT_OID_RAWSZ , SEEK_END ) < 0 ) {
357+ p_close (fd );
358+ return true;
359+ }
360+
361+ bytes_read = p_read (fd , & idx_checksum , GIT_OID_RAWSZ );
362+ p_close (fd );
363+
364+ if (bytes_read != GIT_OID_RAWSZ )
365+ return true;
366+
367+ return git_oid_cmp (& idx_checksum , & idx -> checksum ) == 0 ;
368+ }
369+
328370int git_midx_entry_find (
329371 git_midx_entry * e ,
330372 git_midx_file * idx ,
@@ -343,7 +385,7 @@ int git_midx_entry_find(
343385 hi = ntohl (idx -> oid_fanout [(int )short_oid -> id [0 ]]);
344386 lo = ((short_oid -> id [0 ] == 0x0 ) ? 0 : ntohl (idx -> oid_fanout [(int )short_oid -> id [0 ] - 1 ]));
345387
346- pos = git_pack__lookup_sha1 (idx -> oid_lookup , 20 , lo , hi , short_oid -> id );
388+ pos = git_pack__lookup_sha1 (idx -> oid_lookup , GIT_OID_RAWSZ , lo , hi , short_oid -> id );
347389
348390 if (pos >= 0 ) {
349391 /* An object matching exactly the oid was found */
@@ -399,6 +441,24 @@ int git_midx_entry_find(
399441 return 0 ;
400442}
401443
444+ int git_midx_foreach_entry (
445+ git_midx_file * idx ,
446+ git_odb_foreach_cb cb ,
447+ void * data )
448+ {
449+ size_t i ;
450+ int error ;
451+
452+ GIT_ASSERT_ARG (idx );
453+
454+ for (i = 0 ; i < idx -> num_objects ; ++ i ) {
455+ if ((error = cb (& idx -> oid_lookup [i ], data )) != 0 )
456+ return git_error_set_after_callback (error );
457+ }
458+
459+ return error ;
460+ }
461+
402462int git_midx_close (git_midx_file * idx )
403463{
404464 GIT_ASSERT_ARG (idx );
@@ -416,6 +476,7 @@ void git_midx_free(git_midx_file *idx)
416476 if (!idx )
417477 return ;
418478
479+ git_buf_dispose (& idx -> filename );
419480 git_midx_close (idx );
420481 git__free (idx );
421482}
0 commit comments