Commit 6ca9643c by nulltoken

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.
parent b72969e0
......@@ -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
......
......@@ -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;
}
#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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment