commit - 06e5fc98c0fca4d47edc5ba2d0e7e9d0addcafdd
commit + bdd2fbb322a3775fd72d509c35794d84cfe6c88d
blob - c7ae922fdd4a145746c22771f63ff2e6ba588bb8
blob + 0ae98da4f6d7015c65b00992f291d39125a30efd
--- lib/delta.c
+++ lib/delta.c
struct got_delta *
got_delta_open(const char *path_packfile, off_t offset, size_t tslen,
- int type, size_t size)
+ int type, size_t size, off_t data_offset)
{
struct got_delta *delta;
delta->offset = offset;
delta->tslen = tslen;
delta->size = size;
+ delta->data_offset = data_offset;
return delta;
}
blob - 159057631e643f4fad94371f41acbd2023aa9529
blob + fb5e1481403dce4d214df33cc142f465105f5dc0
--- lib/delta.h
+++ lib/delta.h
size_t tslen;
int type;
size_t size;
+ off_t data_offset;
};
struct got_delta_chain {
SIMPLEQ_HEAD(, got_delta) entries;
};
-struct got_delta *got_delta_open(const char *, off_t, size_t, int, size_t);
+struct got_delta *got_delta_open(const char *, off_t, size_t, int, size_t,
+ off_t);
void got_delta_close(struct got_delta *);
const struct got_error *got_delta_chain_get_base_type(int *,
struct got_delta_chain *);
blob - dd64e4ac004ebf28028927affaa8a9d342b5f944
blob + 3098ee5298760506e297b4c3fcc5fa9a041e5dc2
--- lib/pack.c
+++ lib/pack.c
FILE *, const char *, off_t, size_t, int, size_t);
static const struct got_error *
+add_delta(struct got_delta_chain *deltas, const char *path_packfile,
+ off_t delta_offset, size_t tslen, int delta_type, size_t delta_size,
+ size_t delta_data_offset)
+{
+ struct got_delta *delta;
+
+ delta = got_delta_open(path_packfile, delta_offset, tslen,
+ delta_type, delta_size, delta_data_offset);
+ if (delta == NULL)
+ return got_error(GOT_ERR_NO_MEM);
+ /* delta is freed in got_object_close() */
+ deltas->nentries++;
+ SIMPLEQ_INSERT_HEAD(&deltas->entries, delta, entry);
+ return NULL;
+}
+
+static const struct got_error *
resolve_offset_delta(struct got_delta_chain *deltas,
struct got_repository *repo, FILE *packfile, const char *path_packfile,
- off_t delta_offset)
+ off_t delta_offset,size_t tslen, int delta_type, size_t delta_size)
+
{
const struct got_error *err;
off_t base_offset;
uint8_t base_type;
uint64_t base_size;
size_t base_tslen;
+ off_t delta_data_offset;
err = parse_offset_delta(&base_offset, packfile, delta_offset);
if (err)
return err;
+ delta_data_offset = ftello(packfile);
+ if (delta_data_offset == -1)
+ return got_error_from_errno();
+
+ err = add_delta(deltas, path_packfile, delta_offset, tslen,
+ delta_type, delta_size, delta_data_offset);
+ if (err)
+ return err;
+
/* An offset delta must be in the same packfile. */
if (fseeko(packfile, base_offset, SEEK_SET) != 0)
return got_error_from_errno();
static const struct got_error *
resolve_ref_delta(struct got_delta_chain *deltas, struct got_repository *repo,
- FILE *packfile, const char *path_packfile, off_t delta_offset)
+ FILE *packfile, const char *path_packfile, off_t delta_offset,
+ size_t tslen, int delta_type, size_t delta_size)
{
const struct got_error *err;
struct got_object_id id;
size_t n;
FILE *base_packfile;
char *path_base_packfile;
+ off_t delta_data_offset;
n = fread(&id, sizeof(id), 1, packfile);
if (n != 1)
return got_ferror(packfile, GOT_ERR_IO);
+ delta_data_offset = ftello(packfile);
+ if (delta_data_offset == -1)
+ return got_error_from_errno();
+
+ err = add_delta(deltas, path_packfile, delta_offset, tslen,
+ delta_type, delta_size, delta_data_offset);
+ if (err)
+ return err;
+
err = search_packidx(&packidx, &idx, repo, &id);
if (err)
return err;
int delta_type, size_t delta_size)
{
const struct got_error *err = NULL;
- struct got_delta *delta;
- delta = got_delta_open(path_packfile, delta_offset, tslen,
- delta_type, delta_size);
- if (delta == NULL)
- return got_error(GOT_ERR_NO_MEM);
- deltas->nentries++;
- SIMPLEQ_INSERT_HEAD(&deltas->entries, delta, entry);
- /* In case of error below, delta is freed in got_object_close(). */
-
switch (delta_type) {
case GOT_OBJ_TYPE_COMMIT:
case GOT_OBJ_TYPE_TREE:
case GOT_OBJ_TYPE_BLOB:
case GOT_OBJ_TYPE_TAG:
/* Plain types are the final delta base. Recursion ends. */
+ err = add_delta(deltas, path_packfile, delta_offset, tslen,
+ delta_type, delta_size, 0);
break;
case GOT_OBJ_TYPE_OFFSET_DELTA:
err = resolve_offset_delta(deltas, repo, packfile,
- path_packfile, delta_offset);
+ path_packfile, delta_offset, tslen, delta_type,
+ delta_size);
break;
case GOT_OBJ_TYPE_REF_DELTA:
- err = resolve_ref_delta(deltas, repo, packfile, path_packfile,
- delta_offset);
+ err = resolve_ref_delta(deltas, repo, packfile,
+ path_packfile, delta_offset, tslen, delta_type,
+ delta_size);
break;
default:
return got_error(GOT_ERR_NOT_IMPL);
goto done;
}
- if (fseeko(delta_file, delta->offset + delta->tslen,
- SEEK_SET) != 0) {
- fclose(delta_file);
- err = got_error_from_errno();
- goto done;
- }
if (n == 0) {
/* Plain object types are the delta base. */
goto done;
}
+ if (fseeko(delta_file, delta->offset + delta->tslen,
+ SEEK_SET) != 0) {
+ fclose(delta_file);
+ err = got_error_from_errno();
+ goto done;
+ }
err = got_inflate_to_file(&delta_len, delta_file,
base_file);
fclose(delta_file);
continue;
}
- if (delta->type == GOT_OBJ_TYPE_REF_DELTA &&
- fseeko(delta_file, SHA1_DIGEST_LENGTH, SEEK_CUR) != 0) {
+ if (fseeko(delta_file, delta->data_offset, SEEK_CUR) != 0) {
fclose(delta_file);
err = got_error_from_errno();
goto done;