diff options
-rw-r--r-- | apt-pkg/deb/deblistparser.cc | 112 | ||||
-rwxr-xr-x | test/integration/test-bug-661537-build-profiles-support | 86 | ||||
-rw-r--r-- | test/libapt/parsedepends_test.cc | 29 |
3 files changed, 130 insertions, 97 deletions
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 7d4fd52cf..8311b5d7d 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -635,72 +635,94 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop, if (ParseRestrictionsList == true) { - // Parse a restrictions list - if (I != Stop && *I == '<') + // Parse a restrictions formula which is in disjunctive normal form: + // (foo AND bar) OR (blub AND bla) + + std::vector<string> const profiles = APT::Configuration::getBuildProfiles(); + + // if the next character is a restriction list, then by default the + // dependency does not apply and the conditions have to be checked + // if the next character is not a restriction list, then by default the + // dependency applies + bool applies1 = (*I != '<'); + while (I != Stop) { + if (*I != '<') + break; + ++I; // malformed if (unlikely(I == Stop)) return 0; - std::vector<string> const profiles = APT::Configuration::getBuildProfiles(); - const char *End = I; - bool Found = false; - bool NegRestriction = false; - while (I != Stop) - { - // look for whitespace or ending '>' - for (;End != Stop && !isspace(*End) && *End != '>'; ++End); - if (unlikely(End == Stop)) - return 0; - - if (*I == '!') + // if of the prior restriction list is already fulfilled, then + // we can just skip to the end of the current list + if (applies1) { + for (;End != Stop && *End != '>'; ++End); + I = ++End; + // skip whitespace + for (;I != Stop && isspace(*I) != 0; I++); + } else { + bool applies2 = true; + // all the conditions inside a restriction list have to be + // met so once we find one that is not met, we can skip to + // the end of this list + while (I != Stop) { - NegRestriction = true; - ++I; - } + // look for whitespace or ending '>' + // End now points to the character after the current term + for (;End != Stop && !isspace(*End) && *End != '>'; ++End); - std::string restriction(I, End); + if (unlikely(End == Stop)) + return 0; - std::string prefix = "profile."; - // only support for "profile" prefix, ignore others - if (restriction.size() > prefix.size() && - restriction.substr(0, prefix.size()) == prefix) - { - // get the name of the profile - restriction = restriction.substr(prefix.size()); + bool NegRestriction = false; + if (*I == '!') + { + NegRestriction = true; + ++I; + } + + std::string restriction(I, End); if (restriction.empty() == false && profiles.empty() == false && - std::find(profiles.begin(), profiles.end(), restriction) != profiles.end()) + std::find(profiles.begin(), profiles.end(), restriction) != profiles.end()) { - Found = true; - if (I[-1] != '!') - NegRestriction = false; - // we found a match, so fast-forward to the end of the wildcards - for (; End != Stop && *End != '>'; ++End); + if (NegRestriction) { + applies2 = false; + // since one of the terms does not apply we don't have to check the others + for (; End != Stop && *End != '>'; ++End); + } + } else { + if (!NegRestriction) { + applies2 = false; + // since one of the terms does not apply we don't have to check the others + for (; End != Stop && *End != '>'; ++End); + } + } + + if (*End++ == '>') { + I = End; + // skip whitespace + for (;I != Stop && isspace(*I) != 0; I++); + break; } - } - if (*End++ == '>') { I = End; - break; + // skip whitespace + for (;I != Stop && isspace(*I) != 0; I++); + } + if (applies2) { + applies1 = true; } - - I = End; - for (;I != Stop && isspace(*I) != 0; I++); } - - if (NegRestriction == true) - Found = !Found; - - if (Found == false) - Package = ""; /* not for this restriction */ } - // Skip whitespace - for (;I != Stop && isspace(*I) != 0; I++); + if (applies1 == false) { + Package = ""; //not for this restriction + } } if (I != Stop && *I == '|') diff --git a/test/integration/test-bug-661537-build-profiles-support b/test/integration/test-bug-661537-build-profiles-support index ae1403f71..6c850fdf9 100755 --- a/test/integration/test-bug-661537-build-profiles-support +++ b/test/integration/test-bug-661537-build-profiles-support @@ -11,18 +11,16 @@ insertinstalledpackage 'build-essential' 'all' '0' 'Multi-Arch: foreign' insertpackage 'unstable' 'foo' 'all' '1.0' insertpackage 'unstable' 'bar' 'all' '1.0' -insertsource 'unstable' 'buildprofiles' 'any' '1' 'Build-Depends: foo (>= 1.0) [i386 arm] <!profile.stage1 !profile.cross>, bar' +insertsource 'unstable' 'buildprofiles' 'any' '1' 'Build-Depends: foo (>= 1.0) [i386 arm] <!stage1 !cross>, bar' # table from https://wiki.debian.org/BuildProfileSpec -insertsource 'unstable' 'spec-1' 'any' '1' 'Build-Depends: foo <!profile.stage1>' -insertsource 'unstable' 'spec-2' 'any' '1' 'Build-Depends: foo <profile.stage1>' -insertsource 'unstable' 'spec-3' 'any' '1' 'Build-Depends: foo <!profile.stage1 !profile.notest>' -insertsource 'unstable' 'spec-4' 'any' '1' 'Build-Depends: foo <profile.stage1 profile.notest>' -insertsource 'unstable' 'spec-5' 'any' '1' 'Build-Depends: foo <!profile.stage1 profile.notest>' -insertsource 'unstable' 'spec-6' 'any' '1' 'Build-Depends: foo <profile.stage1 !profile.notest>' -# multiple stanzas not supported: error out -insertsource 'unstable' 'spec-7' 'any' '1' 'Build-Depends: foo <profile.stage1><!profile.notest>' -insertsource 'unstable' 'spec-8' 'any' '1' 'Build-Depends: foo <profile.stage1> <!profile.notest>' +insertsource 'unstable' 'spec-1' 'any' '1' 'Build-Depends: foo <!stage1>' +insertsource 'unstable' 'spec-2' 'any' '1' 'Build-Depends: foo <stage1>' +insertsource 'unstable' 'spec-3' 'any' '1' 'Build-Depends: foo <!stage1 !notest>' +insertsource 'unstable' 'spec-4' 'any' '1' 'Build-Depends: foo <stage1 notest>' +insertsource 'unstable' 'spec-5' 'any' '1' 'Build-Depends: foo <!stage1 notest>' +insertsource 'unstable' 'spec-6' 'any' '1' 'Build-Depends: foo <stage1 !notest>' +insertsource 'unstable' 'spec-7' 'any' '1' 'Build-Depends: foo <stage1> <!notest>' setupaptarchive @@ -72,7 +70,7 @@ Building dependency tree... 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' msgtest 'Check if version of installed dpkg is high enough for' 'build profiles support' -if dpkg --compare-versions "$(command dpkg-query --showformat='${Version}' --show dpkg)" 'ge' '1.17.2'; then +if dpkg --compare-versions "$(command dpkg-query --showformat='${Version}' --show dpkg)" 'ge' '1.17.14'; then msgpass testwithdpkg() { msgtest "Test with" "dpkg-checkbuilddeps -d '$1' -P '$2'" @@ -113,35 +111,37 @@ testprofile() { testwithdpkg "$2" "$3" "$4" } -testprofile 'spec-1' 'foo <!profile.stage1>' '' "$KEEP" -testprofile 'spec-1' 'foo <!profile.stage1>' 'stage1' "$DROP" -testprofile 'spec-1' 'foo <!profile.stage1>' 'notest' "$KEEP" -testprofile 'spec-1' 'foo <!profile.stage1>' 'stage1,notest' "$DROP" - -testprofile 'spec-2' 'foo <profile.stage1>' '' "$DROP" -testprofile 'spec-2' 'foo <profile.stage1>' 'stage1' "$KEEP" -testprofile 'spec-2' 'foo <profile.stage1>' 'notest' "$DROP" -testprofile 'spec-2' 'foo <profile.stage1>' 'stage1,notest' "$KEEP" - -testprofile 'spec-3' 'foo <!profile.stage1 !profile.notest>' '' "$KEEP" -testprofile 'spec-3' 'foo <!profile.stage1 !profile.notest>' 'stage1' "$DROP" -testprofile 'spec-3' 'foo <!profile.stage1 !profile.notest>' 'notest' "$DROP" -testprofile 'spec-3' 'foo <!profile.stage1 !profile.notest>' 'stage1,notest' "$DROP" - -testprofile 'spec-4' 'foo <profile.stage1 profile.notest>' '' "$DROP" -testprofile 'spec-4' 'foo <profile.stage1 profile.notest>' 'stage1' "$KEEP" -testprofile 'spec-4' 'foo <profile.stage1 profile.notest>' 'notest' "$KEEP" -testprofile 'spec-4' 'foo <profile.stage1 profile.notest>' 'stage1,notest' "$KEEP" - -testprofile 'spec-5' 'foo <!profile.stage1 profile.notest>' '' "$KEEP" -testprofile 'spec-5' 'foo <!profile.stage1 profile.notest>' 'stage1' "$DROP" -testprofile 'spec-5' 'foo <!profile.stage1 profile.notest>' 'notest' "$KEEP" -testprofile 'spec-5' 'foo <!profile.stage1 profile.notest>' 'stage1,notest' "$DROP" - -testprofile 'spec-6' 'foo <profile.stage1 !profile.notest>' '' "$KEEP" -testprofile 'spec-6' 'foo <profile.stage1 !profile.notest>' 'stage1' "$KEEP" -testprofile 'spec-6' 'foo <profile.stage1 !profile.notest>' 'notest' "$DROP" -testprofile 'spec-6' 'foo <profile.stage1 !profile.notest>' 'stage1,notest' "$KEEP" - -testfailure aptget build-dep spec-7 -s -testfailure aptget build-dep spec-8 -s +testprofile 'spec-1' 'foo <!stage1>' '' "$KEEP" +testprofile 'spec-1' 'foo <!stage1>' 'stage1' "$DROP" +testprofile 'spec-1' 'foo <!stage1>' 'notest' "$KEEP" +testprofile 'spec-1' 'foo <!stage1>' 'stage1,notest' "$DROP" + +testprofile 'spec-2' 'foo <stage1>' '' "$DROP" +testprofile 'spec-2' 'foo <stage1>' 'stage1' "$KEEP" +testprofile 'spec-2' 'foo <stage1>' 'notest' "$DROP" +testprofile 'spec-2' 'foo <stage1>' 'stage1,notest' "$KEEP" + +testprofile 'spec-3' 'foo <!stage1 !notest>' '' "$KEEP" +testprofile 'spec-3' 'foo <!stage1 !notest>' 'stage1' "$DROP" +testprofile 'spec-3' 'foo <!stage1 !notest>' 'notest' "$DROP" +testprofile 'spec-3' 'foo <!stage1 !notest>' 'stage1,notest' "$DROP" + +testprofile 'spec-4' 'foo <stage1 notest>' '' "$DROP" +testprofile 'spec-4' 'foo <stage1 notest>' 'stage1' "$DROP" +testprofile 'spec-4' 'foo <stage1 notest>' 'notest' "$DROP" +testprofile 'spec-4' 'foo <stage1 notest>' 'stage1,notest' "$KEEP" + +testprofile 'spec-5' 'foo <!stage1 notest>' '' "$DROP" +testprofile 'spec-5' 'foo <!stage1 notest>' 'stage1' "$DROP" +testprofile 'spec-5' 'foo <!stage1 notest>' 'notest' "$KEEP" +testprofile 'spec-5' 'foo <!stage1 notest>' 'stage1,notest' "$DROP" + +testprofile 'spec-6' 'foo <stage1 !notest>' '' "$DROP" +testprofile 'spec-6' 'foo <stage1 !notest>' 'stage1' "$KEEP" +testprofile 'spec-6' 'foo <stage1 !notest>' 'notest' "$DROP" +testprofile 'spec-6' 'foo <stage1 !notest>' 'stage1,notest' "$DROP" + +testprofile 'spec-7' 'foo <stage1> <!notest>' '' "$KEEP" +testprofile 'spec-7' 'foo <stage1> <!notest>' 'stage1' "$KEEP" +testprofile 'spec-7' 'foo <stage1> <!notest>' 'notest' "$DROP" +testprofile 'spec-7' 'foo <stage1> <!notest>' 'stage1,notest' "$KEEP" diff --git a/test/libapt/parsedepends_test.cc b/test/libapt/parsedepends_test.cc index 52eac8232..f644599bd 100644 --- a/test/libapt/parsedepends_test.cc +++ b/test/libapt/parsedepends_test.cc @@ -33,9 +33,10 @@ static void parseDependency(bool const StripMultiArch, bool const ParseArchFlag "os-for-me [ linux-any ], " "cpu-not-for-me [ any-armel ], " "os-not-for-me [ kfreebsd-any ], " - "not-in-stage1 <!profile.stage1>, " - "not-in-stage1-or-nodoc <!profile.nodoc !profile.stage1>, " - "only-in-stage1 <unknown.unknown profile.stage1>, " + "not-in-stage1 <!stage1>, " + "not-stage1-and-not-nodoc <!nodoc !stage1>, " + "not-stage1-or-not-nodoc <!nodoc> <!stage1>, " + "unknown-profile <unknown stage1>, " "overlord-dev:any (= 7.15.3~) | overlord-dev:native (>> 7.15.5), " ; @@ -184,7 +185,7 @@ static void parseDependency(bool const StripMultiArch, bool const ParseArchFlag if (ParseRestrictionsList == true) { Start = debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch, ParseRestrictionsList); - EXPECT_EQ("", Package); // not-in-stage1-or-in-nodoc + EXPECT_EQ("", Package); // not-stage1-and-not-nodoc } else { EXPECT_EQ(true, 0 == debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch, ParseRestrictionsList)); Start = strstr(Start, ","); @@ -193,7 +194,16 @@ static void parseDependency(bool const StripMultiArch, bool const ParseArchFlag if (ParseRestrictionsList == true) { Start = debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch, ParseRestrictionsList); - EXPECT_EQ("only-in-stage1", Package); + EXPECT_EQ("not-stage1-or-not-nodoc", Package); + } else { + EXPECT_EQ(true, 0 == debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch, ParseRestrictionsList)); + Start = strstr(Start, ","); + Start++; + } + + if (ParseRestrictionsList == true) { + Start = debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch, ParseRestrictionsList); + EXPECT_EQ("", Package); // unknown-profile } else { EXPECT_EQ(true, 0 == debListParser::ParseDepends(Start, End, Package, Version, Op, ParseArchFlags, StripMultiArch, ParseRestrictionsList)); Start = strstr(Start, ","); @@ -232,10 +242,11 @@ test: SCOPED_TRACE(std::string("ParseRestrictionsList: ") + (ParseRestrictionsList ? "true" : "false")); parseDependency(StripMultiArch, ParseArchFlags, ParseRestrictionsList); } - if (StripMultiArch == false) - if (ParseArchFlags == false) - ParseRestrictionsList = !ParseRestrictionsList; - ParseArchFlags = !ParseArchFlags; + if (StripMultiArch == false) { + if (ParseArchFlags == false) + ParseRestrictionsList = !ParseRestrictionsList; + ParseArchFlags = !ParseArchFlags; + } StripMultiArch = !StripMultiArch; runner++; |