summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornulltoken <emeric.fermas@gmail.com>2012-05-06 21:00:20 +0200
committernulltoken <emeric.fermas@gmail.com>2012-05-13 11:28:49 +0200
commit6ca9643c967cb2de89ba360eb226ec49d27345a4 (patch)
tree4bbd3f42863be71000333585e68b220a990ba80b
parentb72969e0643cb561b42aceec4d1a18ce9c782c09 (diff)
downloadlibgit2-6ca9643c967cb2de89ba360eb226ec49d27345a4.tar.gz
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.
-rw-r--r--include/git2/blob.h12
-rw-r--r--src/blob.c56
-rw-r--r--tests-clar/object/blob/write.c68
3 files changed, 120 insertions, 16 deletions
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();
+}