ropkg: add command to compare two version strings
This commit is contained in:
@@ -8,6 +8,7 @@ enum {
|
||||
CMD_QUERY,
|
||||
CMD_EXTRACT,
|
||||
CMD_INSTALL,
|
||||
CMD_COMPARE_VERSION,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
236
ropkg/compare-version.c
Normal file
236
ropkg/compare-version.c
Normal file
@@ -0,0 +1,236 @@
|
||||
#include "commands.h"
|
||||
#include "ropkg/version.h"
|
||||
|
||||
#include <blue/cmd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
enum {
|
||||
OPT_VERBOSE,
|
||||
ARG_VERSION_LEFT,
|
||||
ARG_OPERATOR,
|
||||
ARG_VERSION_RIGHT,
|
||||
};
|
||||
|
||||
static enum ropkg_status comparison_op_from_string(
|
||||
const char *s,
|
||||
enum ropkg_comparison_op *out)
|
||||
{
|
||||
if (!strcmp(s, "==") || !strcmp(s, "eq")) {
|
||||
*out = ROPKG_OP_EQUAL;
|
||||
} else if (!strcmp(s, "<") || !strcmp(s, "lt")) {
|
||||
*out = ROPKG_OP_LESS_THAN;
|
||||
} else if (!strcmp(s, "<=") || !strcmp(s, "le")) {
|
||||
*out = ROPKG_OP_LESS_EQUAL;
|
||||
} else if (!strcmp(s, ">") || !strcmp(s, "gt")) {
|
||||
*out = ROPKG_OP_GREATER_THAN;
|
||||
} else if (!strcmp(s, ">=") || !strcmp(s, "ge")) {
|
||||
*out = ROPKG_OP_GREATER_EQUAL;
|
||||
} else if (!strcmp(s, "!=") || !strcmp(s, "ne")) {
|
||||
*out = ROPKG_OP_NOT_EQUAL;
|
||||
} else {
|
||||
return ROPKG_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return ROPKG_SUCCESS;
|
||||
}
|
||||
|
||||
static int compare_version(
|
||||
const b_command *self,
|
||||
const b_arglist *opt,
|
||||
const b_array *args)
|
||||
{
|
||||
int ret = -1;
|
||||
bool verbose = false;
|
||||
|
||||
struct ropkg_version *left = NULL, *right = NULL;
|
||||
enum ropkg_status status = ropkg_version_create(&left);
|
||||
if (!B_OK(status)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
status = ropkg_version_create(&right);
|
||||
if (!B_OK(status)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
const char *left_string = NULL, *right_string = NULL, *op_string = NULL;
|
||||
b_arglist_get_string(
|
||||
opt,
|
||||
B_COMMAND_INVALID_ID,
|
||||
ARG_VERSION_LEFT,
|
||||
0,
|
||||
&left_string);
|
||||
b_arglist_get_string(
|
||||
opt,
|
||||
B_COMMAND_INVALID_ID,
|
||||
ARG_VERSION_RIGHT,
|
||||
0,
|
||||
&right_string);
|
||||
b_arglist_get_string(
|
||||
opt,
|
||||
B_COMMAND_INVALID_ID,
|
||||
ARG_OPERATOR,
|
||||
0,
|
||||
&op_string);
|
||||
verbose = b_arglist_get_count(opt, OPT_VERBOSE, B_COMMAND_INVALID_ID)
|
||||
> 0;
|
||||
|
||||
if (!left_string) {
|
||||
b_arglist_report_missing_args(
|
||||
opt,
|
||||
B_COMMAND_INVALID_ID,
|
||||
ARG_VERSION_LEFT,
|
||||
0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!right_string) {
|
||||
b_arglist_report_missing_args(
|
||||
opt,
|
||||
B_COMMAND_INVALID_ID,
|
||||
ARG_VERSION_RIGHT,
|
||||
0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!op_string) {
|
||||
b_arglist_report_missing_args(
|
||||
opt,
|
||||
B_COMMAND_INVALID_ID,
|
||||
ARG_OPERATOR,
|
||||
0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
b_result result = ropkg_version_parse(left, left_string);
|
||||
if (b_result_is_error(result)) {
|
||||
b_throw(result);
|
||||
goto end;
|
||||
}
|
||||
|
||||
result = ropkg_version_parse(right, right_string);
|
||||
if (b_result_is_error(result)) {
|
||||
b_throw(result);
|
||||
goto end;
|
||||
}
|
||||
|
||||
enum ropkg_comparison_op op;
|
||||
status = comparison_op_from_string(op_string, &op);
|
||||
if (status != ROPKG_SUCCESS) {
|
||||
b_arglist_report_invalid_arg_value(
|
||||
opt,
|
||||
B_COMMAND_INVALID_ID,
|
||||
ARG_OPERATOR,
|
||||
op_string);
|
||||
goto end;
|
||||
}
|
||||
|
||||
bool comparison_result = ropkg_version_compare(left, right, op);
|
||||
ret = comparison_result ? 0 : 1;
|
||||
|
||||
if (verbose) {
|
||||
char temp[128];
|
||||
ropkg_version_to_string(left, temp, sizeof temp);
|
||||
|
||||
printf("%s ", temp);
|
||||
|
||||
switch (op) {
|
||||
case ROPKG_OP_EQUAL:
|
||||
printf("== ");
|
||||
break;
|
||||
case ROPKG_OP_NOT_EQUAL:
|
||||
printf("!= ");
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ropkg_version_to_string(right, temp, sizeof temp);
|
||||
printf("%s -> %s\n",
|
||||
temp,
|
||||
comparison_result ? "true" : "false");
|
||||
}
|
||||
|
||||
end:
|
||||
if (left) {
|
||||
ropkg_version_destroy(left);
|
||||
}
|
||||
|
||||
if (right) {
|
||||
ropkg_version_destroy(right);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
B_COMMAND(CMD_COMPARE_VERSION, CMD_ROOT)
|
||||
{
|
||||
B_COMMAND_NAME("compare-version");
|
||||
B_COMMAND_DESC("compare two package version identifiers.");
|
||||
B_COMMAND_FLAGS(B_COMMAND_SHOW_HELP_BY_DEFAULT);
|
||||
B_COMMAND_FUNCTION(compare_version);
|
||||
|
||||
B_COMMAND_HELP_OPTION();
|
||||
|
||||
B_COMMAND_OPTION(OPT_VERBOSE)
|
||||
{
|
||||
B_OPTION_SHORT_NAME('v');
|
||||
B_OPTION_LONG_NAME("verbose");
|
||||
B_OPTION_DESC(
|
||||
"print the result of the comparison to "
|
||||
"standard out.");
|
||||
}
|
||||
|
||||
B_COMMAND_ARG(ARG_VERSION_LEFT)
|
||||
{
|
||||
B_ARG_NAME("left-version");
|
||||
B_ARG_DESC("the left-side of the comparison operation.");
|
||||
B_ARG_NR_VALUES(1);
|
||||
}
|
||||
|
||||
B_COMMAND_ARG(ARG_OPERATOR)
|
||||
{
|
||||
B_ARG_NAME("operator");
|
||||
B_ARG_DESC("the comparison operator to use.");
|
||||
B_ARG_ALLOWED_VALUES(
|
||||
"==",
|
||||
"!=",
|
||||
"<",
|
||||
"<=",
|
||||
">",
|
||||
">=",
|
||||
"eq",
|
||||
"ne",
|
||||
"lt",
|
||||
"le",
|
||||
"gt",
|
||||
"ge");
|
||||
B_ARG_NR_VALUES(1);
|
||||
}
|
||||
|
||||
B_COMMAND_ARG(ARG_VERSION_RIGHT)
|
||||
{
|
||||
B_ARG_NAME("right-version");
|
||||
B_ARG_DESC("the right-side of the comparison operation.");
|
||||
B_ARG_NR_VALUES(1);
|
||||
}
|
||||
|
||||
B_COMMAND_USAGE()
|
||||
{
|
||||
B_COMMAND_USAGE_ARG(ARG_VERSION_LEFT);
|
||||
B_COMMAND_USAGE_ARG(ARG_OPERATOR);
|
||||
B_COMMAND_USAGE_ARG(ARG_VERSION_RIGHT);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user