aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Groffen <grobian@gentoo.org>2018-04-05 14:10:26 +0200
committerFabian Groffen <grobian@gentoo.org>2018-04-05 14:10:26 +0200
commit89a388678c4975b541d24931b0916e2959ed70be (patch)
tree030352927ff2fc83d20346322c25fd199dda08fb
parentshow_merge_times: start counting parallel merges from start of the file (diff)
downloadportage-utils-89a388678c4975b541d24931b0916e2959ed70be.tar.gz
portage-utils-89a388678c4975b541d24931b0916e2959ed70be.tar.bz2
portage-utils-89a388678c4975b541d24931b0916e2959ed70be.zip
atom_explode: fix parsing of some valid corner cases
Extract the version part of the atom, such that we can more reliably parse the version components without worrying about accidentially taking parts of the package name. Bug: https://bugs.gentoo.org/526596
-rw-r--r--libq/atom_explode.c78
-rwxr-xr-xtests/qatom/dotest13
2 files changed, 53 insertions, 38 deletions
diff --git a/libq/atom_explode.c b/libq/atom_explode.c
index 1b81909..e52f149 100644
--- a/libq/atom_explode.c
+++ b/libq/atom_explode.c
@@ -147,7 +147,7 @@ atom_explode(const char *atom)
}
strcpy(ret->CATEGORY, atom);
- /* eat file name crap */
+ /* eat file name crap when given an (autocompleted) path */
if ((ptr = strstr(ret->CATEGORY, ".ebuild")) != NULL)
*ptr = '\0';
@@ -172,11 +172,12 @@ atom_explode(const char *atom)
}
}
- /* break up the CATEOGRY and PVR */
+ /* break up the CATEGORY and PVR */
if ((ptr = strrchr(ret->CATEGORY, '/')) != NULL) {
ret->PN = ptr + 1;
*ptr = '\0';
- /* eat extra crap in case it exists */
+ /* eat extra crap in case it exists, this is a feature to allow
+ * /path/to/pkg.ebuild */
if ((ptr = strrchr(ret->CATEGORY, '/')) != NULL)
ret->CATEGORY = ptr + 1;
} else {
@@ -184,9 +185,28 @@ atom_explode(const char *atom)
ret->CATEGORY = NULL;
}
+ /* CATEGORY should be all set here, PN contains everything up to
+ * SLOT, REPO or '*'
+ * PN must not end in a hyphen followed by anything matching version
+ * syntax, version syntax starts with a number, so "-[0-9]" is a
+ * separator from PN to PV* */
+
+ ptr = ret->PN;
+ while ((ptr = strchr(ptr, '-')) != NULL) {
+ ptr++;
+ if (*ptr >= '0' && *ptr <= '9')
+ break;
+ }
+
+ if (ptr == NULL) {
+ /* atom has no version, this is it */
+ return ret;
+ }
+ ret->PV = ptr;
+
/* find -r# */
- ptr = ret->PN + strlen(ret->PN) - 1;
- while (*ptr && ptr > ret->PN) {
+ ptr = ret->PV + strlen(ret->PV) - 1;
+ while (*ptr && ptr > ret->PV) {
if (!isdigit(*ptr)) {
if (ptr[0] == 'r' && ptr[-1] == '-') {
ret->PR_int = atoi(ptr + 1);
@@ -197,39 +217,35 @@ atom_explode(const char *atom)
--ptr;
}
strcpy(ret->P, ret->PN);
+ ret->PV[-1] = '\0';
/* break out all the suffixes */
sidx = 0;
ret->suffixes = xrealloc(ret->suffixes, sizeof(atom_suffix) * (sidx + 1));
ret->suffixes[sidx].sint = 0;
ret->suffixes[sidx].suffix = VER_NORM;
- while ((ptr = strrchr(ret->PN, '_')) != NULL) {
+ ptr = ret->PV + strlen(ret->PV) - 1;
+ while (ptr-- > ret->PV) {
+ if (*ptr != '_')
+ continue;
for (idx = 0; idx < ARRAY_SIZE(atom_suffixes_str); ++idx) {
- if (strncmp(ptr, atom_suffixes_str[idx], strlen(atom_suffixes_str[idx])))
+ if (strncmp(ptr, atom_suffixes_str[idx],
+ strlen(atom_suffixes_str[idx])))
continue;
- /* check this is a real suffix and not _p hitting mod_perl */
- char *tmp_ptr = ptr;
- tmp_ptr += strlen(atom_suffixes_str[idx]);
- ret->suffixes[sidx].sint = atoll(tmp_ptr);
- while (isdigit(*tmp_ptr))
- ++tmp_ptr;
- if (*tmp_ptr)
- goto no_more_suffixes;
+ ret->suffixes[sidx].sint =
+ atoll(ptr + strlen(atom_suffixes_str[idx]));
ret->suffixes[sidx].suffix = idx;
++sidx;
- *ptr = '\0';
- ret->suffixes = xrealloc(ret->suffixes, sizeof(atom_suffix) * (sidx + 1));
+ ret->suffixes = xrealloc(ret->suffixes,
+ sizeof(atom_suffix) * (sidx + 1));
ret->suffixes[sidx].sint = 0;
ret->suffixes[sidx].suffix = VER_NORM;
break;
}
- if (*ptr)
- break;
}
- no_more_suffixes:
if (sidx)
--sidx;
for (idx = 0; idx < sidx; ++idx, --sidx) {
@@ -238,35 +254,27 @@ atom_explode(const char *atom)
ret->suffixes[idx] = t;
}
- /* allow for 1 optional suffix letter, must be following a number
- * otherwise we eat stuff like -c, see bug #639978 */
- ptr = ret->PN + strlen(ret->PN);
+ /* allow for 1 optional suffix letter, must be following a number */
+ ptr = ret->PV + strlen(ret->PV);
if (ptr[-1] >= 'a' && ptr[-1] <= 'z' &&
- ptr - 2 > ret->PN && ptr[-2] >= '0' && ptr[-2] <= '9')
+ ptr - 2 > ret->PV && ptr[-2] >= '0' && ptr[-2] <= '9')
{
ret->letter = ptr[-1];
--ptr;
}
/* eat the trailing version number [-.0-9]+ */
- bool has_pv = false;
- while (--ptr > ret->PN)
+ while (--ptr > ret->PV) {
if (*ptr == '-') {
- has_pv = true;
*ptr = '\0';
break;
} else if (*ptr != '.' && !isdigit(*ptr))
break;
- if (has_pv) {
- ret->PV = ret->P + (ptr - ret->PN) + 1;
- ptr = stpcpy(ret->PVR, ret->PV);
- sprintf(ptr, "-r%i", ret->PR_int);
- } else {
- /* atom has no version */
- ret->PV = ret->PVR = NULL;
- ret->letter = 0;
}
+ ptr = stpcpy(ret->PVR, ret->PV);
+ sprintf(ptr, "-r%i", ret->PR_int);
+
return ret;
}
diff --git a/tests/qatom/dotest b/tests/qatom/dotest
index 4bb0460..a0e6a34 100755
--- a/tests/qatom/dotest
+++ b/tests/qatom/dotest
@@ -29,9 +29,9 @@ test l07 "cat pkg 123 >=" ">=cat/pkg-123"
test l07 "cat pkg 123 = *" "=cat/pkg-123*"
# Explicit format.
-test f01 "cat" -F '%{CATEGORY}' "cat/pkg"
-test f02 "<unset>" -F '%{CATEGORY}' "pkg"
-test f03 "" -F '%[CATEGORY]' "pkg"
+test f01 "cat" -F '%{CATEGORY}' "cat/pkg"
+test f02 "<unset>" -F '%{CATEGORY}' "pkg"
+test f03 "" -F '%[CATEGORY]' "pkg"
test f04 "cat" -F '%{CATEGORY}' "cat/pkg-123-r4:5"
test f05 "pkg-123" -F '%{P}' "cat/pkg-123-r4:5"
test f06 "pkg" -F '%{PN}' "cat/pkg-123-r4:5"
@@ -41,5 +41,12 @@ test f09 "pkg-123-r4" -F '%{PF}' "cat/pkg-123-r4:5"
test f10 "r4" -F '%{PR}' "cat/pkg-123-r4:5"
test f11 ":5" -F '%{SLOT}' "cat/pkg-123-r4:5"
test f12 "pkg-c" -F '%{PN}' "cat/pkg-c" # bug #639978
+test f13 "mod_perl 1.5_p20180304 r5" \
+ -F '%{PN} %{PV} %{PR}' \
+ "dev-libs/mod_perl-1.5_p20180304-r5"
+test f14 "foo-r1" -F '%{PN}' "foo-r1" # bug #526596
+test f15 "app-emacs diff-mode-" \
+ -F '%{CATEGORY} %{PN}' \
+ "app-emacs/diff-mode-"
end