repo: Move the 'init' builtin command to a public API, ostree_repo_create

This continues the goal of making more of ostree accessible by API,
rather than forking out to subprocesses.

https://bugzilla.gnome.org/show_bug.cgi?id=707582
This commit is contained in:
Jasper St. Pierre 2013-09-05 00:14:30 -04:00
parent eb6f017ef8
commit 57d285f619
3 changed files with 131 additions and 84 deletions

View File

@ -52,6 +52,12 @@
* content files zlib-compressed. It is suitable for non-root-owned * content files zlib-compressed. It is suitable for non-root-owned
* repositories that can be served via a static HTTP server. * repositories that can be served via a static HTTP server.
* *
* Creating an #OstreeRepo does not invoke any file I/O, and thus needs
* to be initialized, either from an existing contents or with a new
* repository. If you have an existing repo, use ostree_repo_check()
* to load it from disk and check its validity. To initialize a new
* repository in the given filepath, use ostree_repo_create() instead.
*
* To store content in the repo, first start a transaction with * To store content in the repo, first start a transaction with
* ostree_repo_prepare_transaction(). Then create a * ostree_repo_prepare_transaction(). Then create a
* #OstreeMutableTree, and apply functions such as * #OstreeMutableTree, and apply functions such as
@ -311,6 +317,34 @@ ostree_repo_write_config (OstreeRepo *self,
return ret; return ret;
} }
static gboolean
ostree_repo_mode_to_string (OstreeRepoMode mode,
const char **out_mode,
GError **error)
{
gboolean ret = FALSE;
const char *ret_mode;
switch (mode)
{
case OSTREE_REPO_MODE_BARE:
ret_mode = "bare";
break;
case OSTREE_REPO_MODE_ARCHIVE_Z2:
ret_mode ="archive-z2";
break;
default:
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid mode '%d'", mode);
goto out;
}
ret = TRUE;
*out_mode = ret_mode;
out:
return ret;
}
gboolean gboolean
ostree_repo_mode_from_string (const char *mode, ostree_repo_mode_from_string (const char *mode,
OstreeRepoMode *out_mode, OstreeRepoMode *out_mode,
@ -336,6 +370,81 @@ ostree_repo_mode_from_string (const char *mode,
return ret; return ret;
} }
#define DEFAULT_CONFIG_CONTENTS ("[core]\n" \
"repo_version=1\n")
/**
* ostree_repo_create:
* @self: An #OstreeRepo
* @mode: The mode to store the repository in
* @cancellable: Cancellable
* @error: Error
*
* Create the underlying structure on disk for the
* repository.
*/
gboolean
ostree_repo_create (OstreeRepo *self,
OstreeRepoMode mode,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
GString *config_data = NULL;
gs_unref_object GFile *child = NULL;
gs_unref_object GFile *grandchild = NULL;
const char *mode_str;
if (!ostree_repo_mode_to_string (mode, &mode_str, error))
goto out;
if (!gs_file_ensure_directory (self->repodir, FALSE, cancellable, error))
goto out;
config_data = g_string_new (DEFAULT_CONFIG_CONTENTS);
g_string_append_printf (config_data, "mode=%s\n", mode_str);
if (!g_file_replace_contents (self->config_file,
config_data->str,
config_data->len,
NULL, FALSE, 0, NULL,
cancellable, error))
goto out;
if (!g_file_make_directory (self->objects_dir, cancellable, error))
goto out;
if (!g_file_make_directory (self->tmp_dir, cancellable, error))
goto out;
if (!g_file_make_directory (self->remote_cache_dir, cancellable, error))
goto out;
g_clear_object (&child);
child = g_file_get_child (self->repodir, "refs");
if (!g_file_make_directory (child, cancellable, error))
goto out;
g_clear_object (&grandchild);
grandchild = g_file_get_child (child, "heads");
if (!g_file_make_directory (grandchild, cancellable, error))
goto out;
g_clear_object (&grandchild);
grandchild = g_file_get_child (child, "remotes");
if (!g_file_make_directory (grandchild, cancellable, error))
goto out;
if (!ostree_repo_check (self, error))
goto out;
ret = TRUE;
out:
if (config_data)
g_string_free (config_data, TRUE);
return ret;
}
gboolean gboolean
ostree_repo_check (OstreeRepo *self, GError **error) ostree_repo_check (OstreeRepo *self, GError **error)
{ {

View File

@ -33,16 +33,6 @@ G_BEGIN_DECLS
#define OSTREE_IS_REPO(obj) \ #define OSTREE_IS_REPO(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSTREE_TYPE_REPO)) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSTREE_TYPE_REPO))
GType ostree_repo_get_type (void);
OstreeRepo* ostree_repo_new (GFile *path);
OstreeRepo* ostree_repo_new_default (void);
gboolean ostree_repo_check (OstreeRepo *self, GError **error);
GFile * ostree_repo_get_path (OstreeRepo *self);
/** /**
* OstreeRepoMode: * OstreeRepoMode:
* @OSTREE_REPO_MODE_BARE: Files are stored as themselves; can only be written as root * @OSTREE_REPO_MODE_BARE: Files are stored as themselves; can only be written as root
@ -56,9 +46,24 @@ typedef enum {
OSTREE_REPO_MODE_ARCHIVE_Z2 OSTREE_REPO_MODE_ARCHIVE_Z2
} OstreeRepoMode; } OstreeRepoMode;
gboolean ostree_repo_mode_from_string (const char *mode, gboolean ostree_repo_mode_from_string (const char *mode,
OstreeRepoMode *out_mode, OstreeRepoMode *out_mode,
GError **error); GError **error);
GType ostree_repo_get_type (void);
OstreeRepo* ostree_repo_new (GFile *path);
OstreeRepo* ostree_repo_new_default (void);
gboolean ostree_repo_check (OstreeRepo *self, GError **error);
gboolean ostree_repo_create (OstreeRepo *self,
OstreeRepoMode mode,
GCancellable *cancellable,
GError **error);
GFile * ostree_repo_get_path (OstreeRepo *self);
OstreeRepoMode ostree_repo_get_mode (OstreeRepo *self); OstreeRepoMode ostree_repo_get_mode (OstreeRepo *self);

View File

@ -26,27 +26,19 @@
#include "ostree.h" #include "ostree.h"
#include "libgsystem.h" #include "libgsystem.h"
static char *opt_mode = NULL; static char *opt_mode = "bare";
static GOptionEntry options[] = { static GOptionEntry options[] = {
{ "mode", 0, 0, G_OPTION_ARG_STRING, &opt_mode, "Initialize repository in given mode (bare, archive-z2)", NULL }, { "mode", 0, 0, G_OPTION_ARG_STRING, &opt_mode, "Initialize repository in given mode (bare, archive-z2)", NULL },
{ NULL } { NULL }
}; };
#define DEFAULT_CONFIG_CONTENTS ("[core]\n" \
"repo_version=1\n")
gboolean gboolean
ostree_builtin_init (int argc, char **argv, OstreeRepo *repo, GCancellable *cancellable, GError **error) ostree_builtin_init (int argc, char **argv, OstreeRepo *repo, GCancellable *cancellable, GError **error)
{ {
GOptionContext *context = NULL; GOptionContext *context = NULL;
gboolean ret = FALSE; gboolean ret = FALSE;
const char *mode_str = "bare"; OstreeRepoMode mode;
GFile *repo_path = NULL;
gs_unref_object GFile *child = NULL;
gs_unref_object GFile *grandchild = NULL;
GString *config_data = NULL;
context = g_option_context_new ("- Initialize a new empty repository"); context = g_option_context_new ("- Initialize a new empty repository");
g_option_context_add_main_entries (context, options, NULL); g_option_context_add_main_entries (context, options, NULL);
@ -54,74 +46,15 @@ ostree_builtin_init (int argc, char **argv, OstreeRepo *repo, GCancellable *canc
if (!g_option_context_parse (context, &argc, &argv, error)) if (!g_option_context_parse (context, &argc, &argv, error))
goto out; goto out;
repo_path = ostree_repo_get_path (repo); if (!ostree_repo_mode_from_string (opt_mode, &mode, error))
child = g_file_get_child (repo_path, "config");
config_data = g_string_new (DEFAULT_CONFIG_CONTENTS);
if (opt_mode)
{
OstreeRepoMode mode;
if (!ostree_repo_mode_from_string (opt_mode, &mode, error))
goto out;
mode_str = opt_mode;
}
g_string_append_printf (config_data, "mode=%s\n", mode_str);
if (!g_file_replace_contents (child,
config_data->str,
config_data->len,
NULL, FALSE, 0, NULL,
NULL, error))
goto out; goto out;
g_clear_object (&child); if (!ostree_repo_create (repo, mode, NULL, error))
child = g_file_get_child (repo_path, "objects");
if (!g_file_make_directory (child, NULL, error))
goto out;
g_clear_object (&grandchild);
grandchild = g_file_get_child (child, "pack");
if (!g_file_make_directory (grandchild, NULL, error))
goto out;
g_clear_object (&child);
child = g_file_get_child (repo_path, "tmp");
if (!g_file_make_directory (child, NULL, error))
goto out;
g_clear_object (&child);
child = g_file_get_child (repo_path, "refs");
if (!g_file_make_directory (child, NULL, error))
goto out;
g_clear_object (&grandchild);
grandchild = g_file_get_child (child, "heads");
if (!g_file_make_directory (grandchild, NULL, error))
goto out;
g_clear_object (&grandchild);
grandchild = g_file_get_child (child, "remotes");
if (!g_file_make_directory (grandchild, NULL, error))
goto out;
g_clear_object (&child);
child = g_file_get_child (repo_path, "tags");
if (!g_file_make_directory (child, NULL, error))
goto out;
g_clear_object (&child);
child = g_file_get_child (repo_path, "remote-cache");
if (!g_file_make_directory (child, NULL, error))
goto out;
if (!ostree_repo_check (repo, error))
goto out; goto out;
ret = TRUE; ret = TRUE;
out: out:
if (context) if (context)
g_option_context_free (context); g_option_context_free (context);
if (config_data)
g_string_free (config_data, TRUE);
return ret; return ret;
} }