commit 6c00b54532f90be3b76dd1aed025376a35dc35de from: Stefan Sperling date: Wed Jan 17 20:59:05 2018 UTC open packed objects correctly; don't worry about their contents yet commit - a92b0c17291b08d61cbe30b1e639a6331606218b commit + 6c00b54532f90be3b76dd1aed025376a35dc35de blob - 9e3f32b04c48fb04b77e6f8312deb951ae55ea31 blob + 204947b421455ff730a46fe0ff59b72331ec8a6a --- include/got_object.h +++ include/got_object.h @@ -73,9 +73,15 @@ struct got_object { #define GOT_OBJ_TYPE_OFFSET_DELTA 6 #define GOT_OBJ_TYPE_REF_DELTA 7 + int flags; +#define GOT_OBJ_FLAG_PACKED 0x01 + size_t hdrlen; size_t size; struct got_object_id id; + + char *path_packfile; + off_t pack_offset; }; struct got_repository; blob - a0ff6db1d758648a099b4c092d5950ce875c5333 blob + f3581b6726ebe6258178022ac2703b58f32165bb --- lib/object.c +++ lib/object.c @@ -134,7 +134,7 @@ inflate_read(struct got_zstream_buf *zb, FILE *f, size n = fread(zb->inbuf, 1, zb->inlen, f); if (n == 0) { if (ferror(f)) - return got_error(GOT_ERR_IO); + return got_ferror(f, GOT_ERR_IO); *outlenp = 0; return NULL; } @@ -268,34 +268,26 @@ object_path(char **path, struct got_object_id *id, str return err; } -static const struct got_error * -open_object(FILE **f, struct got_object_id *id, struct got_repository *repo) +const struct got_error * +open_object(FILE **f, struct got_object *obj, struct got_repository *repo) { const struct got_error *err = NULL; char *path; - err = object_path(&path, id, repo); + if (obj->flags & GOT_OBJ_FLAG_PACKED) { + return got_error(GOT_ERR_NOT_IMPL); + } + + err = object_path(&path, &obj->id, repo); if (err) return err; - *f = fopen(path, "rb"); if (*f == NULL) { - if (errno != ENOENT) { - err = got_error_from_errno(); - goto done; - } - err = got_packfile_extract_object(f, id, repo); - if (err) - goto done; - if (*f == NULL) { - err = got_error(GOT_ERR_NO_OBJ); - goto done; - } + err = got_error_from_errno(); + goto done; } done: free(path); - if (err && *f != NULL) - fclose(*f); return err; } @@ -303,24 +295,43 @@ const struct got_error * got_object_open(struct got_object **obj, struct got_repository *repo, struct got_object_id *id) { - const struct got_error *err; + const struct got_error *err = NULL; + char *path; FILE *f; - err = open_object(&f, id, repo); + err = object_path(&path, id, repo); if (err) return err; - err = read_object_header(obj, repo, f); - if (err == NULL) + f = fopen(path, "rb"); + if (f == NULL) { + if (errno != ENOENT) { + err = got_error_from_errno(); + goto done; + } + err = got_packfile_open_object(obj, id, repo); + if (err) + goto done; + if (*obj == NULL) + err = got_error(GOT_ERR_NO_OBJ); + } else { + err = read_object_header(obj, repo, f); + if (err) + goto done; memcpy((*obj)->id.sha1, id->sha1, SHA1_DIGEST_LENGTH); - else + } +done: + free(path); + if (err && f) fclose(f); return err; + } void got_object_close(struct got_object *obj) { + free(obj->path_packfile); free(obj); } @@ -587,7 +598,7 @@ got_object_commit_open(struct got_commit_object **comm if (obj->type != GOT_OBJ_TYPE_COMMIT) return got_error(GOT_ERR_OBJ_TYPE); - err = open_object(&f, &obj->id, repo); + err = open_object(&f, obj, repo); if (err) return err; @@ -656,7 +667,7 @@ got_object_tree_open(struct got_tree_object **tree, if (obj->type != GOT_OBJ_TYPE_TREE) return got_error(GOT_ERR_OBJ_TYPE); - err = open_object(&f, &obj->id, repo); + err = open_object(&f, obj, repo); if (err) return err; @@ -695,7 +706,7 @@ got_object_blob_open(struct got_blob_object **blob, if (*blob == NULL) return got_error(GOT_ERR_NO_MEM); - err = open_object(&((*blob)->f), &obj->id, repo); + err = open_object(&((*blob)->f), obj, repo); if (err) { free(*blob); return err; blob - dc94a559b6db4076da4c7b2c80a70f615e39aa0b blob + 7e7325a8f390d9822562634b04bd0eb7fc9da742 --- lib/pack.c +++ lib/pack.c @@ -292,16 +292,15 @@ get_object_idx(struct got_packidx_v2_hdr *packidx, str i = betoh32(packidx->fanout_table[id0 - 1]); while (i < totobj) { - struct got_object_id *oid = &packidx->sorted_ids[i++]; + struct got_object_id *oid = &packidx->sorted_ids[i]; uint32_t offset; int cmp = got_object_id_cmp(id, oid); - if (cmp < 0) - continue; - if (cmp > 0) + if (cmp == 0) + return i; + else if (cmp > 0) break; - - return i; + i++; } return -1; @@ -325,36 +324,6 @@ read_packfile_hdr(FILE *f, struct got_packidx_v2_hdr * err = got_error(GOT_ERR_BAD_PACKFILE); return err; -} - -static const struct got_error * -dump_plain_object(FILE *infile, uint8_t type, uint64_t size, FILE *outfile) -{ - const char *type_tag = got_object_get_type_tag(type); - size_t n; - - if (type_tag == NULL) - return got_error(GOT_ERR_OBJ_TYPE); - - fprintf(outfile, "%s %llu", type_tag, size); - fputc('\0', outfile); - - while (size > 0) { - uint8_t data[2048]; - size_t len = MIN(size, sizeof(data)); - - n = fread(data, len, 1, infile); - if (n != 1) - return got_ferror(infile, GOT_ERR_BAD_PACKIDX); - - n = fwrite(data, len, 1, outfile); - if (n != 1) - return got_ferror(outfile, GOT_ERR_BAD_PACKIDX); - - size -= len; - } - - return NULL; } static const struct got_error * @@ -389,66 +358,24 @@ decode_type_and_size(uint8_t *type, uint64_t *size, FI *type = t; *size = s; return NULL; -} - -static const struct got_error * -dump_packed_object(FILE **f, FILE *packfile, off_t offset) -{ - const struct got_error *err = NULL; - const char *template = "/tmp/got.XXXXXXXXXX"; - uint8_t type; - uint64_t size; - FILE *outfile = NULL; - - *f = got_opentemp(); - if (*f == NULL) { - err = got_error(GOT_ERR_FILE_OPEN); - goto done; - } - - if (fseeko(packfile, offset, SEEK_SET) != 0) { - err = got_error_from_errno(); - goto done; - } - - err = decode_type_and_size(&type, &size, packfile); - if (err) - goto done; - - switch (type) { - case GOT_OBJ_TYPE_COMMIT: - case GOT_OBJ_TYPE_TREE: - case GOT_OBJ_TYPE_BLOB: - err = dump_plain_object(packfile, type, size, *f); - break; - case GOT_OBJ_TYPE_REF_DELTA: - case GOT_OBJ_TYPE_TAG: - case GOT_OBJ_TYPE_OFFSET_DELTA: - default: - err = got_error(GOT_ERR_NOT_IMPL); - goto done; - } - - rewind(*f); -done: - if (err && *f) - fclose(*f); - return err; } static const struct got_error * -extract_object(FILE **f, const char *path_packdir, - struct got_packidx_v2_hdr *packidx, struct got_object_id *id) +open_packed_object(struct got_object **obj, struct got_repository *repo, + const char *path_packdir, struct got_packidx_v2_hdr *packidx, + struct got_object_id *id) { const struct got_error *err = NULL; int idx = get_object_idx(packidx, id); off_t offset; - char *path_packfile; - FILE *packfile; char hex[SHA1_DIGEST_STRING_LENGTH]; char *sha1str; + char *path_packfile; + FILE *packfile; + uint8_t type; + uint64_t size; - *f = NULL; + *obj = NULL; if (idx == -1) /* object not found in pack index */ return NULL; @@ -475,20 +402,55 @@ extract_object(FILE **f, const char *path_packdir, if (err) goto done; - printf("Dumping object at offset %llu\n", offset); - err = dump_packed_object(f, packfile, offset); + if (fseeko(packfile, offset, SEEK_SET) != 0) { + err = got_error_from_errno(); + goto done; + } + + err = decode_type_and_size(&type, &size, packfile); if (err) goto done; + *obj = calloc(1, sizeof(**obj)); + if (*obj == NULL) { + err = got_error(GOT_ERR_NO_MEM); + goto done; + } + + switch (type) { + case GOT_OBJ_TYPE_COMMIT: + case GOT_OBJ_TYPE_TREE: + case GOT_OBJ_TYPE_BLOB: + (*obj)->path_packfile = strdup(path_packfile); + if ((*obj)->path_packfile == NULL) { + err = got_error(GOT_ERR_NO_MEM); + goto done; + } + (*obj)->type = type; + (*obj)->flags = GOT_OBJ_FLAG_PACKED; + (*obj)->hdrlen = 0; + (*obj)->size = size; + memcpy(&(*obj)->id, id, sizeof((*obj)->id)); + (*obj)->pack_offset = offset; + break; + case GOT_OBJ_TYPE_REF_DELTA: + case GOT_OBJ_TYPE_TAG: + case GOT_OBJ_TYPE_OFFSET_DELTA: + default: + err = got_error(GOT_ERR_NOT_IMPL); + goto done; + } done: free(path_packfile); + if (err) + free(*obj); if (packfile && fclose(packfile) == -1 && err == 0) err = got_error_from_errno(); return err; } const struct got_error * -got_packfile_extract_object(FILE **f, struct got_object_id *id, +got_packfile_open_object(struct got_object **obj, struct got_object_id *id, struct got_repository *repo) { const struct got_error *err = NULL; @@ -525,10 +487,10 @@ got_packfile_extract_object(FILE **f, struct got_objec if (err) goto done; - err = extract_object(f, path_packdir, packidx, id); + err = open_packed_object(obj, repo, path_packdir, packidx, id); if (err) goto done; - if (*f != NULL) + if (*obj != NULL) break; } blob - 9e034eb2f7ab046e1448b158af3478bdf73aee1b blob + e26be48fe9e5fa02953cf19e02932e77d46a40d5 --- lib/pack.h +++ lib/pack.h @@ -121,5 +121,5 @@ const struct got_error *got_packidx_open(struct got_pa const char *); void got_packidx_close(struct got_packidx_v2_hdr *); -const struct got_error *got_packfile_extract_object(FILE **, +const struct got_error *got_packfile_open_object(struct got_object **, struct got_object_id *, struct got_repository *);