diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2016-05-02 19:48:38 +0100 | 
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2016-05-02 19:48:38 +0100 | 
| commit | c6e09edc498cdbcb307f97e5f18861697558d6ce (patch) | |
| tree | 80bd2e4b954106fcef8eb71164f1638a2aea7b5e | |
| parent | Add a flexible extensible lexer (diff) | |
| download | gentoobrowse-api-c6e09edc498cdbcb307f97e5f18861697558d6ce.tar.bz2 gentoobrowse-api-c6e09edc498cdbcb307f97e5f18861697558d6ce.tar.xz gentoobrowse-api-c6e09edc498cdbcb307f97e5f18861697558d6ce.zip | |
Add a dependency scanner/extracter
| -rw-r--r-- | gentoobrowse-api/domain/portage-models.ice | 10 | ||||
| -rw-r--r-- | gentoobrowse-api/service/depend.cpp | 87 | ||||
| -rw-r--r-- | gentoobrowse-api/service/depend.h | 25 | ||||
| -rw-r--r-- | gentoobrowse-api/unittests/Jamfile.jam | 6 | ||||
| -rw-r--r-- | gentoobrowse-api/unittests/testDepend.cpp | 264 | 
5 files changed, 392 insertions, 0 deletions
| diff --git a/gentoobrowse-api/domain/portage-models.ice b/gentoobrowse-api/domain/portage-models.ice index ca018e8..f281aea 100644 --- a/gentoobrowse-api/domain/portage-models.ice +++ b/gentoobrowse-api/domain/portage-models.ice @@ -79,6 +79,16 @@ module Gentoo {  		StringList urls;  	}; +	class Dependency { +		StringList when; +		optional(1) string op; +		string category; +		string package; +		optional(2) string version; +		optional(3) string slot; +		StringList use; +	}; +  	sequence<Category> Categories;  	sequence<Package> Packages;  	sequence<Ebuild> Ebuilds; diff --git a/gentoobrowse-api/service/depend.cpp b/gentoobrowse-api/service/depend.cpp new file mode 100644 index 0000000..f93787e --- /dev/null +++ b/gentoobrowse-api/service/depend.cpp @@ -0,0 +1,87 @@ +#include "depend.h" +#include <boost/algorithm/string/split.hpp> + +const Glib::ustring WhenUse_Begin("\\s*(!?[[:alnum:]-_]+)\\?\\s*\\(\\s*"); +const Glib::ustring WhenUse_End("\\s*\\)\\s*"); +const Glib::ustring Or_Begin("\\s*\\|\\|\\s*\\(\\s*"); +const Glib::ustring Or_Group("\\s*\\(\\s*"); +const Glib::ustring Or_End("\\s*\\)\\s*"); +const Glib::ustring AtomSpec("\\s*" +		"([[:punct:]]+)?" // op +		"([[:alnum:]-]+)\\/" // cat +		"(((-?[[:alpha:]]+[[:digit:]]+)|[[:alpha:]_+]|(-[[:alpha:]]))+)" // package +		"(-([0-9][.0-9]*[[:alpha:]]?\\*?(_(alpha|beta|pre|rc|p))?[[:digit:]]*(-r[[:digit:]]+)?))?" // version +		"(:([^/ []+(\\/[^ []+)?))?" // slot +		"(\\[([^]]+)\\])?\\s*"); // use + +const std::string InWhen("InWhen"); +const std::string InOr("InOr"); + +namespace Portage { +	namespace Utils { +		template<typename T, typename Y> IceUtil::Optional<T> iuo(const boost::optional<Y> & x) +		{ +			if (x) { +				return *x; +			} +			return IceUtil::Optional<T>(); +		} + +		template<typename T, typename Y> std::vector<T> split(const boost::optional<Y> & x) +		{ +			std::vector<T> rtn; +			if (x) { +				boost::algorithm::split(rtn, *x, [](auto c) { return c == ','; }); +				std::sort(rtn.begin(), rtn.end()); +			} +			return rtn; +		} + +		Depend::Depend() +		{ +			// use? ( +			rules.push_back({ { InitialState, InWhen, InOr }, regex(WhenUse_Begin), [this](auto es) { +					es->pushState(InWhen); +					when.push_back(*es->pattern->match(1)); +				} }); +			// ) +			rules.push_back({ { InWhen }, regex(WhenUse_End), [this](auto es) { +					es->popState(); +					when.pop_back(); +				} }); +			// || ( +			rules.push_back({ { InitialState, InWhen, InOr }, regex(Or_Begin), [this](auto es) { +					es->pushState(InOr); +				} }); +			// || ( +			rules.push_back({ { InOr }, regex(Or_Group), [this](auto es) { +					es->pushState(InOr); +				} }); +			// ) +			rules.push_back({ { InOr }, regex(Or_End), [this](auto es) { +					es->popState(); +				} }); +			// [op]some-cat/package[-version][:slot][uses] +			rules.push_back({ { InitialState, InWhen, InOr }, regex(AtomSpec), [this](auto es) { +					ds.push_back(new Gentoo::Dependency( +							when, +							iuo<std::string>(es->pattern->match(1)), // op +							*es->pattern->match(2), // category +							*es->pattern->match(3), // package +							iuo<std::string>(es->pattern->match(8)), // version +							iuo<std::string>(es->pattern->match(13)), // slot +							split<std::string>(es->pattern->match(16)) // use +						)); +				} }); +		} + +		std::vector<Gentoo::DependencyPtr> +		Depend::parse(const std::string & s) +		{ +			Depend d; +			d.extract(s.c_str(), s.length()); +			return d.ds; +		} +	} +} + diff --git a/gentoobrowse-api/service/depend.h b/gentoobrowse-api/service/depend.h new file mode 100644 index 0000000..3acae7f --- /dev/null +++ b/gentoobrowse-api/service/depend.h @@ -0,0 +1,25 @@ +#ifndef GENTOOBROWSE_SERVICE_DEPEND_H +#define GENTOOBROWSE_SERVICE_DEPEND_H + +#include <visibility.h> +#include <istream> +#include <vector> +#include <portage-models.h> +#include "utils/lexer.h" + +namespace Portage { +	namespace Utils { +		class Depend : Gentoo::Utils::Lexer { +			private: +				Depend(); +				Gentoo::StringList when; + +			public: +				DLL_PUBLIC static std::vector<Gentoo::DependencyPtr> parse(const std::string &); +				std::vector<Gentoo::DependencyPtr> ds; +		}; +	} +} + +#endif + diff --git a/gentoobrowse-api/unittests/Jamfile.jam b/gentoobrowse-api/unittests/Jamfile.jam index 6c5ca2d..71aa67c 100644 --- a/gentoobrowse-api/unittests/Jamfile.jam +++ b/gentoobrowse-api/unittests/Jamfile.jam @@ -42,6 +42,12 @@ lib testCommon :  	<define>ROOT=\"$(me)\"  	; +run +	testDepend.cpp +	: : : +	<define>BOOST_TEST_DYN_LINK +	<library>testCommon +	: testDepend ;  run  	testMaintenance.cpp diff --git a/gentoobrowse-api/unittests/testDepend.cpp b/gentoobrowse-api/unittests/testDepend.cpp new file mode 100644 index 0000000..15b4cf3 --- /dev/null +++ b/gentoobrowse-api/unittests/testDepend.cpp @@ -0,0 +1,264 @@ +#define BOOST_TEST_MODULE TestDepend +#include <boost/test/unit_test.hpp> + +#include <depend.h> + +BOOST_AUTO_TEST_CASE( simple1 ) +{ +	auto ds = Portage::Utils::Depend::parse("sys-libs/readline"); +	BOOST_REQUIRE_EQUAL(ds.size(), 1); +	BOOST_REQUIRE(!ds[0]->op); +	BOOST_REQUIRE_EQUAL(ds[0]->category, "sys-libs"); +	BOOST_REQUIRE_EQUAL(ds[0]->package, "readline"); +	BOOST_REQUIRE(ds[0]->when.empty()); +	BOOST_REQUIRE(!ds[0]->version); +	BOOST_REQUIRE(!ds[0]->slot); +	BOOST_REQUIRE(ds[0]->use.empty()); +} + +BOOST_AUTO_TEST_CASE( simple2 ) +{ +	auto ds = Portage::Utils::Depend::parse("sys-libs/readline sys-apps/portage"); +	BOOST_REQUIRE_EQUAL(ds.size(), 2); +	BOOST_REQUIRE(!ds[0]->op); +	BOOST_REQUIRE_EQUAL(ds[0]->category, "sys-libs"); +	BOOST_REQUIRE_EQUAL(ds[0]->package, "readline"); +	BOOST_REQUIRE(ds[0]->when.empty()); +	BOOST_REQUIRE(!ds[0]->version); +	BOOST_REQUIRE(!ds[0]->slot); +	BOOST_REQUIRE(ds[0]->use.empty()); +	BOOST_REQUIRE(!ds[1]->op); +	BOOST_REQUIRE_EQUAL(ds[1]->category, "sys-apps"); +	BOOST_REQUIRE_EQUAL(ds[1]->package, "portage"); +	BOOST_REQUIRE(ds[1]->when.empty()); +	BOOST_REQUIRE(!ds[1]->version); +	BOOST_REQUIRE(!ds[1]->slot); +	BOOST_REQUIRE(ds[1]->use.empty()); +} + +BOOST_AUTO_TEST_CASE( simple2when1 ) +{ +	auto ds = Portage::Utils::Depend::parse("sys-libs/readline !maybe? ( sys-apps/portage ) other/package"); +	BOOST_REQUIRE_EQUAL(ds.size(), 3); +	BOOST_REQUIRE(!ds[0]->op); +	BOOST_REQUIRE_EQUAL(ds[0]->category, "sys-libs"); +	BOOST_REQUIRE_EQUAL(ds[0]->package, "readline"); +	BOOST_REQUIRE(ds[0]->when.empty()); +	BOOST_REQUIRE(!ds[0]->version); +	BOOST_REQUIRE(!ds[0]->slot); +	BOOST_REQUIRE(ds[0]->use.empty()); +	BOOST_REQUIRE(!ds[1]->op); +	BOOST_REQUIRE_EQUAL(ds[1]->category, "sys-apps"); +	BOOST_REQUIRE_EQUAL(ds[1]->package, "portage"); +	BOOST_REQUIRE_EQUAL(ds[1]->when.size(), 1); +	BOOST_REQUIRE_EQUAL(ds[1]->when[0], "!maybe"); +	BOOST_REQUIRE(!ds[2]->op); +	BOOST_REQUIRE_EQUAL(ds[2]->category, "other"); +	BOOST_REQUIRE_EQUAL(ds[2]->package, "package"); +	BOOST_REQUIRE(ds[2]->when.empty()); +	BOOST_REQUIRE(!ds[0]->version); +	BOOST_REQUIRE(!ds[0]->slot); +	BOOST_REQUIRE(ds[0]->use.empty()); +} + +BOOST_AUTO_TEST_CASE( simple2when2 ) +{ +	auto ds = Portage::Utils::Depend::parse("sys-libs/readline !maybe? ( and? ( sys-apps/portage ) not/this ) other/package"); +	BOOST_REQUIRE_EQUAL(ds.size(), 4); +	BOOST_REQUIRE(!ds[0]->op); +	BOOST_REQUIRE_EQUAL(ds[0]->category, "sys-libs"); +	BOOST_REQUIRE_EQUAL(ds[0]->package, "readline"); +	BOOST_REQUIRE(!ds[0]->version); +	BOOST_REQUIRE(ds[0]->when.empty()); +	BOOST_REQUIRE(!ds[1]->op); +	BOOST_REQUIRE_EQUAL(ds[1]->category, "sys-apps"); +	BOOST_REQUIRE_EQUAL(ds[1]->package, "portage"); +	BOOST_REQUIRE_EQUAL(ds[1]->when.size(), 2); +	BOOST_REQUIRE_EQUAL(ds[1]->when[0], "!maybe"); +	BOOST_REQUIRE_EQUAL(ds[1]->when[1], "and"); +	BOOST_REQUIRE(!ds[1]->version); +	BOOST_REQUIRE_EQUAL(ds[2]->category, "not"); +	BOOST_REQUIRE_EQUAL(ds[2]->package, "this"); +	BOOST_REQUIRE_EQUAL(ds[2]->when.size(), 1); +	BOOST_REQUIRE_EQUAL(ds[2]->when[0], "!maybe"); +	BOOST_REQUIRE(!ds[2]->version); +	BOOST_REQUIRE(!ds[3]->op); +	BOOST_REQUIRE_EQUAL(ds[3]->category, "other"); +	BOOST_REQUIRE_EQUAL(ds[3]->package, "package"); +	BOOST_REQUIRE(!ds[3]->version); +	BOOST_REQUIRE(ds[3]->when.empty()); +} + +BOOST_AUTO_TEST_CASE( op ) +{ +	auto ds = Portage::Utils::Depend::parse(" !sys-libs/readline "); +	BOOST_REQUIRE_EQUAL(ds.size(), 1); +	BOOST_REQUIRE(ds[0]->op); +	BOOST_REQUIRE_EQUAL(*ds[0]->op, "!"); +	BOOST_REQUIRE_EQUAL(ds[0]->category, "sys-libs"); +	BOOST_REQUIRE_EQUAL(ds[0]->package, "readline"); +	BOOST_REQUIRE(!ds[0]->version); +	BOOST_REQUIRE(ds[0]->when.empty()); +} + +BOOST_AUTO_TEST_CASE( version1 ) +{ +	auto ds = Portage::Utils::Depend::parse(" =sys-libs/readline-3 "); +	BOOST_REQUIRE_EQUAL(ds.size(), 1); +	BOOST_REQUIRE(ds[0]->op); +	BOOST_REQUIRE_EQUAL(*ds[0]->op, "="); +	BOOST_REQUIRE_EQUAL(ds[0]->category, "sys-libs"); +	BOOST_REQUIRE_EQUAL(ds[0]->package, "readline"); +	BOOST_REQUIRE(ds[0]->version); +	BOOST_REQUIRE_EQUAL(*ds[0]->version, "3"); +	BOOST_REQUIRE(ds[0]->when.empty()); +	BOOST_REQUIRE(!ds[0]->slot); +	BOOST_REQUIRE(ds[0]->use.empty()); +} + +BOOST_AUTO_TEST_CASE( version2 ) +{ +	auto ds = Portage::Utils::Depend::parse(" =sys-libs/readline2-3 "); +	BOOST_REQUIRE_EQUAL(ds.size(), 1); +	BOOST_REQUIRE(ds[0]->op); +	BOOST_REQUIRE_EQUAL(*ds[0]->op, "="); +	BOOST_REQUIRE_EQUAL(ds[0]->category, "sys-libs"); +	BOOST_REQUIRE_EQUAL(ds[0]->package, "readline2"); +	BOOST_REQUIRE(ds[0]->version); +	BOOST_REQUIRE_EQUAL(*ds[0]->version, "3"); +	BOOST_REQUIRE(ds[0]->when.empty()); +	BOOST_REQUIRE(!ds[0]->slot); +	BOOST_REQUIRE(ds[0]->use.empty()); +} + +BOOST_AUTO_TEST_CASE( special ) +{ +	auto ds = Portage::Utils::Depend::parse(" >x11-libs/Gtk+-2.0 "); +	BOOST_REQUIRE_EQUAL(ds.size(), 1); +	BOOST_REQUIRE(ds[0]->op); +	BOOST_REQUIRE_EQUAL(*ds[0]->op, ">"); +	BOOST_REQUIRE_EQUAL(ds[0]->category, "x11-libs"); +	BOOST_REQUIRE_EQUAL(ds[0]->package, "Gtk+"); +	BOOST_REQUIRE(ds[0]->version); +	BOOST_REQUIRE_EQUAL(*ds[0]->version, "2.0"); +	BOOST_REQUIRE(ds[0]->when.empty()); +} + +BOOST_AUTO_TEST_CASE( versionSuffix ) +{ +	auto ds = Portage::Utils::Depend::parse(" >x11-libs/Gtk+-2.0.0_alpha "); +	BOOST_REQUIRE(ds[0]->version); +	BOOST_REQUIRE_EQUAL(*ds[0]->version, "2.0.0_alpha"); +} + +BOOST_AUTO_TEST_CASE( versionSuffixNum ) +{ +	auto ds = Portage::Utils::Depend::parse(" >x11-libs/Gtk+-2.0.0_alpha43 "); +	BOOST_REQUIRE(ds[0]->version); +	BOOST_REQUIRE_EQUAL(*ds[0]->version, "2.0.0_alpha43"); +} + +BOOST_AUTO_TEST_CASE( versionSuffixNumRev ) +{ +	auto ds = Portage::Utils::Depend::parse(" >x11-libs/Gtk+-2.0.0_alpha43-r33 "); +	BOOST_REQUIRE(ds[0]->version); +	BOOST_REQUIRE_EQUAL(*ds[0]->version, "2.0.0_alpha43-r33"); +} + +BOOST_AUTO_TEST_CASE( versionLetter ) +{ +	auto ds = Portage::Utils::Depend::parse(" >x11-libs/Gtk+-2.0.0g "); +	BOOST_REQUIRE(ds[0]->version); +	BOOST_REQUIRE_EQUAL(*ds[0]->version, "2.0.0g"); +} + +BOOST_AUTO_TEST_CASE( versionRange ) +{ +	auto ds = Portage::Utils::Depend::parse(" >x11-libs/Gtk+-2.0.0* "); +	BOOST_REQUIRE(ds[0]->version); +	BOOST_REQUIRE_EQUAL(*ds[0]->version, "2.0.0*"); +} + +BOOST_AUTO_TEST_CASE( versionSlot ) +{ +	auto ds = Portage::Utils::Depend::parse(" >x11-libs/Gtk+-2.0.0:foo"); +	BOOST_REQUIRE(ds[0]->version); +	BOOST_REQUIRE_EQUAL(*ds[0]->version, "2.0.0"); +	BOOST_REQUIRE(ds[0]->slot); +	BOOST_REQUIRE_EQUAL(ds[0]->slot, "foo"); +	BOOST_REQUIRE(ds[0]->use.empty()); +} + +BOOST_AUTO_TEST_CASE( slot ) +{ +	auto ds = Portage::Utils::Depend::parse(" >x11-libs/Gtk+:foo"); +	BOOST_REQUIRE(!ds[0]->version); +	BOOST_REQUIRE(ds[0]->slot); +	BOOST_REQUIRE_EQUAL(ds[0]->slot, "foo"); +	BOOST_REQUIRE(ds[0]->use.empty()); +} + +BOOST_AUTO_TEST_CASE( versionSlotSubSlot ) +{ +	auto ds = Portage::Utils::Depend::parse(" >x11-libs/Gtk+-2.0.0:foo/bar"); +	BOOST_REQUIRE(ds[0]->version); +	BOOST_REQUIRE_EQUAL(*ds[0]->version, "2.0.0"); +	BOOST_REQUIRE(ds[0]->slot); +	BOOST_REQUIRE_EQUAL(ds[0]->slot, "foo/bar"); +	BOOST_REQUIRE(ds[0]->use.empty()); +} + +BOOST_AUTO_TEST_CASE( slotUse ) +{ +	auto ds = Portage::Utils::Depend::parse(" >x11-libs/Gtk+:foo[bar,baz]"); +	BOOST_REQUIRE(!ds[0]->version); +	BOOST_REQUIRE(ds[0]->slot); +	BOOST_REQUIRE_EQUAL(ds[0]->slot, "foo"); +	BOOST_REQUIRE_EQUAL(ds[0]->use.size(), 2); +	BOOST_REQUIRE_EQUAL(ds[0]->use[0], "bar"); +	BOOST_REQUIRE_EQUAL(ds[0]->use[1], "baz"); +} + +BOOST_AUTO_TEST_CASE( use ) +{ +	auto ds = Portage::Utils::Depend::parse(" >x11-libs/Gtk+[moo,cow]"); +	BOOST_REQUIRE(!ds[0]->version); +	BOOST_REQUIRE(!ds[0]->slot); +	BOOST_REQUIRE_EQUAL(ds[0]->use.size(), 2); +	BOOST_REQUIRE_EQUAL(ds[0]->use[0], "cow"); +	BOOST_REQUIRE_EQUAL(ds[0]->use[1], "moo"); +} + +BOOST_AUTO_TEST_CASE( aorb ) +{ +	auto ds = Portage::Utils::Depend::parse(" || ( cat/a cat/b  ) "); +	BOOST_REQUIRE_EQUAL(ds.size(), 2); +	BOOST_REQUIRE(ds[0]->when.empty()); +	BOOST_REQUIRE(ds[1]->when.empty()); +} + +BOOST_AUTO_TEST_CASE( deepor ) +{ +	auto ds = Portage::Utils::Depend::parse(" || ( ( cat/c cat/d ) ( cat/a cat/b ) ) "); +	BOOST_REQUIRE_EQUAL(ds.size(), 4); +	BOOST_REQUIRE(ds[0]->when.empty()); +	BOOST_REQUIRE(ds[1]->when.empty()); +	BOOST_REQUIRE(ds[2]->when.empty()); +	BOOST_REQUIRE(ds[3]->when.empty()); +} + +BOOST_AUTO_TEST_CASE( annoyed1 ) +{ +	auto ds = Portage::Utils::Depend::parse(" !<=app-emulation/emul-linux-x86-baselibs-20140508-r1 "); +	BOOST_REQUIRE_EQUAL(ds.size(), 1); +	BOOST_REQUIRE(ds[0]->op); +	BOOST_REQUIRE_EQUAL(*ds[0]->op, "!<="); +	BOOST_REQUIRE_EQUAL(ds[0]->category, "app-emulation"); +	BOOST_REQUIRE_EQUAL(ds[0]->package, "emul-linux-x86-baselibs"); +	BOOST_REQUIRE(ds[0]->version); +	BOOST_REQUIRE_EQUAL(*ds[0]->version, "20140508-r1"); +	BOOST_REQUIRE(ds[0]->when.empty()); +	BOOST_REQUIRE(!ds[0]->slot); +	BOOST_REQUIRE(ds[0]->use.empty()); +} + | 
