[PATCH 1/2] libdpkg: remember whether a version string had the epoch/revision when parsed
Raphaël Hertzog
hertzog at debian.org
Sun May 2 07:59:29 UTC 2010
For the epoch, we add a new boolean attribute "epoch_present" to the
versionrevision struct. For the revision, we ensure that a NULL value
means "no revision" and that an empty revision really represents an empty
revision ("1.0-").
Add non-regression tests to check that the output function preserves
the original string when it has been parsed by parseversion().
---
lib/dpkg/database.c | 1 +
lib/dpkg/dpkg-db.h | 8 +++-
lib/dpkg/parsehelp.c | 17 +++++--
lib/dpkg/test/t-version.c | 118 +++++++++++++++++++++++++++++++++++++--------
src/enquiry.c | 8 ++--
5 files changed, 121 insertions(+), 31 deletions(-)
diff --git a/lib/dpkg/database.c b/lib/dpkg/database.c
index e982372..3f9d017 100644
--- a/lib/dpkg/database.c
+++ b/lib/dpkg/database.c
@@ -59,6 +59,7 @@ static unsigned int hash(const char *name) {
void blankversion(struct versionrevision *version) {
version->epoch= 0;
version->version= version->revision= NULL;
+ version->epoch_present = false;
}
void blankpackage(struct pkginfo *pigp) {
diff --git a/lib/dpkg/dpkg-db.h b/lib/dpkg/dpkg-db.h
index 9ad461c..6dd01af 100644
--- a/lib/dpkg/dpkg-db.h
+++ b/lib/dpkg/dpkg-db.h
@@ -36,6 +36,7 @@ struct versionrevision {
unsigned long epoch;
const char *version;
const char *revision;
+ bool epoch_present;
};
enum deptype {
@@ -260,7 +261,12 @@ extern const struct namevalue wantinfos[];
int informativeversion(const struct versionrevision *version);
-enum versiondisplayepochwhen { vdew_never, vdew_nonambig, vdew_always };
+enum versiondisplayepochwhen {
+ vdew_never, /* Always hide the epoch */
+ vdew_nonambig, /* Display it only when required (!= 0, other : in version) */
+ vdew_always, /* Always display it */
+ vdew_parsed /* Keep same output as what has been parsed */
+};
void varbufversion(struct varbuf*, const struct versionrevision*,
enum versiondisplayepochwhen);
const char *parseversion(struct versionrevision *rversion, const char*);
diff --git a/lib/dpkg/parsehelp.c b/lib/dpkg/parsehelp.c
index a37df93..4c98e21 100644
--- a/lib/dpkg/parsehelp.c
+++ b/lib/dpkg/parsehelp.c
@@ -173,21 +173,26 @@ void varbufversion
const struct versionrevision *version,
enum versiondisplayepochwhen vdew)
{
+ bool epoch_required = version->epoch ||
+ (version->version && strchr(version->version, ':')) ||
+ (version->revision && strchr(version->revision, ':'));
switch (vdew) {
case vdew_never:
break;
case vdew_nonambig:
- if (!version->epoch &&
- (!version->version || !strchr(version->version,':')) &&
- (!version->revision || !strchr(version->revision,':'))) break;
+ if (!epoch_required) break;
case vdew_always: /* FALL THROUGH */
varbufprintf(vb,"%lu:",version->epoch);
break;
+ case vdew_parsed:
+ if (version->epoch_present || epoch_required)
+ varbufprintf(vb, "%lu:", version->epoch);
+ break;
default:
internerr("unknown versiondisplayepochwhen '%d'", vdew);
}
if (version->version) varbufaddstr(vb,version->version);
- if (version->revision && *version->revision) {
+ if (version->revision) {
varbufaddc(vb,'-');
varbufaddstr(vb,version->revision);
}
@@ -240,14 +245,16 @@ const char *parseversion(struct versionrevision *rversion, const char *string) {
if (!*++colon) return _("nothing after colon in version number");
string= colon;
rversion->epoch= epoch;
+ rversion->epoch_present = true;
} else {
rversion->epoch= 0;
+ rversion->epoch_present = false;
}
rversion->version= nfstrnsave(string,end-string);
hyphen= strrchr(rversion->version,'-');
if (hyphen)
*hyphen++ = '\0';
- rversion->revision= hyphen ? hyphen : "";
+ rversion->revision = hyphen; /* NULL means no revision */
return NULL;
}
diff --git a/lib/dpkg/test/t-version.c b/lib/dpkg/test/t-version.c
index 8355c6d..950c93d 100644
--- a/lib/dpkg/test/t-version.c
+++ b/lib/dpkg/test/t-version.c
@@ -24,8 +24,8 @@
#include <dpkg/test.h>
#include <dpkg/dpkg-db.h>
-#define version(epoch, version, revision) \
- (struct versionrevision) { (epoch), (version), (revision) }
+#define version(epoch, version, revision, epoch_present) \
+ (struct versionrevision) { (epoch), (version), (revision), (epoch_present) }
static void
test_version_compare(void)
@@ -41,19 +41,19 @@ test_version_compare(void)
test_pass(epochsdiffer(&a, &b));
/* Test for version equality. */
- a = b = version(0, "0", "0");
+ a = b = version(0, "0", "0", false);
test_pass(versioncompare(&a, &b) == 0);
- a = version(0, "0", "00");
- b = version(0, "00", "0");
+ a = version(0, "0", "00", false);
+ b = version(0, "00", "0", true);
test_pass(versioncompare(&a, &b) == 0);
- a = b = version(1, "2", "3");
+ a = b = version(1, "2", "3", true);
test_pass(versioncompare(&a, &b) == 0);
/* Test for epoch difference. */
- a = version(0, "0", "0");
- b = version(1, "0", "0");
+ a = version(0, "0", "0", false);
+ b = version(1, "0", "0", true);
test_pass(versioncompare(&a, &b) < 0);
test_pass(versioncompare(&b, &a) > 0);
@@ -67,68 +67,72 @@ test_version_parse(void)
/* Test 0 versions. */
blankversion(&a);
- b = version(0, "0", "");
+ b = version(0, "0", "", false);
test_pass(parseversion(&a, "0") == NULL);
test_pass(versioncompare(&a, &b) == 0);
+ test_pass(a.epoch_present == false);
test_pass(parseversion(&a, "0:0") == NULL);
test_pass(versioncompare(&a, &b) == 0);
+ test_pass(a.epoch_present == true);
+ test_pass(a.revision == NULL);
test_pass(parseversion(&a, "0:0-") == NULL);
+ test_pass(a.revision && *a.revision == '\0');
test_pass(versioncompare(&a, &b) == 0);
- b = version(0, "0", "0");
+ b = version(0, "0", "0", false);
test_pass(parseversion(&a, "0:0-0") == NULL);
test_pass(versioncompare(&a, &b) == 0);
- b = version(0, "0.0", "0.0");
+ b = version(0, "0.0", "0.0", false);
test_pass(parseversion(&a, "0:0.0-0.0") == NULL);
test_pass(versioncompare(&a, &b) == 0);
/* Test epoched versions. */
- b = version(1, "0", "");
+ b = version(1, "0", "", true);
test_pass(parseversion(&a, "1:0") == NULL);
test_pass(versioncompare(&a, &b) == 0);
- b = version(5, "1", "");
+ b = version(5, "1", "", true);
test_pass(parseversion(&a, "5:1") == NULL);
test_pass(versioncompare(&a, &b) == 0);
/* Test multiple dashes. */
- b = version(0, "0-0", "0");
+ b = version(0, "0-0", "0", false);
test_pass(parseversion(&a, "0:0-0-0") == NULL);
test_pass(versioncompare(&a, &b) == 0);
- b = version(0, "0-0-0", "0");
+ b = version(0, "0-0-0", "0", false);
test_pass(parseversion(&a, "0:0-0-0-0") == NULL);
test_pass(versioncompare(&a, &b) == 0);
/* Test multiple colons. */
- b = version(0, "0:0", "0");
+ b = version(0, "0:0", "0", false);
test_pass(parseversion(&a, "0:0:0-0") == NULL);
test_pass(versioncompare(&a, &b) == 0);
- b = version(0, "0:0:0", "0");
+ b = version(0, "0:0:0", "0", false);
test_pass(parseversion(&a, "0:0:0:0-0") == NULL);
test_pass(versioncompare(&a, &b) == 0);
/* Test multiple dashes and colons. */
- b = version(0, "0:0-0", "0");
+ b = version(0, "0:0-0", "0", false);
test_pass(parseversion(&a, "0:0:0-0-0") == NULL);
test_pass(versioncompare(&a, &b) == 0);
- b = version(0, "0-0:0", "0");
+ b = version(0, "0-0:0", "0", false);
test_pass(parseversion(&a, "0:0-0:0-0") == NULL);
test_pass(versioncompare(&a, &b) == 0);
/* Test valid characters in upstream version. */
- b = version(0, "azAZ09.-+~:", "0");
+ b = version(0, "azAZ09.-+~:", "0", false);
test_pass(parseversion(&a, "0:azAZ09.-+~:-0") == NULL);
test_pass(versioncompare(&a, &b) == 0);
/* Test valid characters in revision. */
- b = version(0, "0", "azAZ09.+~");
+ b = version(0, "0", "azAZ09.+~", false);
test_pass(parseversion(&a, "0:0-azAZ09.+~") == NULL);
test_pass(versioncompare(&a, &b) == 0);
@@ -149,9 +153,81 @@ test_version_parse(void)
}
static void
+test_version_output(void)
+{
+ struct versionrevision a;
+ struct varbuf output = VARBUF_INIT;
+ const char * string;
+
+ /* Test how epoch is handled on output */
+ string = "0:2-3";
+ parseversion(&a, string);
+ varbufreset(&output);
+ varbufversion(&output, &a, vdew_parsed);
+ varbufaddc(&output, '\0');
+ test_pass(strcmp(string, output.buf) == 0);
+
+ varbufreset(&output);
+ varbufversion(&output, &a, vdew_always);
+ varbufaddc(&output, '\0');
+ test_pass(strcmp(string, output.buf) == 0);
+
+ varbufreset(&output);
+ varbufversion(&output, &a, vdew_never);
+ varbufaddc(&output, '\0');
+ test_pass(strcmp("2-3", output.buf) == 0);
+
+ varbufreset(&output);
+ varbufversion(&output, &a, vdew_nonambig);
+ varbufaddc(&output, '\0');
+ test_pass(strcmp("2-3", output.buf) == 0);
+
+ string = "1:2-3";
+ parseversion(&a, string);
+ varbufreset(&output);
+ varbufversion(&output, &a, vdew_nonambig);
+ varbufaddc(&output, '\0');
+ test_pass(strcmp("1:2-3", output.buf) == 0);
+
+ a = version(0, "1:a", "2", false); /* Can't happen with parseversion */
+ varbufreset(&output);
+ varbufversion(&output, &a, vdew_parsed);
+ varbufaddc(&output, '\0');
+ test_pass(strcmp("0:1:a-2", output.buf) == 0);
+ varbufreset(&output);
+ varbufversion(&output, &a, vdew_nonambig);
+ varbufaddc(&output, '\0');
+ test_pass(strcmp("0:1:a-2", output.buf) == 0);
+
+ a = version(0, "1", "2:3", false); /* Can't happen with parseversion */
+ varbufreset(&output);
+ varbufversion(&output, &a, vdew_parsed);
+ varbufaddc(&output, '\0');
+ test_pass(strcmp("0:1-2:3", output.buf) == 0);
+ varbufreset(&output);
+ varbufversion(&output, &a, vdew_nonambig);
+ varbufaddc(&output, '\0');
+ test_pass(strcmp("0:1-2:3", output.buf) == 0);
+
+ /* Test how revision is output */
+ a = version(0, "1", "", false);
+ varbufreset(&output);
+ varbufversion(&output, &a, vdew_parsed);
+ varbufaddc(&output, '\0');
+ test_pass(strcmp("1-", output.buf) == 0);
+
+ a = version(0, "1", NULL, false);
+ varbufreset(&output);
+ varbufversion(&output, &a, vdew_parsed);
+ varbufaddc(&output, '\0');
+ test_pass(strcmp("1", output.buf) == 0);
+}
+
+static void
test(void)
{
test_version_compare();
test_version_parse();
+ test_version_output();
}
diff --git a/src/enquiry.c b/src/enquiry.c
index 6441082..a43c562 100644
--- a/src/enquiry.c
+++ b/src/enquiry.c
@@ -289,22 +289,22 @@ assert_version_support(const char *const *argv,
}
void assertpredep(const char *const *argv) {
- struct versionrevision version = { 0, "1.1.0", NULL };
+ struct versionrevision version = { 0, "1.1.0", NULL, false };
assert_version_support(argv, &version, _("Pre-Depends field"));
}
void assertepoch(const char *const *argv) {
- struct versionrevision version = { 0, "1.4.0.7", NULL };
+ struct versionrevision version = { 0, "1.4.0.7", NULL, false };
assert_version_support(argv, &version, _("epoch"));
}
void assertlongfilenames(const char *const *argv) {
- struct versionrevision version = { 0, "1.4.1.17", NULL };
+ struct versionrevision version = { 0, "1.4.1.17", NULL, false };
assert_version_support(argv, &version, _("long filenames"));
}
void assertmulticonrep(const char *const *argv) {
- struct versionrevision version = { 0, "1.4.1.19", NULL };
+ struct versionrevision version = { 0, "1.4.1.19", NULL, false };
assert_version_support(argv, &version, _("multiple Conflicts and Replaces"));
}
--
1.7.0.5
--ZPt4rx8FFjLCG7dd
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="0002-libdpkg-keep-same-version-string-in-dependency-field.patch"
More information about the pkg-perl-maintainers
mailing list