зеркало из https://github.com/microsoft/git.git
csum-file: introduce sha1file_checkpoint
It is useful to be able to rewind a check-summed file to a certain previous state after writing data into it using sha1write() API. The fast-import command does this after streaming a blob data to the packfile being generated and then noticing that the same blob has already been written, and it does this with a private code truncate_pack() that is commented as "Yes, this is a layering violation". Introduce two API functions, sha1file_checkpoint(), that allows the caller to save a state of a sha1file, and then later revert it to the saved state. Use it to reimplement truncate_pack(). Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
0e990530ae
Коммит
6c52614864
20
csum-file.c
20
csum-file.c
|
@ -158,6 +158,26 @@ struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp
|
|||
return f;
|
||||
}
|
||||
|
||||
void sha1file_checkpoint(struct sha1file *f, struct sha1file_checkpoint *checkpoint)
|
||||
{
|
||||
sha1flush(f);
|
||||
checkpoint->offset = f->total;
|
||||
checkpoint->ctx = f->ctx;
|
||||
}
|
||||
|
||||
int sha1file_truncate(struct sha1file *f, struct sha1file_checkpoint *checkpoint)
|
||||
{
|
||||
off_t offset = checkpoint->offset;
|
||||
|
||||
if (ftruncate(f->fd, offset) ||
|
||||
lseek(f->fd, offset, SEEK_SET) != offset)
|
||||
return -1;
|
||||
f->total = offset;
|
||||
f->ctx = checkpoint->ctx;
|
||||
f->offset = 0; /* sha1flush() was called in checkpoint */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crc32_begin(struct sha1file *f)
|
||||
{
|
||||
f->crc32 = crc32(0, NULL, 0);
|
||||
|
|
|
@ -17,6 +17,15 @@ struct sha1file {
|
|||
unsigned char buffer[8192];
|
||||
};
|
||||
|
||||
/* Checkpoint */
|
||||
struct sha1file_checkpoint {
|
||||
off_t offset;
|
||||
git_SHA_CTX ctx;
|
||||
};
|
||||
|
||||
extern void sha1file_checkpoint(struct sha1file *, struct sha1file_checkpoint *);
|
||||
extern int sha1file_truncate(struct sha1file *, struct sha1file_checkpoint *);
|
||||
|
||||
/* sha1close flags */
|
||||
#define CSUM_CLOSE 1
|
||||
#define CSUM_FSYNC 2
|
||||
|
|
|
@ -1143,17 +1143,11 @@ static int store_object(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void truncate_pack(off_t to, git_SHA_CTX *ctx)
|
||||
static void truncate_pack(struct sha1file_checkpoint *checkpoint)
|
||||
{
|
||||
if (ftruncate(pack_data->pack_fd, to)
|
||||
|| lseek(pack_data->pack_fd, to, SEEK_SET) != to)
|
||||
if (sha1file_truncate(pack_file, checkpoint))
|
||||
die_errno("cannot truncate pack to skip duplicate");
|
||||
pack_size = to;
|
||||
|
||||
/* yes this is a layering violation */
|
||||
pack_file->total = to;
|
||||
pack_file->offset = 0;
|
||||
pack_file->ctx = *ctx;
|
||||
pack_size = checkpoint->offset;
|
||||
}
|
||||
|
||||
static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark)
|
||||
|
@ -1166,8 +1160,8 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark)
|
|||
unsigned long hdrlen;
|
||||
off_t offset;
|
||||
git_SHA_CTX c;
|
||||
git_SHA_CTX pack_file_ctx;
|
||||
git_zstream s;
|
||||
struct sha1file_checkpoint checkpoint;
|
||||
int status = Z_OK;
|
||||
|
||||
/* Determine if we should auto-checkpoint. */
|
||||
|
@ -1175,11 +1169,8 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark)
|
|||
|| (pack_size + 60 + len) < pack_size)
|
||||
cycle_packfile();
|
||||
|
||||
offset = pack_size;
|
||||
|
||||
/* preserve the pack_file SHA1 ctx in case we have to truncate later */
|
||||
sha1flush(pack_file);
|
||||
pack_file_ctx = pack_file->ctx;
|
||||
sha1file_checkpoint(pack_file, &checkpoint);
|
||||
offset = checkpoint.offset;
|
||||
|
||||
hdrlen = snprintf((char *)out_buf, out_sz, "blob %" PRIuMAX, len) + 1;
|
||||
if (out_sz <= hdrlen)
|
||||
|
@ -1245,14 +1236,14 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark)
|
|||
|
||||
if (e->idx.offset) {
|
||||
duplicate_count_by_type[OBJ_BLOB]++;
|
||||
truncate_pack(offset, &pack_file_ctx);
|
||||
truncate_pack(&checkpoint);
|
||||
|
||||
} else if (find_sha1_pack(sha1, packed_git)) {
|
||||
e->type = OBJ_BLOB;
|
||||
e->pack_id = MAX_PACK_ID;
|
||||
e->idx.offset = 1; /* just not zero! */
|
||||
duplicate_count_by_type[OBJ_BLOB]++;
|
||||
truncate_pack(offset, &pack_file_ctx);
|
||||
truncate_pack(&checkpoint);
|
||||
|
||||
} else {
|
||||
e->depth = 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче