Commit 4d7ec76c by Edward Thomson

odb: add git_odb_loose_backend_options

Move the arguments to `git_odb_loose` into an options structure.
parent dbccfc20
...@@ -34,25 +34,55 @@ GIT_BEGIN_DECL ...@@ -34,25 +34,55 @@ GIT_BEGIN_DECL
*/ */
GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **out, const char *objects_dir); GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **out, const char *objects_dir);
typedef enum {
GIT_ODB_BACKEND_LOOSE_FSYNC = (1 << 0)
} git_odb_backend_loose_flag_t;
/** Options for configuring a loose object backend. */
typedef struct {
unsigned int version; /**< version for the struct */
/** A combination of the `git_odb_backend_loose_flag_t` types. */
uint32_t flags;
/**
* zlib compression level to use (0-9), where 1 is the fastest
* at the expense of larger files, and 9 produces the best
* compression at the expense of speed. 0 indicates that no
* compression should be performed. -1 is the default (currently
* optimizing for speed).
*/
int compression_level;
/** Permissions to use creating a directory or 0 for defaults */
unsigned int dir_mode;
/** Permissions to use creating a file or 0 for defaults */
unsigned int file_mode;
} git_odb_backend_loose_options;
/* The current version of the diff options structure */
#define GIT_ODB_BACKEND_LOOSE_OPTIONS_VERSION 1
/* Stack initializer for diff options. Alternatively use
* `git_diff_options_init` programmatic initialization.
*/
#define GIT_ODB_BACKEND_LOOSE_OPTIONS_INIT \
{ GIT_ODB_BACKEND_LOOSE_OPTIONS_VERSION, 0, -1 }
/** /**
* Create a backend for loose objects * Create a backend for loose objects
* *
* @param out location to store the odb backend pointer * @param out location to store the odb backend pointer
* @param objects_dir the Git repository's objects directory * @param objects_dir the Git repository's objects directory
* @param compression_level zlib compression level to use * @param opts options for the loose object backend or NULL
* @param do_fsync whether to do an fsync() after writing
* @param dir_mode permissions to use creating a directory or 0 for defaults
* @param file_mode permissions to use creating a file or 0 for defaults
* *
* @return 0 or an error code * @return 0 or an error code
*/ */
GIT_EXTERN(int) git_odb_backend_loose( GIT_EXTERN(int) git_odb_backend_loose(
git_odb_backend **out, git_odb_backend **out,
const char *objects_dir, const char *objects_dir,
int compression_level, git_odb_backend_loose_options *opts);
int do_fsync,
unsigned int dir_mode,
unsigned int file_mode);
/** /**
* Create a backend out of a single packfile * Create a backend out of a single packfile
......
...@@ -625,6 +625,7 @@ int git_odb__add_default_backends( ...@@ -625,6 +625,7 @@ int git_odb__add_default_backends(
struct stat st; struct stat st;
ino_t inode; ino_t inode;
git_odb_backend *loose, *packed; git_odb_backend *loose, *packed;
git_odb_backend_loose_options loose_opts = GIT_ODB_BACKEND_LOOSE_OPTIONS_INIT;
/* TODO: inodes are not really relevant on Win32, so we need to find /* TODO: inodes are not really relevant on Win32, so we need to find
* a cross-platform workaround for this */ * a cross-platform workaround for this */
...@@ -659,8 +660,11 @@ int git_odb__add_default_backends( ...@@ -659,8 +660,11 @@ int git_odb__add_default_backends(
git_mutex_unlock(&db->lock); git_mutex_unlock(&db->lock);
#endif #endif
if (db->do_fsync)
loose_opts.flags |= GIT_ODB_BACKEND_LOOSE_FSYNC;
/* add the loose object backend */ /* add the loose object backend */
if (git_odb_backend_loose(&loose, objects_dir, -1, db->do_fsync, 0, 0) < 0 || if (git_odb_backend_loose(&loose, objects_dir, &loose_opts) < 0 ||
add_backend_internal(db, loose, git_odb__loose_priority, as_alternates, inode) < 0) add_backend_internal(db, loose, git_odb__loose_priority, as_alternates, inode) < 0)
return -1; return -1;
......
...@@ -46,10 +46,7 @@ typedef struct { ...@@ -46,10 +46,7 @@ typedef struct {
typedef struct loose_backend { typedef struct loose_backend {
git_odb_backend parent; git_odb_backend parent;
int object_zlib_level; /** loose object zlib compression level. */ git_odb_backend_loose_options options;
int fsync_object_files; /** loose object file fsync flag. */
mode_t object_file_mode;
mode_t object_dir_mode;
size_t objects_dirlen; size_t objects_dirlen;
char objects_dir[GIT_FLEX_ARRAY]; char objects_dir[GIT_FLEX_ARRAY];
...@@ -100,7 +97,9 @@ static int object_file_name( ...@@ -100,7 +97,9 @@ static int object_file_name(
static int object_mkdir(const git_str *name, const loose_backend *be) static int object_mkdir(const git_str *name, const loose_backend *be)
{ {
return git_futils_mkdir_relative( return git_futils_mkdir_relative(
name->ptr + be->objects_dirlen, be->objects_dir, be->object_dir_mode, name->ptr + be->objects_dirlen,
be->objects_dir,
be->options.dir_mode,
GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST | GIT_MKDIR_VERIFY_DIR, NULL); GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST | GIT_MKDIR_VERIFY_DIR, NULL);
} }
...@@ -827,9 +826,10 @@ static void loose_backend__writestream_free(git_odb_stream *_stream) ...@@ -827,9 +826,10 @@ static void loose_backend__writestream_free(git_odb_stream *_stream)
static int filebuf_flags(loose_backend *backend) static int filebuf_flags(loose_backend *backend)
{ {
int flags = GIT_FILEBUF_TEMPORARY | int flags = GIT_FILEBUF_TEMPORARY |
(backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT); (backend->options.compression_level << GIT_FILEBUF_DEFLATE_SHIFT);
if (backend->fsync_object_files || git_repository__fsync_gitdir) if ((backend->options.flags & GIT_ODB_BACKEND_LOOSE_FSYNC) ||
git_repository__fsync_gitdir)
flags |= GIT_FILEBUF_FSYNC; flags |= GIT_FILEBUF_FSYNC;
return flags; return flags;
...@@ -865,7 +865,7 @@ static int loose_backend__writestream(git_odb_stream **stream_out, git_odb_backe ...@@ -865,7 +865,7 @@ static int loose_backend__writestream(git_odb_stream **stream_out, git_odb_backe
if (git_str_joinpath(&tmp_path, backend->objects_dir, "tmp_object") < 0 || if (git_str_joinpath(&tmp_path, backend->objects_dir, "tmp_object") < 0 ||
git_filebuf_open(&stream->fbuf, tmp_path.ptr, filebuf_flags(backend), git_filebuf_open(&stream->fbuf, tmp_path.ptr, filebuf_flags(backend),
backend->object_file_mode) < 0 || backend->options.file_mode) < 0 ||
stream->stream.write((git_odb_stream *)stream, hdr, hdrlen) < 0) stream->stream.write((git_odb_stream *)stream, hdr, hdrlen) < 0)
{ {
git_filebuf_cleanup(&stream->fbuf); git_filebuf_cleanup(&stream->fbuf);
...@@ -1083,7 +1083,7 @@ static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, c ...@@ -1083,7 +1083,7 @@ static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, c
if (git_str_joinpath(&final_path, backend->objects_dir, "tmp_object") < 0 || if (git_str_joinpath(&final_path, backend->objects_dir, "tmp_object") < 0 ||
git_filebuf_open(&fbuf, final_path.ptr, filebuf_flags(backend), git_filebuf_open(&fbuf, final_path.ptr, filebuf_flags(backend),
backend->object_file_mode) < 0) backend->options.file_mode) < 0)
{ {
error = -1; error = -1;
goto cleanup; goto cleanup;
...@@ -1126,13 +1126,31 @@ static void loose_backend__free(git_odb_backend *_backend) ...@@ -1126,13 +1126,31 @@ static void loose_backend__free(git_odb_backend *_backend)
git__free(_backend); git__free(_backend);
} }
static void normalize_options(
git_odb_backend_loose_options *opts,
const git_odb_backend_loose_options *given_opts)
{
git_odb_backend_loose_options init = GIT_ODB_BACKEND_LOOSE_OPTIONS_INIT;
if (given_opts)
memcpy(opts, given_opts, sizeof(git_odb_backend_loose_options));
else
memcpy(opts, &init, sizeof(git_odb_backend_loose_options));
if (opts->compression_level < 0)
opts->compression_level = Z_BEST_SPEED;
if (opts->dir_mode == 0)
opts->dir_mode = GIT_OBJECT_DIR_MODE;
if (opts->file_mode == 0)
opts->file_mode = GIT_OBJECT_FILE_MODE;
}
int git_odb_backend_loose( int git_odb_backend_loose(
git_odb_backend **backend_out, git_odb_backend **backend_out,
const char *objects_dir, const char *objects_dir,
int compression_level, git_odb_backend_loose_options *opts)
int do_fsync,
unsigned int dir_mode,
unsigned int file_mode)
{ {
loose_backend *backend; loose_backend *backend;
size_t objects_dirlen, alloclen; size_t objects_dirlen, alloclen;
...@@ -1150,22 +1168,11 @@ int git_odb_backend_loose( ...@@ -1150,22 +1168,11 @@ int git_odb_backend_loose(
backend->parent.version = GIT_ODB_BACKEND_VERSION; backend->parent.version = GIT_ODB_BACKEND_VERSION;
backend->objects_dirlen = objects_dirlen; backend->objects_dirlen = objects_dirlen;
memcpy(backend->objects_dir, objects_dir, objects_dirlen); memcpy(backend->objects_dir, objects_dir, objects_dirlen);
if (backend->objects_dir[backend->objects_dirlen - 1] != '/') if (backend->objects_dir[backend->objects_dirlen - 1] != '/')
backend->objects_dir[backend->objects_dirlen++] = '/'; backend->objects_dir[backend->objects_dirlen++] = '/';
if (compression_level < 0) normalize_options(&backend->options, opts);
compression_level = Z_BEST_SPEED;
if (dir_mode == 0)
dir_mode = GIT_OBJECT_DIR_MODE;
if (file_mode == 0)
file_mode = GIT_OBJECT_FILE_MODE;
backend->object_zlib_level = compression_level;
backend->fsync_object_files = do_fsync;
backend->object_dir_mode = dir_mode;
backend->object_file_mode = file_mode;
backend->parent.read = &loose_backend__read; backend->parent.read = &loose_backend__read;
backend->parent.write = &loose_backend__write; backend->parent.write = &loose_backend__write;
......
...@@ -196,6 +196,7 @@ static void test_write_object_permission( ...@@ -196,6 +196,7 @@ static void test_write_object_permission(
git_oid oid; git_oid oid;
struct stat statbuf; struct stat statbuf;
mode_t mask, os_mask; mode_t mask, os_mask;
git_odb_backend_loose_options opts = GIT_ODB_BACKEND_LOOSE_OPTIONS_INIT;
/* Windows does not return group/user bits from stat, /* Windows does not return group/user bits from stat,
* files are never executable. * files are never executable.
...@@ -209,8 +210,11 @@ static void test_write_object_permission( ...@@ -209,8 +210,11 @@ static void test_write_object_permission(
mask = p_umask(0); mask = p_umask(0);
p_umask(mask); p_umask(mask);
opts.dir_mode = dir_mode;
opts.file_mode = file_mode;
cl_git_pass(git_odb_new(&odb, NULL)); cl_git_pass(git_odb_new(&odb, NULL));
cl_git_pass(git_odb_backend_loose(&backend, "test-objects", -1, 0, dir_mode, file_mode)); cl_git_pass(git_odb_backend_loose(&backend, "test-objects", &opts));
cl_git_pass(git_odb_add_backend(odb, backend, 1)); cl_git_pass(git_odb_add_backend(odb, backend, 1));
cl_git_pass(git_odb_write(&oid, odb, "Test data\n", 10, GIT_OBJECT_BLOB)); cl_git_pass(git_odb_write(&oid, odb, "Test data\n", 10, GIT_OBJECT_BLOB));
...@@ -243,9 +247,16 @@ static void write_object_to_loose_odb(int fsync) ...@@ -243,9 +247,16 @@ static void write_object_to_loose_odb(int fsync)
git_odb *odb; git_odb *odb;
git_odb_backend *backend; git_odb_backend *backend;
git_oid oid; git_oid oid;
git_odb_backend_loose_options opts = GIT_ODB_BACKEND_LOOSE_OPTIONS_INIT;
if (fsync)
opts.flags |= GIT_ODB_BACKEND_LOOSE_FSYNC;
opts.dir_mode = 0777;
opts.file_mode = 0666;
cl_git_pass(git_odb_new(&odb, NULL)); cl_git_pass(git_odb_new(&odb, NULL));
cl_git_pass(git_odb_backend_loose(&backend, "test-objects", -1, fsync, 0777, 0666)); cl_git_pass(git_odb_backend_loose(&backend, "test-objects", &opts));
cl_git_pass(git_odb_add_backend(odb, backend, 1)); cl_git_pass(git_odb_add_backend(odb, backend, 1));
cl_git_pass(git_odb_write(&oid, odb, "Test data\n", 10, GIT_OBJECT_BLOB)); cl_git_pass(git_odb_write(&oid, odb, "Test data\n", 10, GIT_OBJECT_BLOB));
git_odb_free(odb); git_odb_free(odb);
......
...@@ -79,10 +79,11 @@ void test_odb_sorting__override_default_backend_priority(void) ...@@ -79,10 +79,11 @@ void test_odb_sorting__override_default_backend_priority(void)
{ {
git_odb *new_odb; git_odb *new_odb;
git_odb_backend *loose, *packed, *backend; git_odb_backend *loose, *packed, *backend;
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ODB_LOOSE_PRIORITY, 5)); cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ODB_LOOSE_PRIORITY, 5));
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ODB_PACKED_PRIORITY, 3)); cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ODB_PACKED_PRIORITY, 3));
git_odb_backend_pack(&packed, "./testrepo.git/objects"); git_odb_backend_pack(&packed, "./testrepo.git/objects");
git_odb_backend_loose(&loose, "./testrepo.git/objects", -1, 0, 0, 0); git_odb_backend_loose(&loose, "./testrepo.git/objects", NULL);
cl_git_pass(git_odb_open(&new_odb, cl_fixture("testrepo.git/objects"), NULL)); cl_git_pass(git_odb_open(&new_odb, cl_fixture("testrepo.git/objects"), NULL));
cl_assert_equal_sz(2, git_odb_num_backends(new_odb)); cl_assert_equal_sz(2, git_odb_num_backends(new_odb));
......
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