Skip to content

Commit 4fadd59

Browse files
committed
Merge pull request libgit2#5447 (lhchavez:git-odb-options)
2 parents fa618a5 + f847fa7 commit 4fadd59

File tree

5 files changed

+399
-112
lines changed

5 files changed

+399
-112
lines changed

src/midx.c

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
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+
328370
int 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+
402462
int 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
}

src/midx.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "map.h"
1616
#include "mwindow.h"
17+
#include "odb.h"
1718

1819
/*
1920
* A multi-pack-index file.
@@ -49,6 +50,9 @@ typedef struct git_midx_file {
4950

5051
/* The trailer of the file. Contains the SHA1-checksum of the whole file. */
5152
git_oid checksum;
53+
54+
/* something like ".git/objects/pack/multi-pack-index". */
55+
git_buf filename;
5256
} git_midx_file;
5357

5458
/*
@@ -66,11 +70,18 @@ typedef struct git_midx_entry {
6670
int git_midx_open(
6771
git_midx_file **idx_out,
6872
const char *path);
73+
bool git_midx_needs_refresh(
74+
const git_midx_file *idx,
75+
const char *path);
6976
int git_midx_entry_find(
7077
git_midx_entry *e,
7178
git_midx_file *idx,
7279
const git_oid *short_oid,
7380
size_t len);
81+
int git_midx_foreach_entry(
82+
git_midx_file *idx,
83+
git_odb_foreach_cb cb,
84+
void *data);
7485
int git_midx_close(git_midx_file *idx);
7586
void git_midx_free(git_midx_file *idx);
7687

0 commit comments

Comments
 (0)