meta: replace bluelib with fx
This commit is contained in:
@@ -0,0 +1,930 @@
|
||||
#include "db.h"
|
||||
|
||||
#include <fx/io/directory.h>
|
||||
#include <ropkg/repo-mgmt.h>
|
||||
#include <ropkg/status.h>
|
||||
#include <sqlite3.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct ropkg_repo_mgmt {
|
||||
sqlite3 *repo_meta;
|
||||
sqlite3 *repo_packages;
|
||||
|
||||
fx_directory *repo_root;
|
||||
fx_directory *repo_pool;
|
||||
fx_directory *repo_news;
|
||||
fx_directory *repo_channel;
|
||||
};
|
||||
|
||||
struct ropkg_repo_mgmt_channel {
|
||||
sqlite3 *c_meta;
|
||||
|
||||
fx_directory *c_root;
|
||||
fx_directory *c_news;
|
||||
};
|
||||
|
||||
struct ropkg_repo_mgmt_component {
|
||||
sqlite3 *c_meta;
|
||||
sqlite3 *c_packages;
|
||||
|
||||
fx_directory *c_root;
|
||||
fx_directory *c_news;
|
||||
};
|
||||
|
||||
static fx_result init_repo_meta_db(sqlite3 *db)
|
||||
{
|
||||
const char *sql = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int err = 0;
|
||||
|
||||
sql = "CREATE TABLE repo ("
|
||||
"name TEXT PRIMARY KEY,"
|
||||
"description TEXT NOT NULL);";
|
||||
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
err = sqlite3_step(stmt);
|
||||
if (err != SQLITE_DONE) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
sql = "CREATE TABLE architecture ("
|
||||
"name TEXT PRIMARY KEY);";
|
||||
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
err = sqlite3_step(stmt);
|
||||
if (err != SQLITE_DONE) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
sql = "CREATE TABLE channel ("
|
||||
"name TEXT PRIMARY KEY);";
|
||||
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
err = sqlite3_step(stmt);
|
||||
if (err != SQLITE_DONE) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
sql = "CREATE TABLE news ("
|
||||
"id NUMBER PRIMARY KEY,"
|
||||
"title TEXT NOT NULL,"
|
||||
"importance TEXT,"
|
||||
"category TEXT,"
|
||||
"publish_date TEXT NOT NULL,"
|
||||
"filename TEXT NOT NULL);";
|
||||
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
err = sqlite3_step(stmt);
|
||||
if (err != SQLITE_DONE) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static fx_result init_repo_packages_db(sqlite3 *db)
|
||||
{
|
||||
const char *sql = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int err = 0;
|
||||
|
||||
sql = "CREATE TABLE package ("
|
||||
"name TEXT NOT NULL,"
|
||||
"arch TEXT NOT NULL,"
|
||||
"version TEXT NOT NULL,"
|
||||
"description TEXT,"
|
||||
"priority TEXT,"
|
||||
"category TEXT,"
|
||||
"maintainer TEXT NOT NULL,"
|
||||
"provides TEXT,"
|
||||
"dependencies TEXT,"
|
||||
"recommends TEXT,"
|
||||
"suggests TEXT,"
|
||||
"conflicts TEXT,"
|
||||
"enhances TEXT,"
|
||||
"filename TEXT UNIQUE,"
|
||||
"PRIMARY KEY(name, arch, version));";
|
||||
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
err = sqlite3_step(stmt);
|
||||
if (err != SQLITE_DONE) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static fx_result init_channel_meta_db(sqlite3 *db)
|
||||
{
|
||||
const char *sql = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int err = 0;
|
||||
|
||||
sql = "CREATE TABLE channel ("
|
||||
"name TEXT PRIMARY KEY,"
|
||||
"description TEXT NOT NULL);";
|
||||
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
err = sqlite3_step(stmt);
|
||||
if (err != SQLITE_DONE) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
sql = "CREATE TABLE component ("
|
||||
"name TEXT PRIMARY KEY);";
|
||||
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
err = sqlite3_step(stmt);
|
||||
if (err != SQLITE_DONE) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
sql = "CREATE TABLE news ("
|
||||
"id NUMBER PRIMARY KEY,"
|
||||
"title TEXT NOT NULL,"
|
||||
"importance TEXT,"
|
||||
"category TEXT,"
|
||||
"publish_date TEXT NOT NULL,"
|
||||
"filename TEXT NOT NULL);";
|
||||
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
err = sqlite3_step(stmt);
|
||||
if (err != SQLITE_DONE) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static fx_result init_component_meta_db(sqlite3 *db)
|
||||
{
|
||||
const char *sql = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int err = 0;
|
||||
|
||||
sql = "CREATE TABLE component ("
|
||||
"name TEXT PRIMARY KEY,"
|
||||
"description TEXT NOT NULL);";
|
||||
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
err = sqlite3_step(stmt);
|
||||
if (err != SQLITE_DONE) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
sql = "CREATE TABLE news ("
|
||||
"id NUMBER PRIMARY KEY,"
|
||||
"title TEXT NOT NULL,"
|
||||
"importance TEXT,"
|
||||
"category TEXT,"
|
||||
"publish_date TEXT NOT NULL,"
|
||||
"filename TEXT NOT NULL);";
|
||||
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
err = sqlite3_step(stmt);
|
||||
if (err != SQLITE_DONE) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static fx_result init_component_packages_db(sqlite3 *db)
|
||||
{
|
||||
const char *sql = NULL;
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int err = 0;
|
||||
|
||||
sql = "CREATE TABLE package ("
|
||||
"name TEXT NOT NULL,"
|
||||
"arch TEXT NOT NULL,"
|
||||
"version TEXT NOT NULL,"
|
||||
"description TEXT,"
|
||||
"priority TEXT,"
|
||||
"category TEXT,"
|
||||
"maintainer TEXT NOT NULL,"
|
||||
"provides TEXT,"
|
||||
"dependencies TEXT,"
|
||||
"recommends TEXT,"
|
||||
"suggests TEXT,"
|
||||
"conflicts TEXT,"
|
||||
"enhances TEXT,"
|
||||
"repo_name TEXT NOT NULL,"
|
||||
"channel_name TEXT NOT NULL,"
|
||||
"PRIMARY KEY(name, arch, version, repo_name, channel_name));";
|
||||
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
err = sqlite3_step(stmt);
|
||||
if (err != SQLITE_DONE) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
fx_result ropkg_repo_mgmt_open(const char *path, struct ropkg_repo_mgmt **out)
|
||||
{
|
||||
struct ropkg_repo_mgmt *repo = malloc(sizeof *repo);
|
||||
if (!repo) {
|
||||
return FX_RESULT_ERR(NO_MEMORY);
|
||||
}
|
||||
|
||||
memset(repo, 0x0, sizeof *repo);
|
||||
|
||||
fx_result result = fx_directory_open(
|
||||
NULL,
|
||||
FX_RV_PATH(path),
|
||||
0,
|
||||
&repo->repo_root);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_close(repo);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = fx_directory_open(
|
||||
repo->repo_root,
|
||||
FX_RV_PATH("pool"),
|
||||
0,
|
||||
&repo->repo_pool);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_close(repo);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = fx_directory_open(
|
||||
repo->repo_root,
|
||||
FX_RV_PATH("news"),
|
||||
0,
|
||||
&repo->repo_news);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_close(repo);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = fx_directory_open(
|
||||
repo->repo_root,
|
||||
FX_RV_PATH("channel"),
|
||||
0,
|
||||
&repo->repo_channel);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_close(repo);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = open_database(
|
||||
repo->repo_root,
|
||||
"meta.rodb",
|
||||
SQLITE_OPEN_READWRITE,
|
||||
&repo->repo_meta);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_close(repo);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
*out = repo;
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
fx_result ropkg_repo_mgmt_create(const char *path, struct ropkg_repo_mgmt **out)
|
||||
{
|
||||
struct ropkg_repo_mgmt *repo = malloc(sizeof *repo);
|
||||
if (!repo) {
|
||||
return FX_RESULT_ERR(NO_MEMORY);
|
||||
}
|
||||
|
||||
memset(repo, 0x0, sizeof *repo);
|
||||
|
||||
fx_result result = fx_directory_open(
|
||||
NULL,
|
||||
FX_RV_PATH(path),
|
||||
FX_DIRECTORY_OPEN_CREATE,
|
||||
&repo->repo_root);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_close(repo);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = fx_directory_open(
|
||||
repo->repo_root,
|
||||
FX_RV_PATH("pool"),
|
||||
FX_DIRECTORY_OPEN_CREATE,
|
||||
&repo->repo_pool);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_close(repo);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = fx_directory_open(
|
||||
repo->repo_root,
|
||||
FX_RV_PATH("news"),
|
||||
FX_DIRECTORY_OPEN_CREATE,
|
||||
&repo->repo_news);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_close(repo);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = fx_directory_open(
|
||||
repo->repo_root,
|
||||
FX_RV_PATH("channel"),
|
||||
FX_DIRECTORY_OPEN_CREATE,
|
||||
&repo->repo_channel);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_close(repo);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = open_database(
|
||||
repo->repo_root,
|
||||
"meta.rodb",
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
|
||||
&repo->repo_meta);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_close(repo);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = init_repo_meta_db(repo->repo_meta);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_close(repo);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = open_database(
|
||||
repo->repo_root,
|
||||
"packages.rodb",
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
|
||||
&repo->repo_meta);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_close(repo);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = init_repo_packages_db(repo->repo_meta);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_close(repo);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
*out = repo;
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
void ropkg_repo_mgmt_close(struct ropkg_repo_mgmt *repo)
|
||||
{
|
||||
if (repo->repo_meta) {
|
||||
sqlite3_close(repo->repo_meta);
|
||||
repo->repo_meta = NULL;
|
||||
}
|
||||
|
||||
if (repo->repo_pool) {
|
||||
fx_directory_unref(repo->repo_pool);
|
||||
repo->repo_pool = NULL;
|
||||
}
|
||||
|
||||
if (repo->repo_news) {
|
||||
fx_directory_unref(repo->repo_news);
|
||||
repo->repo_news = NULL;
|
||||
}
|
||||
|
||||
if (repo->repo_root) {
|
||||
fx_directory_unref(repo->repo_root);
|
||||
repo->repo_root = NULL;
|
||||
}
|
||||
|
||||
free(repo);
|
||||
}
|
||||
|
||||
static fx_result channel_exists(
|
||||
struct ropkg_repo_mgmt *repo,
|
||||
const char *name,
|
||||
bool *exists)
|
||||
{
|
||||
const char *sql = "SELECT * FROM channel WHERE name = ?;";
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int err = sqlite3_prepare_v2(repo->repo_meta, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(repo->repo_meta));
|
||||
}
|
||||
|
||||
sqlite3_bind_text(stmt, 1, name, strlen(name), NULL);
|
||||
|
||||
err = sqlite3_step(stmt);
|
||||
switch (err) {
|
||||
case SQLITE_ROW:
|
||||
*exists = true;
|
||||
break;
|
||||
case SQLITE_ERROR:
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(repo->repo_meta));
|
||||
default:
|
||||
*exists = false;
|
||||
break;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static fx_result component_exists(
|
||||
struct ropkg_repo_mgmt_channel *channel,
|
||||
const char *name,
|
||||
bool *exists)
|
||||
{
|
||||
const char *sql = "SELECT * FROM component WHERE name = ?;";
|
||||
sqlite3_stmt *stmt = NULL;
|
||||
int err = sqlite3_prepare_v2(channel->c_meta, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(channel->c_meta));
|
||||
}
|
||||
|
||||
sqlite3_bind_text(stmt, 1, name, strlen(name), NULL);
|
||||
|
||||
err = sqlite3_step(stmt);
|
||||
switch (err) {
|
||||
case SQLITE_ROW:
|
||||
*exists = true;
|
||||
break;
|
||||
case SQLITE_ERROR:
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(channel->c_meta));
|
||||
default:
|
||||
*exists = false;
|
||||
break;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
fx_result ropkg_repo_mgmt_open_channel(
|
||||
struct ropkg_repo_mgmt *repo,
|
||||
const char *name,
|
||||
struct ropkg_repo_mgmt_channel **out)
|
||||
{
|
||||
bool exists;
|
||||
fx_result result = channel_exists(repo, name, &exists);
|
||||
if (fx_result_is_error(result)) {
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
return fx_error_with_code(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_NO_CHANNEL);
|
||||
}
|
||||
|
||||
struct ropkg_repo_mgmt_channel *channel = malloc(sizeof *channel);
|
||||
if (!channel) {
|
||||
return FX_RESULT_ERR(NO_MEMORY);
|
||||
}
|
||||
|
||||
memset(channel, 0x0, sizeof *channel);
|
||||
|
||||
result = fx_directory_open(
|
||||
repo->repo_channel,
|
||||
FX_RV_PATH(name),
|
||||
0,
|
||||
&channel->c_root);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_channel_close(channel);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = fx_directory_open(
|
||||
channel->c_root,
|
||||
FX_RV_PATH("news"),
|
||||
0,
|
||||
&channel->c_news);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_channel_close(channel);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = open_database(
|
||||
channel->c_root,
|
||||
"meta.rodb",
|
||||
SQLITE_OPEN_READWRITE,
|
||||
&channel->c_meta);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_channel_close(channel);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
*out = channel;
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
fx_result ropkg_repo_mgmt_create_channel(
|
||||
struct ropkg_repo_mgmt *repo,
|
||||
const char *name,
|
||||
struct ropkg_repo_mgmt_channel **out)
|
||||
{
|
||||
struct ropkg_repo_mgmt_channel *channel = malloc(sizeof *channel);
|
||||
if (!channel) {
|
||||
return FX_RESULT_ERR(NO_MEMORY);
|
||||
}
|
||||
|
||||
memset(channel, 0x0, sizeof *channel);
|
||||
|
||||
fx_result result = fx_directory_open(
|
||||
repo->repo_channel,
|
||||
FX_RV_PATH(name),
|
||||
FX_DIRECTORY_OPEN_CREATE,
|
||||
&channel->c_root);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_channel_close(channel);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = fx_directory_open(
|
||||
channel->c_root,
|
||||
FX_RV_PATH("news"),
|
||||
FX_DIRECTORY_OPEN_CREATE,
|
||||
&channel->c_news);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_channel_close(channel);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = open_database(
|
||||
channel->c_root,
|
||||
"meta.rodb",
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
|
||||
&channel->c_meta);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_channel_close(channel);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = init_channel_meta_db(channel->c_meta);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_channel_close(channel);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
const char *sql = "INSERT INTO channel (name) VALUES (?);";
|
||||
sqlite3_stmt *stmt;
|
||||
int err = sqlite3_prepare(repo->repo_meta, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
ropkg_repo_mgmt_channel_close(channel);
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(repo->repo_meta));
|
||||
}
|
||||
|
||||
sqlite3_bind_text(stmt, 1, name, strlen(name), SQLITE_STATIC);
|
||||
err = sqlite3_step(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
if (err != SQLITE_DONE) {
|
||||
ropkg_repo_mgmt_channel_close(channel);
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(repo->repo_meta));
|
||||
}
|
||||
|
||||
*out = channel;
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
void ropkg_repo_mgmt_channel_close(struct ropkg_repo_mgmt_channel *channel)
|
||||
{
|
||||
if (channel->c_meta) {
|
||||
sqlite3_close(channel->c_meta);
|
||||
channel->c_meta = NULL;
|
||||
}
|
||||
|
||||
if (channel->c_news) {
|
||||
fx_directory_unref(channel->c_news);
|
||||
channel->c_news = NULL;
|
||||
}
|
||||
|
||||
if (channel->c_root) {
|
||||
fx_directory_unref(channel->c_root);
|
||||
channel->c_root = NULL;
|
||||
}
|
||||
|
||||
free(channel);
|
||||
}
|
||||
|
||||
fx_result ropkg_repo_mgmt_channel_open_component(
|
||||
struct ropkg_repo_mgmt_channel *channel,
|
||||
const char *name,
|
||||
struct ropkg_repo_mgmt_component **out)
|
||||
{
|
||||
bool exists;
|
||||
fx_result result = component_exists(channel, name, &exists);
|
||||
if (fx_result_is_error(result)) {
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
return fx_error_with_code(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_NO_COMPONENT);
|
||||
}
|
||||
|
||||
struct ropkg_repo_mgmt_component *component = malloc(sizeof *component);
|
||||
if (!component) {
|
||||
return FX_RESULT_ERR(NO_MEMORY);
|
||||
}
|
||||
|
||||
memset(component, 0x0, sizeof *component);
|
||||
|
||||
result = fx_directory_open(
|
||||
channel->c_root,
|
||||
FX_RV_PATH(name),
|
||||
0,
|
||||
&component->c_root);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_component_close(component);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = fx_directory_open(
|
||||
component->c_root,
|
||||
FX_RV_PATH("news"),
|
||||
0,
|
||||
&component->c_news);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_component_close(component);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = open_database(
|
||||
component->c_root,
|
||||
"meta.rodb",
|
||||
SQLITE_OPEN_READWRITE,
|
||||
&component->c_meta);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_component_close(component);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = open_database(
|
||||
component->c_root,
|
||||
"packages.rodb",
|
||||
SQLITE_OPEN_READWRITE,
|
||||
&component->c_packages);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_component_close(component);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
*out = component;
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
fx_result ropkg_repo_mgmt_channel_create_component(
|
||||
struct ropkg_repo_mgmt_channel *channel,
|
||||
const char *name,
|
||||
struct ropkg_repo_mgmt_component **out)
|
||||
{
|
||||
struct ropkg_repo_mgmt_component *component = malloc(sizeof *component);
|
||||
if (!channel) {
|
||||
return FX_RESULT_ERR(NO_MEMORY);
|
||||
}
|
||||
|
||||
memset(component, 0x0, sizeof *component);
|
||||
|
||||
fx_result result = fx_directory_open(
|
||||
channel->c_root,
|
||||
FX_RV_PATH(name),
|
||||
FX_DIRECTORY_OPEN_CREATE,
|
||||
&component->c_root);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_component_close(component);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = fx_directory_open(
|
||||
component->c_root,
|
||||
FX_RV_PATH("news"),
|
||||
FX_DIRECTORY_OPEN_CREATE,
|
||||
&component->c_news);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_component_close(component);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = open_database(
|
||||
component->c_root,
|
||||
"meta.rodb",
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
|
||||
&component->c_meta);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_component_close(component);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = init_component_meta_db(component->c_meta);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_component_close(component);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = open_database(
|
||||
component->c_root,
|
||||
"packages.rodb",
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
|
||||
&component->c_packages);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_component_close(component);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
result = init_component_packages_db(component->c_packages);
|
||||
if (fx_result_is_error(result)) {
|
||||
ropkg_repo_mgmt_component_close(component);
|
||||
return fx_result_propagate(result);
|
||||
}
|
||||
|
||||
const char *sql = "INSERT INTO component (name) VALUES (?);";
|
||||
sqlite3_stmt *stmt;
|
||||
int err = sqlite3_prepare(channel->c_meta, sql, -1, &stmt, NULL);
|
||||
if (err != SQLITE_OK) {
|
||||
ropkg_repo_mgmt_channel_close(channel);
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(channel->c_meta));
|
||||
}
|
||||
|
||||
sqlite3_bind_text(stmt, 1, name, strlen(name), SQLITE_STATIC);
|
||||
err = sqlite3_step(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
if (err != SQLITE_DONE) {
|
||||
ropkg_repo_mgmt_channel_close(channel);
|
||||
return fx_error_with_string(
|
||||
ROPKG_ERROR_VENDOR,
|
||||
ROPKG_ERR_DB_OP_FAILED,
|
||||
sqlite3_errmsg(channel->c_meta));
|
||||
}
|
||||
|
||||
*out = component;
|
||||
return FX_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
void ropkg_repo_mgmt_component_close(
|
||||
struct ropkg_repo_mgmt_component *component)
|
||||
{
|
||||
if (component->c_packages) {
|
||||
sqlite3_close(component->c_packages);
|
||||
component->c_packages = NULL;
|
||||
}
|
||||
|
||||
if (component->c_meta) {
|
||||
sqlite3_close(component->c_meta);
|
||||
component->c_meta = NULL;
|
||||
}
|
||||
|
||||
if (component->c_news) {
|
||||
fx_directory_unref(component->c_news);
|
||||
component->c_news = NULL;
|
||||
}
|
||||
|
||||
if (component->c_root) {
|
||||
fx_directory_unref(component->c_root);
|
||||
component->c_root = NULL;
|
||||
}
|
||||
|
||||
free(component);
|
||||
}
|
||||
Reference in New Issue
Block a user