diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f928957c149b43f0ad48e8f52d09c717a23e28c..90216055d4c9ef81c7e4de4f635af94a7e7399d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Added descriptions for more targets when running `make help` * Added a new test target for individual modules, available as `make test` * Added script in `tools/test_installed_modules.sh` that tests all modules in an installation +* Build numbers are now prefixed with a `+`. ## Bugfixes @@ -18,6 +19,8 @@ * Removed all references to `sudo`. If `sudo` needs to be used, it should be done manually. * Fixed issue with module name checking which caused modules to fail to build on certain linux distributions * Exact module version is fetched correctly at build-time to ensure that new releases do not affect upstream dependencies +* Issue involving priority between some test versions fixed +* `make patch` when there are no patch files will no longer return an error code. ## Other changes * Removed `require` as a submodule and merged it into `e3-require`. diff --git a/configure/modules/CONFIG b/configure/modules/CONFIG index f9893beef0f96ea7bdd21c75bb8b926e66ee04f6..31571ac1977b307e3731bd2bf6c87275de3df328 100644 --- a/configure/modules/CONFIG +++ b/configure/modules/CONFIG @@ -1,6 +1,7 @@ # -*- mode: Makefile;-*- -E3_MODULE_VERSION:=$(E3_MODULE_VERSION)$(shell [[ "$(E3_MODULE_VERSION)" =~ ^[0-9]+\.[0-9]+\.[0-9]+$$ ]] && echo -0) +# Update the module version (for numeric versions) with a build number of 0 if none is specified +E3_MODULE_VERSION:=$(E3_MODULE_VERSION)$(shell [[ "$(E3_MODULE_VERSION)" =~ ^[0-9]+\.[0-9]+\.[0-9]+$$ ]] && echo +0) include $(EPICS_BASE)/configure/CONFIG_BASE_VERSION include $(REQUIRE_CONFIG)/CONFIG_REQUIRE diff --git a/configure/modules/DEFINES_FT b/configure/modules/DEFINES_FT index e81b52d948bb062094e61ed6e39bbe112097c46c..c3337cb43552e2da41edfa0abedb5bfbae76dbf7 100644 --- a/configure/modules/DEFINES_FT +++ b/configure/modules/DEFINES_FT @@ -16,19 +16,28 @@ git submodule update --remote --merge $@/ endef define patch_site -for i in $(shell ls $(TOP)/patch/Site/$(E3_MODULE_VERSION)-+([a-zA-Z])*.p0.patch); do\ - printf "\nPatching %s with the file : %s\n" "$(E3_MODULE_SRC_PATH)" "$$i"; \ - git apply --directory=$(E3_MODULE_SRC_PATH) --ignore-whitespace -p0 $$i;\ -done +patches=$$(ls $(TOP)/patch/Site/$(E3_MODULE_VERSION)-*.p0.patch 2> /dev/null); \ +if [ -n "$$patches" ]; then \ + for i in $$patches; do \ + printf "\nPatching %s with the file : %s\n" "$(E3_MODULE_SRC_PATH)" "$$i"; \ + git apply --directory=$(E3_MODULE_SRC_PATH) --ignore-whitespace -p0 $$i; \ + done; \ +else \ + echo ">>> No patches to apply" >&2; \ +fi endef define patch_revert_site -for i in $(shell ls $(TOP)/patch/Site/$(E3_MODULE_VERSION)-+([a-zA-Z])*.p0.patch); do\ - printf "\nReverting applied patch %s with the file : %s\n" "$(E3_MODULE_SRC_PATH)" "$$i"; \ - git apply -R --directory=$(E3_MODULE_SRC_PATH) --ignore-whitespace -p0 $$i;\ -done - +patches=$$(ls $(TOP)/patch/Site/$(E3_MODULE_VERSION)-*.p0.patch 2> /dev/null); \ +if [ -n "$$patches" ]; then \ + for i in $$patches; do\ + printf "\nReverting applied patch %s with the file : %s\n" "$(E3_MODULE_SRC_PATH)" "$$i"; \ + git apply -R --directory=$(E3_MODULE_SRC_PATH) --ignore-whitespace -p0 $$i;\ + done \ +else \ + echo ">>> No patches to revert" >&2; \ +fi endef diff --git a/require-ess/src/require.c b/require-ess/src/require.c index 43ba75a78a431d4c04319750d5e843e2ec5a60db..bda302bc48d8a0a32679ccd2254c209bda9877b9 100644 --- a/require-ess/src/require.c +++ b/require-ess/src/require.c @@ -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; @@ -805,7 +806,7 @@ int libversionShow(const char *outfile) if (requireDebug) \ printf(__VA_ARGS__) -static int compareDigit(int found, int requested, char *name) +static int compareDigit(int found, int requested, const char *name) { debug("require: compareDigit: found %d, requested %d for digit %s\n", found, requested, name); if (found < requested) @@ -822,17 +823,50 @@ static int compareDigit(int found, int requested, char *name) return MATCH; } +static int compareNumericVersion(semver_t *sv_found, semver_t *sv_request, int already_matched) +{ + int match; + + match = compareDigit(sv_found->major, sv_request->major, "major"); + if (match != MATCH) + { + return match; + } + match = compareDigit(sv_found->minor, sv_request->minor, "minor"); + if (match != MATCH) + { + return match; + } + match = compareDigit(sv_found->patch, sv_request->patch, "patch"); + if (match != MATCH) + { + return match; + } + + if (sv_request->build == -1) + { + if (already_matched) + { + debug("require: compareVersions: No build number requested. Returning HIGHER\n"); + return HIGHER; + } + else + { + debug("require: compareVersions: No build number requested. Returning MATCH\n"); + return MATCH; + } + } + return compareDigit(sv_found->build, sv_request->build, "build"); +} + /* * Returns if the version <found> is higher than <request>. */ 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,60 +880,43 @@ 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) { debug("require: compareVersions: Test version requested and found, matches exactly\n"); - return EXACT; + match = EXACT; } - - if (found_parts == 0 || found_parts == 1 || found_parts == 2) + else if (strlen(sv_found->test_str) > 0) { debug("require: compareVersions: Test versions requested and found, no match\n"); - return MISMATCH; + match = MISMATCH; + } + else + { + debug("require: compareVersions: found numeric version, higher than test\n"); + match = HIGHER; } - - debug("require: compareVersions: found numeric version, higher than test\n"); - return HIGHER; - } - - if (found_parts == 0 || found_parts == 1 || found_parts == 2) + } + else if (strlen(sv_found->test_str) > 0) { debug("require: compareVersions: Numeric version requested, test version found\n"); - return MISMATCH; + match = MISMATCH; } - - // At least three digits specifed - match = compareDigit(found_major, req_major, "major"); - if (match != MATCH) - return match; - match = compareDigit(found_minor, req_minor, "minor"); - if (match != MATCH) - return match; - match = compareDigit(found_patch, req_patch, "patch"); - if (match != MATCH) - return match; - - if (req_parts == 3) + else { - if (already_matched) - { - debug("require: compareVersions: No build number requested. Returning HIGHER\n"); - return HIGHER; - } - else - { - debug("require: compareVersions: No build number requested. Returning MATCH\n"); - return MATCH; - } + match = compareNumericVersion(sv_found, sv_request, already_matched); } - return compareDigit(found_build, req_build, "build"); + cleanup_semver(sv_found); + cleanup_semver(sv_request); + return match; } /* require (module) diff --git a/require-ess/src/version.c b/require-ess/src/version.c new file mode 100644 index 0000000000000000000000000000000000000000..9d716c535f995af0671ff53b804421c39570850a --- /dev/null +++ b/require-ess/src/version.c @@ -0,0 +1,72 @@ +#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); +} + +static 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; +} + +static void fetch_part(char *version_str, const 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) +{ + static const char* version_regex = "^(([0-9]+)\\.([0-9]+)\\.([0-9]+)(\\+([0-9]+))?)?(.*)$"; + static const unsigned int max_regex_groups = 7 + 1; + static const unsigned int major_ix = 2; + static const unsigned int minor_ix = 3; + static const unsigned int patch_ix = 4; + static const unsigned int build_ix = 6; + static const unsigned int test_ix = 7; + + 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, major_ix, &s->major); + fetch_part(s->version_str, groups, minor_ix, &s->minor); + fetch_part(s->version_str, groups, patch_ix, &s->patch); + if (groups[build_ix].rm_so != (regoff_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; +} diff --git a/require-ess/src/version.h b/require-ess/src/version.h new file mode 100644 index 0000000000000000000000000000000000000000..f404c8de797ac7181b8d4707c77bccc516c2b279 --- /dev/null +++ b/require-ess/src/version.h @@ -0,0 +1,12 @@ +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); + +int parse_semver(const char *version, semver_t *s); \ No newline at end of file diff --git a/require-ess/tools/build_number.sh b/require-ess/tools/build_number.sh index bfef0766061bfd860e35ca72ef82a281c9b77fa0..077cd15183ff41f96c1bcc6f71cac5bfb5a96cd5 100755 --- a/require-ess/tools/build_number.sh +++ b/require-ess/tools/build_number.sh @@ -16,7 +16,7 @@ v="$3" if [[ $v =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then # shellcheck disable=SC2012 - basename "$(ls -dvr "$p/$m/$v"?(-+([0-9])) 2>/dev/null | head -n 1)" + basename "$(ls -dvr "$p/$m/$v"?(++([0-9])) 2>/dev/null | head -n 1)" else echo "$v" fi \ No newline at end of file diff --git a/require-ess/tools/driver.makefile b/require-ess/tools/driver.makefile index 967314d2b0ea008abddbcdb33c56d5a0610b75cc..df17899cad81d8347748d55fda99ee8fb173308a 100644 --- a/require-ess/tools/driver.makefile +++ b/require-ess/tools/driver.makefile @@ -101,8 +101,8 @@ RM = rm -f CP = cp # This is to allow for build numbers in recognized versions. First regex is for grep, second for sed. -VERSIONGLOB = +([0-9]).+([0-9]).+([0-9])?(-+([0-9])) -VERSIONREGEX = [0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)? +VERSIONGLOB = +([0-9]).+([0-9]).+([0-9])?(++([0-9])) +VERSIONREGEX = [0-9]+\.[0-9]+\.[0-9]+(\+[0-9]+)? # Some generated file names: VERSIONFILE = ${PRJ}_version_${LIBVERSION}.c diff --git a/require.Makefile b/require.Makefile index a1acaf6e63f00b635920647bd1ccdf503b9ff172..d07ccfc6f8ede6bcd2435cae8bbb4334af16f8d9 100644 --- a/require.Makefile +++ b/require.Makefile @@ -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