diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2019-12-24 15:43:17 -0500 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2019-12-24 15:43:17 -0500 |
commit | b85bae06b45a02f89c08065fd672b969d4c43f1b (patch) | |
tree | d508d77f3885fbba8c42f89b8a76aadc6c02e8aa | |
parent | 860d05aa8d580bbf3853db13bc25e9dfcb16f514 (diff) | |
download | spmc-b85bae06b45a02f89c08065fd672b969d4c43f1b.tar.gz |
Add version_spec.c
-rw-r--r-- | include/spm.h | 8 | ||||
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/spm.c | 1 | ||||
-rw-r--r-- | src/version_spec.c | 194 |
4 files changed, 204 insertions, 1 deletions
diff --git a/include/spm.h b/include/spm.h index 7d986c1..55451e9 100644 --- a/include/spm.h +++ b/include/spm.h @@ -211,4 +211,12 @@ ManifestPackage *manifest_search(Manifest *info, const char *package); char *md5sum(const char *filename); char *sha256sum(const char *filename); +// version_spec.c +char *version_suffix_get_alpha(char *str); +char *version_suffix_get_modifier(char *str); +int64_t version_suffix_modifier_calc(char *str); +int version_suffix_alpha_calc(char *str); +int64_t version_from(const char *version_str); + + #endif //SPM_SPM_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c8377ff..d866ef0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,7 @@ include_directories( ${CMAKE_BINARY_DIR}/include ) -add_executable(spm spm.c config.c compat.c deps.c fs.c rpath.c find.c shell.c archive.c strings.c relocation.c install.c config_global.c manifest.c checksum.c extern/url.c) +add_executable(spm spm.c config.c compat.c deps.c fs.c rpath.c find.c shell.c archive.c strings.c relocation.c install.c config_global.c manifest.c checksum.c extern/url.c version_spec.c) target_link_libraries(spm rt crypto ssl curl) install( TARGETS spm @@ -16,6 +16,7 @@ void usage(const char *program_name) { " -V, --version show version\n" " -v, --verbose show more information\n" " -I, --install install package(s)\n" + " -r --root installation prefix (requires --install)\n" , program_name ); } diff --git a/src/version_spec.c b/src/version_spec.c new file mode 100644 index 0000000..7669608 --- /dev/null +++ b/src/version_spec.c @@ -0,0 +1,194 @@ +#include "spm.h" + +char *version_suffix_get_alpha(char *str) { + size_t i; + size_t len = strlen(str); + for (i = 0; i < len; i++) { + // return pointer to the first alphabetic character we find + if (isalpha(str[i])) { + return &str[i]; + } + } + return NULL; +} + +char *version_suffix_get_modifier(char *str) { + size_t i; + char *modifiers[] = { + "rc", + "pre", + "dev", + "post", + NULL, + }; + for (i = 0; i < strlen(str); i++) { + for (int m = 0; modifiers[m] != NULL; m++) { + if (strncasecmp(&str[i], modifiers[m], strlen(modifiers[m])) == 0) { + return &str[i]; + } + } + } + return NULL; +} + +int64_t version_suffix_modifier_calc(char *str) { + int64_t result = 0; + char *tmp_s = str; + + if (strncasecmp(str, "rc", 2) == 0) { + // do rc + tmp_s += strlen("rc"); + if (isdigit(*tmp_s)) { + result -= atoi(tmp_s); + } + else { + result -= 1; + } + } + else if (strncasecmp(str, "pre", 3) == 0) { + // do pre + tmp_s += strlen("pre"); + if (isdigit(*tmp_s)) { + result -= atoi(tmp_s); + } + else { + result -= 1; + } + } + else if (strncasecmp(str, "dev", 3) == 0) { + // do dev + tmp_s += strlen("dev"); + if (isdigit(*tmp_s)) { + result -= atoi(tmp_s); + } + else { + result -= 1; + } + } + else if (strncasecmp(str, "post", 4) == 0) { + // do post + tmp_s += strlen("post"); + if (isdigit(*tmp_s)) { + result += atoi(tmp_s); + } + else { + result += 1; + } + } + + return result; +} + +int version_suffix_alpha_calc(char *str) { + if (version_suffix_get_modifier(str) != NULL) { + return 0; + } + int x = 0; + char chs[255]; + char *ch = chs; + memset(chs, '\0', sizeof(chs)); + strncpy(chs, str, strlen(str)); + + // Convert character to hex-ish + x = (*ch - 'a') + 0xa; + + // Ensure the string ends with a digit + if (strlen(str) == 1) { + strcat(ch, "0"); + } + + // Convert trailing numerical value to an integer + while (*ch != '\0') { + if (!isdigit(*ch)) { + ch++; + continue; + } + x += atoi(ch); + break; + } + + return x; +} + +int64_t version_from(const char *version_str) { + const char *delim = "."; + int64_t result = 0; + + int seen_alpha = 0; // Does the tail contain a single character, but not a modifier? + int seen_modifier = 0; // Does the tail contain "rc", "dev", "pre", and so forth? + char head[255]; // digits of the string + char tail[255]; // alphabetic characters of the string + char *suffix_alpha = NULL; // pointer to location of the first character after the version + char *suffix_modifier = NULL; // pointer to location of the modifier after the version + char *x = NULL; // pointer to each string delimited by "." + char *vstr = calloc(strlen(version_str) + 1, sizeof(char)); + if (!vstr) { + perror("Version string copy"); + return -1; + } + + memset(head, '\0', sizeof(head)); + memset(tail, '\0', sizeof(tail)); + strncpy(vstr, version_str, strlen(version_str)); + + // Split the version into parts + while ((x = strsep(&vstr, delim)) != NULL) { + int64_t tmp = 0; + + // populate the head (numeric characters) + strncpy(head, x, strlen(x)); + for (int i = 0; i < strlen(head); i++) { + if (isalpha(head[i])) { + // populate the tail (alphabetic characters) + strncpy(tail, &head[i], strlen(&head[i])); + head[i] = '\0'; + break; + } + } + + // Detect alphabetic suffix + if (!seen_alpha) { + if ((suffix_alpha = version_suffix_get_alpha(x)) != NULL) { + seen_alpha = 1; + } + } + + // Detect modifier suffix + if (!seen_modifier) { + if ((suffix_modifier = version_suffix_get_modifier(x)) != NULL) { + seen_modifier = 1; + } + } + + // Stop processing if the head starts with something other than numbers + if (!isdigit(head[0])) { + break; + } + + // Convert the head to an integer + tmp = atoi(head); + // Update result. Each portion of the numeric version is its own byte + // Version PARTS are limited to 255 + result = result << 8 | tmp; + } + + if (suffix_alpha != NULL) { + // Convert the alphabetic suffix to an integer + int64_t sac = version_suffix_alpha_calc(suffix_alpha); + result += sac; + } + + if (suffix_modifier != NULL) { + // Convert the modifier string to an integer + int64_t smc = version_suffix_modifier_calc(suffix_modifier); + if (smc < 0) { + result -= ~smc + 1; + } + else { + result += smc; + } + } + + free(vstr); + return result; +} |