ropkg: re-organise commands into groups

This commit is contained in:
2025-08-06 22:13:35 +01:00
parent 562c15f685
commit ece47803c4
21 changed files with 1117 additions and 149 deletions

View File

@@ -1,4 +1,4 @@
file(GLOB sources *.c *.h) file(GLOB_RECURSE sources *.c *.h)
add_executable(ropkg ${sources}) add_executable(ropkg ${sources})
target_link_libraries(ropkg target_link_libraries(ropkg

View File

@@ -1,55 +0,0 @@
#include "commands.h"
#include <blue/cmd.h>
enum {
OPT_OUTPATH,
OPT_OUTPATH_PATH,
ARG_RECIPE,
};
static int build(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
return 0;
}
B_COMMAND(CMD_BUILD, CMD_ROOT)
{
B_COMMAND_NAME("build");
B_COMMAND_SHORT_NAME('B');
B_COMMAND_DESC("build a Rosetta package from a recipe");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(build);
B_COMMAND_HELP_OPTION();
B_COMMAND_OPTION(OPT_OUTPATH)
{
B_OPTION_SHORT_NAME('o');
B_OPTION_LONG_NAME("out");
B_OPTION_DESC("the path to save the new package file to");
B_OPTION_ARG(OPT_OUTPATH_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
B_COMMAND_ARG(ARG_RECIPE)
{
B_ARG_NAME("recipe");
B_ARG_DESC("the recipe to build the package from.");
B_ARG_NR_VALUES(1);
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_OPT(OPT_OUTPATH);
B_COMMAND_USAGE_ARG(ARG_RECIPE);
}
}

View File

@@ -3,12 +3,29 @@
enum { enum {
CMD_ROOT, CMD_ROOT,
CMD_CREATE,
CMD_BUILD, CMD_PACKAGE,
CMD_QUERY, CMD_PACKAGE_CREATE,
CMD_EXTRACT, CMD_PACKAGE_BUILD,
CMD_INSTALL, CMD_PACKAGE_EXTRACT,
CMD_COMPARE_VERSION, CMD_PACKAGE_INSTALL,
CMD_PACKAGE_QUERY,
CMD_PACKAGE_QUERY_README,
CMD_PACKAGE_QUERY_MANIFEST,
CMD_PACKAGE_QUERY_SUMMARY,
CMD_PACKAGE_QUERY_LIST,
CMD_VERSION,
CMD_VERSION_COMPARE,
CMD_MANIFEST,
CMD_MANIFEST_CREATE,
CMD_MANIFEST_VALIDATE,
CMD_NEWS,
CMD_NEWS_CREATE,
CMD_NEWS_VALIDATE,
}; };
#endif #endif

View File

@@ -1,19 +1,29 @@
#include "commands.h" #include "commands.h"
#include <blue/cmd.h> #include <blue/cmd.h>
#include <blue/core/error.h>
#include <blue/term/print.h>
B_COMMAND(CMD_ROOT, B_COMMAND_INVALID_ID) B_COMMAND(CMD_ROOT, B_COMMAND_INVALID_ID)
{ {
B_COMMAND_NAME("ropkg"); B_COMMAND_NAME("ropkg");
B_COMMAND_DESC( B_COMMAND_DESC(
"Rosetta package manipulation tool. This tool is used to " "Rosetta package manipulation tool. This tool is used to "
"create, build, and otherwise manipulate individual Rosetta " "create, build, and otherwise manipulate individual Rosetta "
"package files."); "package files.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT); B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_HELP_OPTION(); B_COMMAND_HELP_OPTION();
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_COMMAND_PLACEHOLDER();
}
} }
int main(int argc, const char **argv) int main(int argc, const char **argv)
{ {
b_set_error_report_function(
b_enhanced_error_reporter,
B_ERROR_REPORT_ALL);
return b_command_dispatch(CMD_ROOT, argc, argv); return b_command_dispatch(CMD_ROOT, argc, argv);
} }

106
ropkg/manifest/create.c Normal file
View File

@@ -0,0 +1,106 @@
#include "../commands.h"
#include <blue/cmd.h>
#include <ropkg/pkg-expr.h>
#include <ropkg/version.h>
#include <stdio.h>
enum {
OPT_HEADERS,
OPT_HEADERS_PATH,
OPT_README,
OPT_README_PATH,
OPT_OUTPATH,
OPT_OUTPATH_PATH,
};
static int create(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
const char *headers_path = NULL, *readme_path = NULL, *out_path = NULL;
b_status status = b_arglist_get_string(
opt,
OPT_HEADERS,
OPT_HEADERS_PATH,
0,
&headers_path);
if (!B_OK(status)) {
b_arglist_report_missing_option(opt, OPT_HEADERS);
return -1;
}
status = b_arglist_get_string(
opt,
OPT_README,
OPT_README_PATH,
0,
&headers_path);
if (!B_OK(status)) {
b_arglist_report_missing_option(opt, OPT_README);
return -1;
}
b_arglist_get_string(opt, OPT_OUTPATH, OPT_OUTPATH_PATH, 0, &out_path);
FILE *headers, *readme, *out;
return 0;
}
B_COMMAND(CMD_MANIFEST_CREATE, CMD_MANIFEST)
{
B_COMMAND_NAME("create");
B_COMMAND_SHORT_NAME('C');
B_COMMAND_DESC("create a manifest file.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(create);
B_COMMAND_HELP_OPTION();
B_COMMAND_OPTION(OPT_HEADERS)
{
B_OPTION_LONG_NAME("headers");
B_OPTION_SHORT_NAME('H');
B_OPTION_DESC(
"The path to a json file describing the package "
"manifest headers.");
B_OPTION_ARG(OPT_HEADERS_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
B_COMMAND_OPTION(OPT_README)
{
B_OPTION_LONG_NAME("readme");
B_OPTION_SHORT_NAME('R');
B_OPTION_DESC(
"The path to a plaintext file describing the package.");
B_OPTION_ARG(OPT_README_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
B_COMMAND_OPTION(OPT_OUTPATH)
{
B_OPTION_LONG_NAME("out");
B_OPTION_SHORT_NAME('o');
B_OPTION_DESC(
"The path to write the new manifest file to. If no "
"path is specified, the manifest will be written to "
"standard out.");
B_OPTION_ARG(OPT_OUTPATH_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
}

19
ropkg/manifest/root.c Normal file
View File

@@ -0,0 +1,19 @@
#include "../commands.h"
#include <blue/cmd.h>
#include <blue/core/error.h>
#include <blue/term/print.h>
B_COMMAND(CMD_MANIFEST, CMD_ROOT)
{
B_COMMAND_NAME("manifest");
B_COMMAND_SHORT_NAME('M');
B_COMMAND_DESC("Package manifest inspection and manipulation.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_HELP_OPTION();
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_COMMAND_PLACEHOLDER();
}
}

307
ropkg/manifest/validate.c Normal file
View File

@@ -0,0 +1,307 @@
#include "../commands.h"
#include <blue/cmd.h>
#include <blue/core/error.h>
#include <ropkg/manifest.h>
#include <ropkg/pkg-expr.h>
#include <ropkg/status.h>
#include <ropkg/version.h>
#include <stdio.h>
enum {
ARG_MANIFEST
};
static void print_pkg_expr(const struct ropkg_pkg_expr *expr);
static void print_pkg_expr_and(const struct ropkg_pkg_expr *expr)
{
int count = 0;
const struct ropkg_pkg_expr_and *expr_and
= (const struct ropkg_pkg_expr_and *)expr;
const struct ropkg_pkg_expr *cur
= ropkg_pkg_expr_and_get_left_node(expr_and);
printf("(");
print_pkg_expr(cur);
printf(")");
printf(" AND ");
cur = ropkg_pkg_expr_and_get_right_node(expr_and);
printf("(");
print_pkg_expr(cur);
printf(")");
}
static void print_pkg_expr_or(const struct ropkg_pkg_expr *expr)
{
int count = 0;
const struct ropkg_pkg_expr_or *expr_or
= (const struct ropkg_pkg_expr_or *)expr;
const struct ropkg_pkg_expr *cur
= ropkg_pkg_expr_or_get_left_node(expr_or);
printf("(");
print_pkg_expr(cur);
printf(")");
printf(" OR ");
cur = ropkg_pkg_expr_or_get_right_node(expr_or);
printf("(");
print_pkg_expr(cur);
printf(")");
}
static void print_pkg_expr_pkg(const struct ropkg_pkg_expr *expr)
{
const struct ropkg_pkg_expr_pkg *pkg
= (const struct ropkg_pkg_expr_pkg *)expr;
printf("%s", ropkg_pkg_expr_pkg_get_name(pkg));
const struct ropkg_version *version
= ropkg_pkg_expr_pkg_get_version(pkg);
if (version) {
char s[128];
ropkg_version_to_string(version, s, sizeof s);
printf("[");
switch (ropkg_pkg_expr_pkg_get_version_predicate(pkg)) {
case ROPKG_OP_LESS_THAN:
printf("<");
break;
case ROPKG_OP_LESS_EQUAL:
printf("<=");
break;
case ROPKG_OP_GREATER_THAN:
printf(">");
break;
case ROPKG_OP_GREATER_EQUAL:
printf(">=");
break;
case ROPKG_OP_EQUAL:
printf("=");
break;
default:
break;
}
printf("%s", s);
printf("]");
}
}
static void print_pkg_expr(const struct ropkg_pkg_expr *expr)
{
enum ropkg_pkg_expr_type type = ropkg_pkg_expr_get_type(expr);
switch (type) {
case ROPKG_PKG_EXPR_NODE_PKG:
print_pkg_expr_pkg(expr);
break;
case ROPKG_PKG_EXPR_NODE_AND:
print_pkg_expr_and(expr);
break;
case ROPKG_PKG_EXPR_NODE_OR:
print_pkg_expr_or(expr);
break;
default:
break;
}
}
static b_result validate_pkg_expr_value(
const struct ropkg_manifest_value *value)
{
const char *value_str = ropkg_manifest_value_get_string(value);
if (!value_str) {
return b_error_with_code(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_INVALID_MANIFEST_FORMAT);
}
struct ropkg_pkg_expr *pkg_expr = NULL;
b_result result = ropkg_pkg_expr_parse(value_str, &pkg_expr);
if (b_result_is_error(result)) {
return b_result_propagate(result);
}
print_pkg_expr(pkg_expr);
return B_RESULT_SUCCESS;
}
static b_result validate_version_value(const struct ropkg_manifest_value *value)
{
const char *value_str = ropkg_manifest_value_get_string(value);
if (!value_str) {
return b_error_with_code(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_INVALID_MANIFEST_FORMAT);
}
struct ropkg_version *version = NULL;
enum ropkg_status status = ropkg_version_create(&version);
if (status != ROPKG_SUCCESS) {
return b_error_with_code(ROPKG_ERROR_VENDOR, status);
}
b_result result = ropkg_version_parse(version, value_str);
if (b_result_is_error(result)) {
return b_result_propagate(result);
}
char temp[128];
ropkg_version_to_string(version, temp, sizeof temp);
ropkg_version_destroy(version);
printf("%s", temp);
return B_RESULT_SUCCESS;
}
static b_result validate_string_value(const struct ropkg_manifest_value *value)
{
const char *value_str = ropkg_manifest_value_get_string(value);
if (!value_str) {
return b_error_with_code(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_INVALID_MANIFEST_FORMAT);
}
printf("%s", value_str);
return B_RESULT_SUCCESS;
}
static b_result validate_int_value(const struct ropkg_manifest_value *value)
{
if (ropkg_manifest_value_get_type(value)
!= ROPKG_MANIFEST_VALUE_T_INT) {
return b_error_with_code(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_INVALID_MANIFEST_FORMAT);
}
printf("%zu", ropkg_manifest_value_get_int(value));
return B_RESULT_SUCCESS;
return B_RESULT_SUCCESS;
}
static int validate(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
const char *manifest_path;
b_status status = b_arglist_get_string(
opt,
B_COMMAND_INVALID_ID,
ARG_MANIFEST,
0,
&manifest_path);
if (!B_OK(status)) {
b_arglist_report_missing_args(
opt,
B_COMMAND_INVALID_ID,
ARG_MANIFEST,
0);
return -1;
}
FILE *fp = fopen(manifest_path, "r");
if (!fp) {
b_throw_error_code(ROPKG_ERROR_VENDOR, ROPKG_ERR_NO_ENTRY);
return -1;
}
struct ropkg_manifest *manifest;
enum ropkg_status status2 = ropkg_manifest_create(&manifest);
if (status2 != ROPKG_SUCCESS) {
b_throw_error_code(ROPKG_ERROR_VENDOR, status2);
return -1;
}
b_result result = ropkg_manifest_parse(fp, manifest);
if (b_result_is_error(result)) {
b_throw(result);
return -1;
}
const struct ropkg_manifest_value *value
= ropkg_manifest_get_first_value(manifest);
while (value && b_result_is_success(result)) {
const char *name = ropkg_manifest_value_get_name(value);
enum ropkg_manifest_value_type type
= ropkg_manifest_value_get_type(value);
enum ropkg_manifest_value_id id
= ropkg_manifest_value_get_id(value);
if (name) {
printf("%s ", name);
}
if (id != ROPKG_MANIFEST_VALUE_N_NONE) {
printf("[%d] ", id);
}
printf(": ");
switch (id) {
case ROPKG_MANIFEST_VALUE_N_DEPENDS:
case ROPKG_MANIFEST_VALUE_N_PROVIDES:
case ROPKG_MANIFEST_VALUE_N_RECOMMENDS:
case ROPKG_MANIFEST_VALUE_N_SUGGESTS:
case ROPKG_MANIFEST_VALUE_N_CONFLICTS:
case ROPKG_MANIFEST_VALUE_N_ENHANCES:
result = validate_pkg_expr_value(value);
break;
case ROPKG_MANIFEST_VALUE_N_INSTALLED_SIZE:
result = validate_int_value(value);
break;
case ROPKG_MANIFEST_VALUE_N_VERSION:
result = validate_version_value(value);
break;
default:
result = validate_string_value(value);
break;
}
printf("\n");
value = ropkg_manifest_get_next_value(manifest, value);
}
if (b_result_is_error(result)) {
b_throw(result);
return -1;
}
return 0;
}
B_COMMAND(CMD_MANIFEST_VALIDATE, CMD_MANIFEST)
{
B_COMMAND_NAME("validate");
B_COMMAND_SHORT_NAME('V');
B_COMMAND_DESC("check a manifest file for errors.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(validate);
B_COMMAND_ARG(ARG_MANIFEST)
{
B_ARG_NAME("manifest-path");
B_ARG_DESC("the manifest file to validate");
B_ARG_NR_VALUES(1);
}
B_COMMAND_HELP_OPTION();
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_ARG(ARG_MANIFEST);
}
}

19
ropkg/news/root.c Normal file
View File

@@ -0,0 +1,19 @@
#include "../commands.h"
#include <blue/cmd.h>
#include <blue/core/error.h>
#include <blue/term/print.h>
B_COMMAND(CMD_NEWS, CMD_ROOT)
{
B_COMMAND_NAME("news");
B_COMMAND_SHORT_NAME('N');
B_COMMAND_DESC("News file inspection and manipulation.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_HELP_OPTION();
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_COMMAND_PLACEHOLDER();
}
}

102
ropkg/package/build.c Normal file
View File

@@ -0,0 +1,102 @@
#include "../commands.h"
#include <blue/cmd.h>
enum {
OPT_OUTPATH,
OPT_OUTPATH_PATH,
OPT_SOURCE_DIRECTORY,
OPT_SOURCE_DIRECTORY_PATH,
OPT_EXT_SOURCE_DIRECTORY,
OPT_EXT_SOURCE_DIRECTORY_NAME,
OPT_EXT_SOURCE_DIRECTORY_PATH,
ARG_RECIPE,
};
static int build(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
return 0;
}
B_COMMAND(CMD_PACKAGE_BUILD, CMD_PACKAGE)
{
B_COMMAND_NAME("build");
B_COMMAND_SHORT_NAME('B');
B_COMMAND_DESC("build a Rosetta package from a recipe");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(build);
B_COMMAND_HELP_OPTION();
B_COMMAND_OPTION(OPT_OUTPATH)
{
B_OPTION_SHORT_NAME('o');
B_OPTION_LONG_NAME("out");
B_OPTION_DESC("the path to save the new package file to");
B_OPTION_ARG(OPT_OUTPATH_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
B_COMMAND_OPTION(OPT_SOURCE_DIRECTORY)
{
B_OPTION_SHORT_NAME('s');
B_OPTION_LONG_NAME("source-dir");
B_OPTION_DESC(
"the source directory to build the package from. if no "
"source directory is specified, the recipe will "
"download the sources automatically.");
B_OPTION_ARG(OPT_SOURCE_DIRECTORY_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
B_COMMAND_OPTION(OPT_EXT_SOURCE_DIRECTORY)
{
B_OPTION_SHORT_NAME('S');
B_OPTION_LONG_NAME("named-source-dir");
B_OPTION_DESC(
"a source directory to build the package from. if no "
"source directory is specified, the recipe will "
"download the sources automatically. use this option "
"if the recipe requires more than one separate source "
"directory.");
B_OPTION_ARG(OPT_EXT_SOURCE_DIRECTORY_NAME)
{
B_ARG_NAME("name");
B_ARG_NR_VALUES(1);
}
B_OPTION_ARG(OPT_EXT_SOURCE_DIRECTORY_PATH)
{
B_ARG_NAME("path");
B_ARG_NR_VALUES(1);
}
}
B_COMMAND_ARG(ARG_RECIPE)
{
B_ARG_NAME("recipe");
B_ARG_DESC("the recipe to build the package from.");
B_ARG_NR_VALUES(1);
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_OPT(OPT_OUTPATH);
B_COMMAND_USAGE_ARG(ARG_RECIPE);
}
}

View File

@@ -1,11 +1,13 @@
#include "commands.h" #include "../commands.h"
#include <blue/cmd.h> #include <blue/cmd.h>
#include <blue/compress/cstream.h>
#include <blue/compress/function.h>
#include <blue/core/error.h>
#include <blue/io/directory.h> #include <blue/io/directory.h>
#include <blue/term/print.h> #include <blue/term/print.h>
#include <errno.h> #include <errno.h>
#include <ropkg/compress.h> #include <ropkg/manifest.h>
#include <ropkg/stream.h>
#include <ropkg/writer.h> #include <ropkg/writer.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -41,14 +43,17 @@ static int add_file_to_archive_ex(
const char *dest) const char *dest)
{ {
b_file *fp; b_file *fp;
b_status status = b_file_open( b_result result = b_file_open(
src_dir, src_dir,
src, src,
B_FILE_READ_ONLY | B_FILE_BINARY, B_FILE_READ_ONLY | B_FILE_BINARY,
&fp); &fp);
if (!fp) { if (!fp) {
b_err("cannot open file '%s'", src); b_throw_error_with_template_caused_by_error(
b_i("reason: %s", b_status_to_string(status)); ROPKG_ERROR_VENDOR,
ROPKG_ERR_DIR_OPEN_FAILED,
result,
B_ERROR_PARAM("filepath", b_path_ptr(src)));
return -1; return -1;
} }
@@ -63,7 +68,7 @@ static int add_file_to_archive_ex(
int c; int c;
while (1) { while (1) {
size_t r; size_t r;
status = b_file_read(fp, offset, sizeof buf, buf, &r); b_status status = b_file_read(fp, offset, sizeof buf, buf, &r);
if (!B_OK(status)) { if (!B_OK(status)) {
break; break;
} }
@@ -97,7 +102,7 @@ static int add_file_to_archive(
static int add_data_archive( static int add_data_archive(
const b_arglist *args, const b_arglist *args,
struct ropkg_stream *stream, struct b_cstream *stream,
struct ropkg_writer *pkg) struct ropkg_writer *pkg)
{ {
const char *data_path_cstr; const char *data_path_cstr;
@@ -108,16 +113,23 @@ static int add_data_archive(
0, 0,
&data_path_cstr); &data_path_cstr);
if (!B_OK(bstatus)) { if (!B_OK(bstatus)) {
b_arglist_report_missing_option(args, OPT_MANIFEST); b_arglist_report_missing_args(
args,
B_COMMAND_INVALID_ID,
ARG_SOURCE_DIR,
0);
return -1; return -1;
} }
b_path *data_path = b_path_create_from_cstr(data_path_cstr); b_path *data_path = b_path_create_from_cstr(data_path_cstr);
b_directory *data_dir; b_directory *data_dir;
bstatus = b_directory_open(NULL, data_path, &data_dir); b_result result = b_directory_open(NULL, data_path, 0, &data_dir);
if (!B_OK(bstatus)) { if (b_result_is_error(result)) {
b_err("cannot open directory '%s'", data_path_cstr); b_throw_error_with_template_caused_by_error(
b_i("reason: %s", b_status_to_string(bstatus)); ROPKG_ERROR_VENDOR,
ROPKG_ERR_DIR_OPEN_FAILED,
result,
B_ERROR_PARAM("filepath", data_path_cstr));
return -1; return -1;
} }
@@ -125,7 +137,7 @@ static int add_data_archive(
struct ropkg_writer_file_info file = {0}; struct ropkg_writer_file_info file = {0};
ropkg_writer_begin_file(pkg, ROPKG_PATH_DATA ".zst", &file); ropkg_writer_begin_file(pkg, ROPKG_PATH_DATA ".zst", &file);
ropkg_stream_begin_compressed_section(stream); b_cstream_begin_compressed_section(stream, NULL);
enum ropkg_status status = ropkg_writer_open(stream, &data); enum ropkg_status status = ropkg_writer_open(stream, &data);
int ret = 0; int ret = 0;
@@ -148,7 +160,7 @@ static int add_data_archive(
} }
ropkg_writer_close(data); ropkg_writer_close(data);
ropkg_stream_end_compressed_section(stream, NULL, NULL); b_cstream_end_compressed_section(stream, NULL, NULL);
ropkg_writer_end_file(pkg); ropkg_writer_end_file(pkg);
return ret; return ret;
@@ -156,7 +168,7 @@ static int add_data_archive(
static int add_control_archive( static int add_control_archive(
const b_arglist *args, const b_arglist *args,
struct ropkg_stream *stream, b_cstream *stream,
struct ropkg_writer *pkg) struct ropkg_writer *pkg)
{ {
int ret; int ret;
@@ -165,7 +177,7 @@ static int add_control_archive(
struct ropkg_writer_file_info file = {0}; struct ropkg_writer_file_info file = {0};
ropkg_writer_begin_file(pkg, ROPKG_PATH_CONTROL ".zst", &file); ropkg_writer_begin_file(pkg, ROPKG_PATH_CONTROL ".zst", &file);
ropkg_stream_begin_compressed_section(stream); b_cstream_begin_compressed_section(stream, NULL);
enum ropkg_status status = ropkg_writer_open(stream, &control); enum ropkg_status status = ropkg_writer_open(stream, &control);
b_arglist_option_iterator it; b_arglist_option_iterator it;
@@ -188,16 +200,40 @@ static int add_control_archive(
ropkg_writer_close(control); ropkg_writer_close(control);
ropkg_stream_end_compressed_section(stream, NULL, NULL); b_cstream_end_compressed_section(stream, NULL, NULL);
ropkg_writer_end_file(pkg); ropkg_writer_end_file(pkg);
return 0; return 0;
} }
static b_result validate_manifest(const char *path)
{
FILE *fp = fopen(path, "r");
if (!fp) {
return b_error_with_template(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_FILE_OPEN_FAILED,
B_ERROR_PARAM("filepath", path));
}
struct ropkg_manifest *manifest;
enum ropkg_status status = ropkg_manifest_create(&manifest);
if (status != ROPKG_SUCCESS) {
return b_error_with_code(ROPKG_ERROR_VENDOR, status);
}
b_result result = ropkg_manifest_parse(fp, manifest);
ropkg_manifest_destroy(manifest);
fclose(fp);
return b_result_propagate(result);
}
static int add_meta_archive( static int add_meta_archive(
const b_arglist *args, const b_arglist *args,
struct ropkg_stream *stream, b_cstream *stream,
struct ropkg_writer *pkg) struct ropkg_writer *pkg)
{ {
const char *manifest_path, *news_path; const char *manifest_path, *news_path;
@@ -205,20 +241,26 @@ static int add_meta_archive(
args, args,
OPT_MANIFEST, OPT_MANIFEST,
OPT_MANIFEST_PATH, OPT_MANIFEST_PATH,
1, 0,
&manifest_path); &manifest_path);
if (!B_OK(bstatus)) { if (!B_OK(bstatus)) {
b_arglist_report_missing_option(args, OPT_MANIFEST); b_arglist_report_missing_option(args, OPT_MANIFEST);
return -1; return -1;
} }
b_result result = validate_manifest(manifest_path);
if (b_result_is_error(result)) {
b_throw(result);
return -1;
}
int ret; int ret;
struct ropkg_writer *meta; struct ropkg_writer *meta;
struct ropkg_writer_file_info file = {0}; struct ropkg_writer_file_info file = {0};
ropkg_writer_begin_file(pkg, ROPKG_PATH_META ".zst", &file); ropkg_writer_begin_file(pkg, ROPKG_PATH_META ".zst", &file);
ropkg_stream_begin_compressed_section(stream); b_cstream_begin_compressed_section(stream, NULL);
enum ropkg_status status = ropkg_writer_open(stream, &meta); enum ropkg_status status = ropkg_writer_open(stream, &meta);
bstatus = b_arglist_get_string( bstatus = b_arglist_get_string(
@@ -243,7 +285,7 @@ static int add_meta_archive(
ropkg_writer_close(meta); ropkg_writer_close(meta);
ropkg_stream_end_compressed_section(stream, NULL, NULL); b_cstream_end_compressed_section(stream, NULL, NULL);
ropkg_writer_end_file(pkg); ropkg_writer_end_file(pkg);
@@ -255,8 +297,8 @@ static int create(
const b_arglist *opt, const b_arglist *opt,
const b_array *args) const b_array *args)
{ {
const struct ropkg_compression_function *zstd const b_compression_function *zstd
= ropkg_compression_function_for_type(ROPKG_COMPRESSION_ZSTD); = b_compression_function_get_by_id(B_COMPRESSOR_FUNCTION_ZSTD);
struct ropkg_writer *pkg, *subpkg; struct ropkg_writer *pkg, *subpkg;
enum ropkg_status status; enum ropkg_status status;
@@ -265,7 +307,7 @@ static int create(
opt, opt,
OPT_OUTPATH, OPT_OUTPATH,
OPT_OUTPATH_PATH, OPT_OUTPATH_PATH,
1, 0,
&out_path); &out_path);
if (!B_OK(bstatus)) { if (!B_OK(bstatus)) {
b_arglist_report_missing_option(opt, OPT_OUTPATH); b_arglist_report_missing_option(opt, OPT_OUTPATH);
@@ -273,37 +315,45 @@ static int create(
} }
FILE *fp = fopen(out_path, "wb"); FILE *fp = fopen(out_path, "wb");
struct ropkg_stream *stream; b_stream *fp_stream = b_stream_open_fp(fp);
status = ropkg_stream_open(fp, zstd, ROPKG_STREAM_WRITE, &stream); b_cstream *cstream;
bstatus = b_cstream_open(
fp_stream,
zstd,
B_COMPRESSION_MODE_COMPRESS,
&cstream);
status = ropkg_writer_open(stream, &pkg); status = ropkg_writer_open(cstream, &pkg);
int ret; int ret;
ret = add_data_archive(opt, stream, pkg); ret = add_data_archive(opt, cstream, pkg);
if (ret != 0) { if (ret != 0) {
goto end; goto end;
} }
ret = add_control_archive(opt, stream, pkg); ret = add_control_archive(opt, cstream, pkg);
if (ret != 0) { if (ret != 0) {
goto end; goto end;
} }
ret = add_meta_archive(opt, stream, pkg); ret = add_meta_archive(opt, cstream, pkg);
if (ret != 0) { if (ret != 0) {
goto end; goto end;
} }
end: end:
ropkg_writer_close(pkg); ropkg_writer_close(pkg);
ropkg_stream_close(stream);
b_cstream_close(cstream);
b_stream_close(fp_stream);
fclose(fp); fclose(fp);
return ret; return ret;
} }
B_COMMAND(CMD_CREATE, CMD_ROOT) B_COMMAND(CMD_PACKAGE_CREATE, CMD_PACKAGE)
{ {
B_COMMAND_NAME("create"); B_COMMAND_NAME("create");
B_COMMAND_SHORT_NAME('C'); B_COMMAND_SHORT_NAME('C');
@@ -376,7 +426,8 @@ B_COMMAND(CMD_CREATE, CMD_ROOT)
B_OPTION_SHORT_NAME('s'); B_OPTION_SHORT_NAME('s');
B_OPTION_LONG_NAME("script"); B_OPTION_LONG_NAME("script");
B_OPTION_DESC( B_OPTION_DESC(
"a control script to be run at a certain point in the " "a control script to be run at a certain point "
"in the "
"package (un)installation process."); "package (un)installation process.");
B_OPTION_ARG(OPT_SCRIPT_NAME) B_OPTION_ARG(OPT_SCRIPT_NAME)
@@ -402,10 +453,13 @@ B_COMMAND(CMD_CREATE, CMD_ROOT)
B_OPTION_SHORT_NAME('p'); B_OPTION_SHORT_NAME('p');
B_OPTION_LONG_NAME("parameter"); B_OPTION_LONG_NAME("parameter");
B_OPTION_DESC( B_OPTION_DESC(
"a parameter to use when creating the new file. " "a parameter to use when creating the new "
"if a parameter EXAMPLE is defined, any variable " "file. "
"if a parameter EXAMPLE is defined, any "
"variable "
"reference " "reference "
"of the form ${EXAMPLE} in the package manifest will " "of the form ${EXAMPLE} in the package "
"manifest will "
"be " "be "
"replaced with the specified parameter value."); "replaced with the specified parameter value.");
@@ -426,8 +480,10 @@ B_COMMAND(CMD_CREATE, CMD_ROOT)
{ {
B_ARG_NAME("source-dir"); B_ARG_NAME("source-dir");
B_ARG_DESC( B_ARG_DESC(
"the directory to package. the specified directory " "the directory to package. the specified "
"will become the root of the newly created package."); "directory "
"will become the root of the newly created "
"package.");
B_ARG_NR_VALUES(1); B_ARG_NR_VALUES(1);
} }

View File

@@ -1,4 +1,4 @@
#include "commands.h" #include "../commands.h"
#include <blue/cmd.h> #include <blue/cmd.h>
@@ -17,12 +17,12 @@ static int extract(
return 0; return 0;
} }
B_COMMAND(CMD_EXTRACT, CMD_ROOT) B_COMMAND(CMD_PACKAGE_EXTRACT, CMD_PACKAGE)
{ {
B_COMMAND_NAME("extract"); B_COMMAND_NAME("extract");
B_COMMAND_SHORT_NAME('X'); B_COMMAND_SHORT_NAME('X');
B_COMMAND_DESC("extract the contents of a Rosetta package"); B_COMMAND_DESC("extract the contents of a Rosetta package");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT); // B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(extract); B_COMMAND_FUNCTION(extract);
B_COMMAND_HELP_OPTION(); B_COMMAND_HELP_OPTION();

View File

@@ -1,4 +1,4 @@
#include "commands.h" #include "../commands.h"
#include <blue/cmd.h> #include <blue/cmd.h>
@@ -17,7 +17,7 @@ static int install(
return 0; return 0;
} }
B_COMMAND(CMD_INSTALL, CMD_ROOT) B_COMMAND(CMD_PACKAGE_INSTALL, CMD_PACKAGE)
{ {
B_COMMAND_NAME("install"); B_COMMAND_NAME("install");
B_COMMAND_SHORT_NAME('I'); B_COMMAND_SHORT_NAME('I');

193
ropkg/package/query/list.c Normal file
View File

@@ -0,0 +1,193 @@
#include "../../commands.h"
#include <blue/cmd.h>
#include <blue/compress/cstream.h>
#include <blue/compress/function.h>
#include <blue/core/bitop.h>
#include <ropkg/manifest.h>
#include <ropkg/reader.h>
enum {
OPT_DATA = 0x01u,
OPT_META = 0x02u,
OPT_CONTROL = 0x04u,
ARG_PACKAGE_PATH,
};
static int print_file_list(
int section,
bool show_header,
struct ropkg_reader *pkg)
{
if (show_header) {
switch (section) {
case OPT_DATA:
printf("data:\n");
break;
case OPT_META:
printf("meta:\n");
break;
case OPT_CONTROL:
printf("control:\n");
break;
default:
break;
}
}
enum ropkg_status status = ROPKG_SUCCESS;
while (!ropkg_reader_eof(pkg)) {
if (show_header) {
printf(" ");
}
const struct ropkg_file_info *file
= ropkg_reader_current_file(pkg);
printf("%s\n", file->f_filename);
status = ropkg_reader_move_next(pkg);
}
return 0;
}
static int query_list(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
const b_compression_function *zstd
= b_compression_function_get_by_id(B_COMPRESSOR_FUNCTION_ZSTD);
struct ropkg_reader *pkg;
enum ropkg_status status;
const char *in_path;
b_status bstatus = b_arglist_get_string(
opt,
B_COMMAND_INVALID_ID,
ARG_PACKAGE_PATH,
0,
&in_path);
if (!B_OK(bstatus)) {
b_arglist_report_missing_args(
opt,
B_COMMAND_INVALID_ID,
ARG_PACKAGE_PATH,
0);
return -1;
}
int sections = 0;
if (b_arglist_get_count(opt, OPT_DATA, B_COMMAND_INVALID_ID) > 0) {
sections |= OPT_DATA;
}
if (b_arglist_get_count(opt, OPT_META, B_COMMAND_INVALID_ID) > 0) {
sections |= OPT_META;
}
if (b_arglist_get_count(opt, OPT_CONTROL, B_COMMAND_INVALID_ID) > 0) {
sections |= OPT_CONTROL;
}
if (sections == 0) {
sections = OPT_DATA;
}
bool show_headers = b_popcountl(sections) > 1;
FILE *fp = fopen(in_path, "rb");
b_stream *fp_stream = b_stream_open_fp(fp);
b_cstream *cstream;
bstatus = b_cstream_open(
fp_stream,
zstd,
B_COMPRESSION_MODE_DECOMPRESS,
&cstream);
status = ropkg_reader_open(cstream, &pkg);
if (status != ROPKG_SUCCESS) {
printf("cannot open package\n");
return -1;
}
while (!ropkg_reader_eof(pkg)) {
const struct ropkg_file_info *file
= ropkg_reader_current_file(pkg);
int section = -1;
if (!strncmp(file->f_filename, "data.tar", 8)) {
section = OPT_DATA;
} else if (!strncmp(file->f_filename, "meta.tar", 8)) {
section = OPT_META;
} else if (!strncmp(file->f_filename, "control.tar", 11)) {
section = OPT_CONTROL;
}
if (section == -1 || (section & sections) != section) {
status = ropkg_reader_move_next(pkg);
continue;
}
struct ropkg_reader *subpkg = NULL;
b_cstream_begin_compressed_section(cstream, NULL);
status = ropkg_reader_open(cstream, &subpkg);
print_file_list(section, show_headers, subpkg);
ropkg_reader_close(subpkg);
b_cstream_end_compressed_section(cstream, NULL, NULL);
status = ropkg_reader_move_next(pkg);
}
return 0;
}
B_COMMAND(CMD_PACKAGE_QUERY_LIST, CMD_PACKAGE_QUERY)
{
B_COMMAND_NAME("list");
B_COMMAND_SHORT_NAME('L');
B_COMMAND_DESC("list the contents of a package");
B_COMMAND_FUNCTION(query_list);
B_COMMAND_HELP_OPTION();
B_COMMAND_ARG(ARG_PACKAGE_PATH)
{
B_ARG_NAME("package");
B_ARG_DESC("the package to query.");
B_ARG_NR_VALUES(1);
}
B_COMMAND_OPTION(OPT_DATA)
{
B_OPTION_SHORT_NAME('d');
B_OPTION_LONG_NAME("data");
B_OPTION_DESC(
"list all data files contained within a "
"package. if no "
"options are specified, this behaviour is the "
"default.");
}
B_COMMAND_OPTION(OPT_META)
{
B_OPTION_SHORT_NAME('m');
B_OPTION_LONG_NAME("meta");
B_OPTION_DESC(
"list all metadata files contained within a "
"package.");
}
B_COMMAND_OPTION(OPT_CONTROL)
{
B_OPTION_SHORT_NAME('c');
B_OPTION_LONG_NAME("control");
B_OPTION_DESC(
"list all control files contained within a "
"package.");
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_ARG(ARG_PACKAGE_PATH);
}
}

View File

@@ -0,0 +1,38 @@
#include "../../commands.h"
#include <blue/cmd.h>
enum {
ARG_PACKAGE_PATH,
};
static int query_manifest(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
return 0;
}
B_COMMAND(CMD_PACKAGE_QUERY_MANIFEST, CMD_PACKAGE_QUERY)
{
B_COMMAND_NAME("manifest");
B_COMMAND_SHORT_NAME('M');
B_COMMAND_DESC("print the manifest of a package");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(query_manifest);
B_COMMAND_HELP_OPTION();
B_COMMAND_ARG(ARG_PACKAGE_PATH)
{
B_ARG_NAME("package");
B_ARG_DESC("the package to query.");
B_ARG_NR_VALUES(1);
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_ARG(ARG_PACKAGE_PATH);
}
}

View File

@@ -0,0 +1,38 @@
#include "../../commands.h"
#include <blue/cmd.h>
enum {
ARG_PACKAGE_PATH,
};
static int query_readme(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
return 0;
}
B_COMMAND(CMD_PACKAGE_QUERY_README, CMD_PACKAGE_QUERY)
{
B_COMMAND_NAME("readme");
B_COMMAND_SHORT_NAME('R');
B_COMMAND_DESC("print the readme of a package");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(query_readme);
B_COMMAND_HELP_OPTION();
B_COMMAND_ARG(ARG_PACKAGE_PATH)
{
B_ARG_NAME("package");
B_ARG_DESC("the package to query.");
B_ARG_NR_VALUES(1);
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_ARG(ARG_PACKAGE_PATH);
}
}

View File

@@ -0,0 +1,18 @@
#include "../../commands.h"
#include <blue/cmd.h>
B_COMMAND(CMD_PACKAGE_QUERY, CMD_PACKAGE)
{
B_COMMAND_NAME("query");
B_COMMAND_SHORT_NAME('Q');
B_COMMAND_DESC("query information about a Rosetta package");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_HELP_OPTION();
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_COMMAND_PLACEHOLDER();
}
}

View File

@@ -0,0 +1,99 @@
#include "../../commands.h"
#include <blue/cmd.h>
#include <blue/compress/cstream.h>
#include <blue/compress/function.h>
#include <blue/io/directory.h>
#include <ropkg/manifest.h>
#include <ropkg/package.h>
#include <ropkg/reader.h>
enum {
ARG_PACKAGE_PATH,
};
static int query_summary(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
const b_compression_function *zstd
= b_compression_function_get_by_id(B_COMPRESSOR_FUNCTION_ZSTD);
struct ropkg_reader *pkg;
enum ropkg_status status;
const char *in_path;
b_status bstatus = b_arglist_get_string(
opt,
B_COMMAND_INVALID_ID,
ARG_PACKAGE_PATH,
0,
&in_path);
if (!B_OK(bstatus)) {
b_arglist_report_missing_args(
opt,
B_COMMAND_INVALID_ID,
ARG_PACKAGE_PATH,
0);
return -1;
}
FILE *fp = fopen(in_path, "rb");
b_stream *fp_stream = b_stream_open_fp(fp);
b_cstream *cstream;
bstatus = b_cstream_open(
fp_stream,
zstd,
B_COMPRESSION_MODE_DECOMPRESS,
&cstream);
status = ropkg_reader_open(cstream, &pkg);
if (status != ROPKG_SUCCESS) {
printf("cannot open package\n");
return -1;
}
b_directory *dest;
b_directory_open(
NULL,
B_RV_PATH("data"),
B_DIRECTORY_OPEN_CREATE | B_DIRECTORY_OPEN_DELETE_ON_CLOSE,
&dest);
b_result result = ropkg_extract_metadata(pkg, dest);
if (b_result_is_error(result)) {
b_throw(result);
}
b_directory_release(dest);
ropkg_reader_close(pkg);
b_cstream_close(cstream);
b_stream_close(fp_stream);
fclose(fp);
return 0;
}
B_COMMAND(CMD_PACKAGE_QUERY_SUMMARY, CMD_PACKAGE_QUERY)
{
B_COMMAND_NAME("summary");
B_COMMAND_SHORT_NAME('S');
B_COMMAND_DESC("print a summary of information about a package");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(query_summary);
B_COMMAND_HELP_OPTION();
B_COMMAND_ARG(ARG_PACKAGE_PATH)
{
B_ARG_NAME("package");
B_ARG_DESC("the package to query.");
B_ARG_NR_VALUES(1);
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_ARG(ARG_PACKAGE_PATH);
}
}

19
ropkg/package/root.c Normal file
View File

@@ -0,0 +1,19 @@
#include "../commands.h"
#include <blue/cmd.h>
#include <blue/core/error.h>
#include <blue/term/print.h>
B_COMMAND(CMD_PACKAGE, CMD_ROOT)
{
B_COMMAND_NAME("package");
B_COMMAND_SHORT_NAME('P');
B_COMMAND_DESC("Package inspection and manipulation.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_HELP_OPTION();
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_COMMAND_PLACEHOLDER();
}
}

View File

@@ -1,38 +0,0 @@
#include "commands.h"
#include <blue/cmd.h>
enum {
ARG_PACKAGE,
};
static int query(
const b_command *self,
const b_arglist *opt,
const b_array *args)
{
return 0;
}
B_COMMAND(CMD_QUERY, CMD_ROOT)
{
B_COMMAND_NAME("query");
B_COMMAND_SHORT_NAME('Q');
B_COMMAND_DESC("query information about a Rosetta package");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(query);
B_COMMAND_HELP_OPTION();
B_COMMAND_ARG(ARG_PACKAGE)
{
B_ARG_NAME("package");
B_ARG_DESC("the package to query.");
B_ARG_NR_VALUES(1);
}
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_ARG(ARG_PACKAGE);
}
}

View File

@@ -1,4 +1,4 @@
#include "commands.h" #include "../commands.h"
#include "ropkg/version.h" #include "ropkg/version.h"
#include <blue/cmd.h> #include <blue/cmd.h>
@@ -175,9 +175,10 @@ end:
return ret; return ret;
} }
B_COMMAND(CMD_COMPARE_VERSION, CMD_ROOT) B_COMMAND(CMD_VERSION_COMPARE, CMD_VERSION)
{ {
B_COMMAND_NAME("compare-version"); B_COMMAND_NAME("compare");
B_COMMAND_SHORT_NAME('C');
B_COMMAND_DESC("compare two package version identifiers."); B_COMMAND_DESC("compare two package version identifiers.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT); B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_FUNCTION(compare_version); B_COMMAND_FUNCTION(compare_version);

19
ropkg/version/root.c Normal file
View File

@@ -0,0 +1,19 @@
#include "../commands.h"
#include <blue/cmd.h>
#include <blue/core/error.h>
#include <blue/term/print.h>
B_COMMAND(CMD_VERSION, CMD_ROOT)
{
B_COMMAND_NAME("version");
B_COMMAND_SHORT_NAME('V');
B_COMMAND_DESC("Version identifier inspection and manipulation.");
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
B_COMMAND_HELP_OPTION();
B_COMMAND_USAGE()
{
B_COMMAND_USAGE_COMMAND_PLACEHOLDER();
}
}