From 6ca9643c967cb2de89ba360eb226ec49d27345a4 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Sun, 6 May 2012 21:00:20 +0200 Subject: [PATCH 1/2] blob: Add git_blob_create_fromdisk() This function will create blobs in the object database from files anywhere on the filesystem. This can be run against bare and non-bare repositories. --- include/git2/blob.h | 12 ++++++ src/blob.c | 56 ++++++++++++++++++++-------- tests-clar/object/blob/write.c | 68 ++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 16 deletions(-) create mode 100644 tests-clar/object/blob/write.c diff --git a/include/git2/blob.h b/include/git2/blob.h index 44b29d7eb..afa350bb1 100644 --- a/include/git2/blob.h +++ b/include/git2/blob.h @@ -103,6 +103,18 @@ GIT_EXTERN(size_t) git_blob_rawsize(git_blob *blob); */ GIT_EXTERN(int) git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *path); +/** + * Read a file from the filesystem and write its content + * to the Object Database as a loose blob + * + * @param oid return the id of the written blob + * @param repo repository where the blob will be written. + * this repository can be bare or not + * @param path file from which the blob will be created + * @return GIT_SUCCESS or an error code + */ +GIT_EXTERN(int) git_blob_create_fromdisk(git_oid *oid, git_repository *repo, const char *path); + /** * Write an in-memory buffer to the ODB as a blob diff --git a/src/blob.c b/src/blob.c index 36571c70a..e25944b91 100644 --- a/src/blob.c +++ b/src/blob.c @@ -148,30 +148,20 @@ static int write_symlink( return error; } -int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *path) +static int blob_create_internal(git_oid *oid, git_repository *repo, const char *path) { int error; - git_buf full_path = GIT_BUF_INIT; - git_off_t size; struct stat st; - const char *workdir; git_odb *odb = NULL; + git_off_t size; - workdir = git_repository_workdir(repo); - assert(workdir); /* error to call this on bare repo */ - - if ((error = git_buf_joinpath(&full_path, workdir, path)) < 0 || - (error = git_path_lstat(full_path.ptr, &st)) < 0 || - (error = git_repository_odb__weakptr(&odb, repo)) < 0) - { - git_buf_free(&full_path); + if ((error = git_path_lstat(path, &st)) < 0 || (error = git_repository_odb__weakptr(&odb, repo)) < 0) return error; - } size = st.st_size; if (S_ISLNK(st.st_mode)) { - error = write_symlink(oid, odb, full_path.ptr, (size_t)size); + error = write_symlink(oid, odb, path, (size_t)size); } else { git_vector write_filters = GIT_VECTOR_INIT; int filter_count; @@ -186,10 +176,10 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat } else if (filter_count == 0) { /* No filters need to be applied to the document: we can stream * directly from disk */ - error = write_file_stream(oid, odb, full_path.ptr, size); + error = write_file_stream(oid, odb, path, size); } else { /* We need to apply one or more filters */ - error = write_file_filtered(oid, odb, full_path.ptr, &write_filters); + error = write_file_filtered(oid, odb, path, &write_filters); } git_filters_free(&write_filters); @@ -209,7 +199,41 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat */ } + return error; +} + +int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *path) +{ + git_buf full_path = GIT_BUF_INIT; + const char *workdir; + int error; + + workdir = git_repository_workdir(repo); + assert(workdir); /* error to call this on bare repo */ + + if (git_buf_joinpath(&full_path, workdir, path) < 0) { + git_buf_free(&full_path); + return -1; + } + + error = blob_create_internal(oid, repo, git_buf_cstr(&full_path)); + git_buf_free(&full_path); return error; } +int git_blob_create_fromdisk(git_oid *oid, git_repository *repo, const char *path) +{ + int error; + git_buf full_path = GIT_BUF_INIT; + + if ((error = git_path_prettify(&full_path, path, NULL)) < 0) { + git_buf_free(&full_path); + return error; + } + + error = blob_create_internal(oid, repo, git_buf_cstr(&full_path)); + + git_buf_free(&full_path); + return error; +} diff --git a/tests-clar/object/blob/write.c b/tests-clar/object/blob/write.c new file mode 100644 index 000000000..160379511 --- /dev/null +++ b/tests-clar/object/blob/write.c @@ -0,0 +1,68 @@ +#include "clar_libgit2.h" +#include "buffer.h" +#include "posix.h" +#include "path.h" +#include "fileops.h" + +static git_repository *repo; + +#define WORKDIR "empty_standard_repo" +#define BARE_REPO "testrepo.git" +#define ELSEWHERE "elsewhere" + +typedef int (*blob_creator_fn)( + git_oid *, + git_repository *, + const char *); + +static void assert_blob_creation(const char *path_to_file, const char *blob_from_path, blob_creator_fn creator) +{ + git_oid oid; + cl_git_mkfile(path_to_file, "1..2...3... Can you hear me?\n"); + + cl_must_pass(creator(&oid, repo, blob_from_path)); + cl_assert(git_oid_streq(&oid, "da5e4f20c91c81b44a7e298f3d3fb3fe2f178e32") == 0); +} + +void test_object_blob_write__can_create_a_blob_in_a_standard_repo_from_a_file_located_in_the_working_directory(void) +{ + repo = cl_git_sandbox_init(WORKDIR); + + assert_blob_creation(WORKDIR "/test.txt", "test.txt", &git_blob_create_fromfile); + + cl_git_sandbox_cleanup(); +} + +void test_object_blob_write__can_create_a_blob_in_a_standard_repo_from_a_absolute_filepath_pointing_outside_of_the_working_directory(void) +{ + git_buf full_path = GIT_BUF_INIT; + + repo = cl_git_sandbox_init(WORKDIR); + + cl_must_pass(p_mkdir(ELSEWHERE, 0777)); + cl_must_pass(git_path_prettify_dir(&full_path, ELSEWHERE, NULL)); + cl_must_pass(git_buf_puts(&full_path, "test.txt")); + + assert_blob_creation(ELSEWHERE "/test.txt", git_buf_cstr(&full_path), &git_blob_create_fromdisk); + + git_buf_free(&full_path); + cl_must_pass(git_futils_rmdir_r(ELSEWHERE, GIT_DIRREMOVAL_FILES_AND_DIRS)); + cl_git_sandbox_cleanup(); +} + +void test_object_blob_write__can_create_a_blob_in_a_bare_repo_from_a_absolute_filepath(void) +{ + git_buf full_path = GIT_BUF_INIT; + + repo = cl_git_sandbox_init(BARE_REPO); + + cl_must_pass(p_mkdir(ELSEWHERE, 0777)); + cl_must_pass(git_path_prettify_dir(&full_path, ELSEWHERE, NULL)); + cl_must_pass(git_buf_puts(&full_path, "test.txt")); + + assert_blob_creation(ELSEWHERE "/test.txt", git_buf_cstr(&full_path), &git_blob_create_fromdisk); + + git_buf_free(&full_path); + cl_must_pass(git_futils_rmdir_r(ELSEWHERE, GIT_DIRREMOVAL_FILES_AND_DIRS)); + cl_git_sandbox_cleanup(); +} From f0b350eb52866a88e762760d4d169beb60370fb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 7 May 2012 11:48:39 +0200 Subject: [PATCH 2/2] tests: make sure we clean up in objects/blob/write.c --- tests-clar/object/blob/write.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests-clar/object/blob/write.c b/tests-clar/object/blob/write.c index 160379511..722c7b956 100644 --- a/tests-clar/object/blob/write.c +++ b/tests-clar/object/blob/write.c @@ -15,6 +15,11 @@ typedef int (*blob_creator_fn)( git_repository *, const char *); +void test_object_blob_write__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + static void assert_blob_creation(const char *path_to_file, const char *blob_from_path, blob_creator_fn creator) { git_oid oid; @@ -29,8 +34,6 @@ void test_object_blob_write__can_create_a_blob_in_a_standard_repo_from_a_file_lo repo = cl_git_sandbox_init(WORKDIR); assert_blob_creation(WORKDIR "/test.txt", "test.txt", &git_blob_create_fromfile); - - cl_git_sandbox_cleanup(); } void test_object_blob_write__can_create_a_blob_in_a_standard_repo_from_a_absolute_filepath_pointing_outside_of_the_working_directory(void) @@ -47,7 +50,6 @@ void test_object_blob_write__can_create_a_blob_in_a_standard_repo_from_a_absolut git_buf_free(&full_path); cl_must_pass(git_futils_rmdir_r(ELSEWHERE, GIT_DIRREMOVAL_FILES_AND_DIRS)); - cl_git_sandbox_cleanup(); } void test_object_blob_write__can_create_a_blob_in_a_bare_repo_from_a_absolute_filepath(void) @@ -64,5 +66,4 @@ void test_object_blob_write__can_create_a_blob_in_a_bare_repo_from_a_absolute_fi git_buf_free(&full_path); cl_must_pass(git_futils_rmdir_r(ELSEWHERE, GIT_DIRREMOVAL_FILES_AND_DIRS)); - cl_git_sandbox_cleanup(); }