diff --git a/include/git2/pack.h b/include/git2/pack.h index 4cf426273..4941998eb 100644 --- a/include/git2/pack.h +++ b/include/git2/pack.h @@ -127,6 +127,18 @@ GIT_EXTERN(int) git_packbuilder_insert_commit(git_packbuilder *pb, const git_oid */ GIT_EXTERN(int) git_packbuilder_insert_walk(git_packbuilder *pb, git_revwalk *walk); +/** + * Recursively insert an object and its referenced objects + * + * Insert the object as well as any object it references. + * + * @param pb the packbuilder + * @param id the id of the root object to insert + * @param name optional name for the object + * @return 0 or an error code + */ +GIT_EXTERN(int) git_packbuilder_insert_recur(git_packbuilder *pb, const git_oid *id, const char *name); + /** * Write the contents of the packfile to an in-memory buffer * diff --git a/src/pack-objects.c b/src/pack-objects.c index 0f43b98e0..932764698 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -1404,6 +1404,42 @@ int git_packbuilder_insert_tree(git_packbuilder *pb, const git_oid *oid) return error; } +int git_packbuilder_insert_recur(git_packbuilder *pb, const git_oid *id, const char *name) +{ + git_object *obj; + int error; + + assert(pb && id); + + if ((error = git_object_lookup(&obj, pb->repo, id, GIT_OBJ_ANY)) < 0) + return error; + + switch (git_object_type(obj)) { + case GIT_OBJ_BLOB: + error = git_packbuilder_insert(pb, id, name); + break; + case GIT_OBJ_TREE: + error = git_packbuilder_insert_tree(pb, id); + break; + case GIT_OBJ_COMMIT: + error = git_packbuilder_insert_commit(pb, id); + break; + case GIT_OBJ_TAG: + if ((error = git_packbuilder_insert(pb, id, name)) < 0) + goto cleanup; + error = git_packbuilder_insert_recur(pb, git_tag_target_id((git_tag *) obj), NULL); + break; + + default: + giterr_set(GITERR_INVALID, "unknown object type"); + error = -1; + } + +cleanup: + git_object_free(obj); + return error; +} + uint32_t git_packbuilder_object_count(git_packbuilder *pb) { return pb->nr_objects;