ropkg: add command to compare two version strings
This commit is contained in:
@@ -8,6 +8,7 @@ enum {
|
|||||||
CMD_QUERY,
|
CMD_QUERY,
|
||||||
CMD_EXTRACT,
|
CMD_EXTRACT,
|
||||||
CMD_INSTALL,
|
CMD_INSTALL,
|
||||||
|
CMD_COMPARE_VERSION,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#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