Skip to content
Snippets Groups Projects
Commit 186440d4 authored by Simon Rose's avatar Simon Rose
Browse files

Added semantic versioning parser with regex

parent a92b27b4
No related branches found
No related tags found
No related merge requests found
......@@ -38,6 +38,7 @@ epicsShareFunc int epicsShareAPI iocshCmd(const char *cmd);
#include <osiFileName.h>
#include <epicsExport.h>
#include "version.h"
#include "require.h"
int requireDebug;
......@@ -827,12 +828,9 @@ static int compareDigit(int found, int requested, char *name)
*/
static int compareVersions(const char *found, const char *request, int already_matched)
{
int found_major = 0, found_minor = 0, found_patch = 0, found_parts = 0, found_build = 0;
int req_major = 0, req_minor = 0, req_patch = 0, req_parts = 0, req_build = 0;
semver_t sv_found, sv_request;
int match;
const char *version_string = "%d.%d.%d-%d";
debug("require: compareVersions(found=%s, request=%s)\n", found, request);
if (request == NULL || request[0] == 0)
......@@ -846,12 +844,14 @@ static int compareVersions(const char *found, const char *request, int already_m
return MISMATCH;
}
found_parts = sscanf(found, version_string, &found_major, &found_minor, &found_patch, &found_build);
/*sv_found = (semver_t *)calloc(1, sizeof(semver_t));
sv_request = (semver_t *)calloc(1, sizeof(semver_t));*/
req_parts = sscanf(request, version_string, &req_major, &req_minor, &req_patch, &req_build);
parse_semver(found, &sv_found);
parse_semver(request, &sv_request);
// test version, look for exact.
if (req_parts == 0 || req_parts == 1 || req_parts == 2)
if (strlen(sv_request.test_str) > 0)
{
if (strcmp(found, request) == 0)
{
......@@ -859,7 +859,7 @@ static int compareVersions(const char *found, const char *request, int already_m
return EXACT;
}
if (found_parts == 0 || found_parts == 1 || found_parts == 2)
if (strlen(sv_found.test_str) > 0)
{
debug("require: compareVersions: Test versions requested and found, no match\n");
return MISMATCH;
......@@ -869,24 +869,25 @@ static int compareVersions(const char *found, const char *request, int already_m
return HIGHER;
}
if (found_parts == 0 || found_parts == 1 || found_parts == 2)
if (strlen(sv_found.test_str) > 0)
{
debug("require: compareVersions: Numeric version requested, test version found\n");
return MISMATCH;
}
// At least three digits specifed
match = compareDigit(found_major, req_major, "major");
match = compareDigit(sv_found.major, sv_request.major, "major");
if (match != MATCH)
return match;
match = compareDigit(found_minor, req_minor, "minor");
match = compareDigit(sv_found.minor, sv_request.minor, "minor");
if (match != MATCH)
return match;
match = compareDigit(found_patch, req_patch, "patch");
match = compareDigit(sv_found.patch, sv_request.patch, "patch");
if (match != MATCH)
return match;
if (req_parts == 3)
// build number not specified
if (sv_request.build == -1)
{
if (already_matched)
{
......@@ -899,7 +900,7 @@ static int compareVersions(const char *found, const char *request, int already_m
return MATCH;
}
}
return compareDigit(found_build, req_build, "build");
return compareDigit(sv_found.build, sv_request.build, "build");
}
/* require (module)
......
#include <regex.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "version.h"
void cleanup_semver(semver_t *s) {
free(s->version_str);
free(s);
}
void init_semver(const char *version, semver_t *s) {
s->version_str = calloc(strlen(version) + 1, sizeof(char));
strcpy(s->version_str, version);
s->test_str = "";
s->major = 0;
s->minor = 0;
s->patch = 0;
s->build = -1;
}
void fetch_part(char *version_str, regmatch_t *groups, unsigned int ix, int *part) {
char tmp;
tmp = version_str[groups[ix].rm_eo];
version_str[groups[ix].rm_eo] = 0;
*part = atoi(version_str + groups[ix].rm_so);
version_str[groups[ix].rm_eo] = tmp;
}
int parse_semver(const char *version, semver_t *s) {
regex_t compiled;
regmatch_t groups[MAX_REGEX_GROUPS];
init_semver(version, s);
if (s->version_str == NULL || s->version_str[0] == 0) {
return 1;
}
if (regcomp(&compiled, VERSION_REGEX, REG_EXTENDED)) {
return 1;
}
if (regexec(&compiled, s->version_str, MAX_REGEX_GROUPS, groups, 0) == 0) {
fetch_part(s->version_str, groups, MAJ_IX, &s->major);
fetch_part(s->version_str, groups, MIN_IX, &s->minor);
fetch_part(s->version_str, groups, PATCH_IX, &s->patch);
if (groups[BUILD_IX].rm_so != (size_t)-1) {
fetch_part(s->version_str, groups, BUILD_IX, &s->build);
}
s->test_str = s->version_str + groups[TEST_IX].rm_so;
}
return 0;
}
/*int main(int argc, char **argv) {
if (argc < 1) return 0;
if (strlen(argv[1]) == 0) return 0;
semver_t *s = (semver_t *)calloc(1,sizeof(semver_t));
parse_semver(argv[1], s);
ps("main", s);
cleanup_semver(s);
return 0;
}*/
\ No newline at end of file
#define VERSION_REGEX "^(([0-9]+)\\.([0-9]+)\\.([0-9]+)(\\-([0-9]+))?)?(.*)$"
#define MAX_REGEX_GROUPS (7+1)
#define MAJ_IX 2
#define MIN_IX 3
#define PATCH_IX 4
#define BUILD_IX 6
#define TEST_IX 7
typedef struct semver_t {
char *version_str;
int major;
int minor;
int patch;
int build; // can be negative; implies that build has not been specified
char *test_str;
} semver_t;
void cleanup_semver(semver_t *s);
void init_semver(const char *version, semver_t *s);
int parse_semver(const char *version, semver_t *s);
\ No newline at end of file
......@@ -41,6 +41,7 @@ APPSRC := $(APP)/src
APPDB := $(APP)/Db
SOURCES += $(APPSRC)/require.c
SOURCES += $(APPSRC)/version.c
DBDS += $(APPSRC)/require.dbd
SOURCES += $(APPSRC)/runScript.c
DBDS += $(APPSRC)/runScript.dbd
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment