aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar David Leverton <levertond@googlemail.com> 2008-03-30 21:24:19 +0000
committerAvatar David Leverton <levertond@googlemail.com> 2008-03-30 21:24:19 +0000
commit5b457721ba818a5d29cc77beddf06b86d1bd6292 (patch)
treed89c91d8a4a76a8773f8253f4689bfbc27d237bc
parent84def64976fb62df7c8ff6d9fa0ced2164e63c67 (diff)
downloadpaludis-5b457721ba818a5d29cc77beddf06b86d1bd6292.tar.gz
paludis-5b457721ba818a5d29cc77beddf06b86d1bd6292.tar.xz
Same for the provides cache.
-rw-r--r--paludis/repositories/e/vdb_repository.cc272
-rw-r--r--paludis/repositories/e/vdb_repository.hh2
-rw-r--r--paludis/repositories/e/vdb_repository_TEST.cc291
-rwxr-xr-xpaludis/repositories/e/vdb_repository_TEST_setup.sh51
4 files changed, 508 insertions, 108 deletions
diff --git a/paludis/repositories/e/vdb_repository.cc b/paludis/repositories/e/vdb_repository.cc
index 6597433..73f4d6b 100644
--- a/paludis/repositories/e/vdb_repository.cc
+++ b/paludis/repositories/e/vdb_repository.cc
@@ -68,12 +68,16 @@
#include <paludis/util/tokeniser.hh>
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/kc.hh>
+#include <paludis/util/create_iterator-impl.hh>
#include <fstream>
#include <functional>
#include <algorithm>
#include <vector>
#include <list>
+#include <map>
+#include <cstring>
+#include <cerrno>
using namespace paludis;
using namespace paludis::erepository;
@@ -82,6 +86,7 @@ using namespace paludis::erepository;
typedef MakeHashedMap<CategoryNamePart, tr1::shared_ptr<QualifiedPackageNameSet> >::Type CategoryMap;
typedef MakeHashedMap<QualifiedPackageName, tr1::shared_ptr<PackageIDSequence> >::Type IDMap;
+typedef std::map<std::pair<QualifiedPackageName, VersionSpec>, tr1::shared_ptr<const Sequence<QualifiedPackageName> > > ProvidesMap;
namespace paludis
{
@@ -97,6 +102,8 @@ namespace paludis
mutable IDMap ids;
mutable tr1::shared_ptr<RepositoryProvidesInterface::ProvidesSequence> provides;
+ mutable tr1::shared_ptr<ProvidesMap> provides_map;
+ mutable bool tried_provides_cache, used_provides_cache;
tr1::shared_ptr<RepositoryNameCache> names_cache;
Implementation(const VDBRepository * const, const VDBRepositoryParams &, tr1::shared_ptr<Mutex> = make_shared_ptr(new Mutex));
@@ -115,6 +122,8 @@ namespace paludis
params(p),
big_nasty_mutex(m),
has_category_names(false),
+ tried_provides_cache(false),
+ used_provides_cache(false),
names_cache(new RepositoryNameCache(p.names_cache, r)),
location_key(new LiteralMetadataValueKey<FSEntry> ("location", "location",
mkt_significant, params.location)),
@@ -455,6 +464,13 @@ VDBRepository::perform_uninstall(const tr1::shared_ptr<const ERepositoryID> & id
}
if (only)
_imp->names_cache->remove(id->name());
+
+ if (_imp->used_provides_cache || (! _imp->tried_provides_cache && load_provided_using_cache()))
+ {
+ _imp->provides_map->erase(std::make_pair(id->name(), id->version()));
+ write_provides_cache();
+ _imp->provides.reset();
+ }
}
}
@@ -479,8 +495,32 @@ VDBRepository::provided_packages() const
if (_imp->provides)
return _imp->provides;
- if (! load_provided_using_cache())
- load_provided_the_slow_way();
+ Context context("When finding provided packages for '" + stringify(name()) + "':");
+
+ if (! _imp->provides_map)
+ {
+ if (! load_provided_using_cache())
+ load_provided_the_slow_way();
+ }
+
+ _imp->provides.reset(new RepositoryProvidesInterface::ProvidesSequence);
+ for (ProvidesMap::const_iterator it(_imp->provides_map->begin()),
+ it_end(_imp->provides_map->end()); it_end != it; ++it)
+ {
+ tr1::shared_ptr<const ERepositoryID> id(package_id_if_exists(it->first.first, it->first.second));
+ if (! id)
+ {
+ Log::get_instance()->message(ll_warning, lc_context) <<
+ "No package available for '" << it->first.first << " " << it->first.second << "'";
+ continue;
+ }
+
+ for (Sequence<QualifiedPackageName>::ConstIterator it2(it->second->begin()),
+ it2_end(it->second->end()); it2_end != it2; ++it2)
+ _imp->provides->push_back(RepositoryProvidesEntry::named_create()
+ (k::virtual_name(), *it2)
+ (k::provided_by(), id));
+ }
return _imp->provides;
}
@@ -489,14 +529,13 @@ bool
VDBRepository::load_provided_using_cache() const
{
Lock l(*_imp->big_nasty_mutex);
+ _imp->tried_provides_cache = true;
if (_imp->params.provides_cache == FSEntry("/var/empty"))
return false;
Context context("When loading VDB PROVIDEs map using '" + stringify(_imp->params.provides_cache) + "':");
- tr1::shared_ptr<ProvidesSequence> result(new ProvidesSequence);
-
if (! _imp->params.provides_cache.is_regular_file())
{
Log::get_instance()->message(ll_warning, lc_no_context, "Provides cache at '"
@@ -509,10 +548,10 @@ VDBRepository::load_provided_using_cache() const
std::string version;
std::getline(provides_cache, version);
- if (version != "paludis-2")
+ if (version != "paludis-3")
{
Log::get_instance()->message(ll_warning, lc_no_context, "Can't use provides cache at '"
- + stringify(_imp->params.provides_cache) + "' because format '" + version + "' is not 'paludis-2'");
+ + stringify(_imp->params.provides_cache) + "' because format '" + version + "' is not 'paludis-3'");
return false;
}
@@ -522,47 +561,108 @@ VDBRepository::load_provided_using_cache() const
{
Log::get_instance()->message(ll_warning, lc_no_context, "Can't use provides cache at '"
+ stringify(_imp->params.provides_cache) + "' because it was generated for repository '"
- + for_name + "'. You must not have multiple name caches at the same location.");
+ + for_name + "'. You must not have multiple provides caches at the same location.");
return false;
}
+ _imp->provides_map.reset(new ProvidesMap);
+
std::string line;
while (std::getline(provides_cache, line))
{
- std::vector<std::string> tokens;
- tokenise_whitespace(line, std::back_inserter(tokens));
- if (tokens.size() < 3)
- continue;
+ try
+ {
+ std::vector<std::string> tokens;
+ tokenise_whitespace(line, std::back_inserter(tokens));
+ if (tokens.size() < 3)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Not using PROVIDES cache line '" +
+ line + "' as it contains fewer than three tokens");
+ continue;
+ }
- QualifiedPackageName q(tokens.at(0));
- VersionSpec v(tokens.at(1));
+ QualifiedPackageName q(tokens.at(0));
+ VersionSpec v(tokens.at(1));
- tr1::shared_ptr<const PackageID> id(package_id_if_exists(q, v));
- if (! id)
+ tr1::shared_ptr<Sequence<QualifiedPackageName> > qpns(new Sequence<QualifiedPackageName>);
+ std::copy(tokens.begin() + 2, tokens.end(), create_inserter<QualifiedPackageName>(qpns->back_inserter()));
+
+ if (_imp->provides_map->end() != _imp->provides_map->find(std::make_pair(q, v)))
+ Log::get_instance()->message(ll_warning, lc_context, "Not using PROVIDES cache line '" +
+ line + "' as it names a package that has already been specified");
+ else
+ _imp->provides_map->insert(std::make_pair(std::make_pair(q, v), qpns));
+ }
+ catch (const InternalError &)
{
- Log::get_instance()->message(ll_warning, lc_context) << "No package available for line '"
- << line << "'";
- continue;
+ throw;
+ }
+ catch (const Exception & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Not using PROVIDES cache line '" +
+ line + "' due to exception '" + e.message() + "' (" + e.what() + ")");
}
-
- DepSpecFlattener<ProvideSpecTree, PackageDepSpec> f(_imp->params.environment);
- tr1::shared_ptr<ProvideSpecTree::ConstItem> pp(parse_provide(
- join(next(next(tokens.begin())), tokens.end(), " "),
- _imp->params.environment, id,
- *EAPIData::get_instance()->eapi_from_string("paludis-1")));
- pp->accept(f);
-
- for (DepSpecFlattener<ProvideSpecTree, PackageDepSpec>::ConstIterator p(f.begin()), p_end(f.end()) ; p != p_end ; ++p)
- result->push_back(RepositoryProvidesEntry::named_create()
- (k::virtual_name(), QualifiedPackageName((*p)->text()))
- (k::provided_by(), id));
}
- _imp->provides = result;
+ _imp->used_provides_cache = true;
return true;
}
void
+VDBRepository::provides_from_package_id(const PackageID & id) const
+{
+ Context context("When loading VDB PROVIDEs entry for '" + stringify(id) + "':");
+
+ try
+ {
+ if (! id.provide_key())
+ return;
+
+ tr1::shared_ptr<const ProvideSpecTree::ConstItem> provide(id.provide_key()->value());
+ DepSpecFlattener<ProvideSpecTree, PackageDepSpec> f(_imp->params.environment);
+ provide->accept(f);
+
+ tr1::shared_ptr<Sequence<QualifiedPackageName> > qpns(new Sequence<QualifiedPackageName>);
+
+ for (DepSpecFlattener<ProvideSpecTree, PackageDepSpec>::ConstIterator
+ p(f.begin()), p_end(f.end()) ; p != p_end ; ++p)
+ {
+ QualifiedPackageName pp((*p)->text());
+
+ if (pp.category != CategoryNamePart("virtual"))
+ Log::get_instance()->message(ll_warning, lc_no_context, "PROVIDE of non-virtual '"
+ + stringify(pp) + "' from '" + stringify(id) + "' will not work as expected");
+
+ qpns->push_back(pp);
+ }
+
+ ProvidesMap::iterator it(_imp->provides_map->find(std::make_pair(id.name(), id.version())));
+ if (qpns->empty())
+ {
+ if (_imp->provides_map->end() != it)
+ _imp->provides_map->erase(it);
+ }
+ else
+ {
+ if (_imp->provides_map->end() == it)
+ _imp->provides_map->insert(std::make_pair(std::make_pair(id.name(), id.version()), qpns));
+ else
+ it->second = qpns;
+ }
+ }
+ catch (const InternalError &)
+ {
+ throw;
+ }
+ catch (const Exception & ee)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Skipping VDB PROVIDE entry for '"
+ + stringify(id) + "' due to exception '"
+ + stringify(ee.message()) + "' (" + stringify(ee.what()) + ")");
+ }
+}
+
+void
VDBRepository::load_provided_the_slow_way() const
{
Lock l(*_imp->big_nasty_mutex);
@@ -572,8 +672,7 @@ VDBRepository::load_provided_the_slow_way() const
Context context("When loading VDB PROVIDEs map the slow way:");
Log::get_instance()->message(ll_debug, lc_no_context, "Starting VDB PROVIDEs map creation");
-
- tr1::shared_ptr<ProvidesSequence> result(new ProvidesSequence);
+ _imp->provides_map.reset(new ProvidesMap);
need_category_names();
std::for_each(_imp->categories.begin(), _imp->categories.end(),
@@ -584,51 +683,38 @@ VDBRepository::load_provided_the_slow_way() const
for (IDMap::const_iterator i(_imp->ids.begin()), i_end(_imp->ids.end()) ;
i != i_end ; ++i)
- {
for (PackageIDSequence::ConstIterator e(i->second->begin()), e_end(i->second->end()) ;
e != e_end ; ++e)
- {
- Context loop_context("When loading VDB PROVIDEs entry for '" + stringify(**e) + "':");
-
- try
- {
- if (! (*e)->provide_key())
- continue;
-
- tr1::shared_ptr<const ProvideSpecTree::ConstItem> provide((*e)->provide_key()->value());;
- DepSpecFlattener<ProvideSpecTree, PackageDepSpec> f(_imp->params.environment);
- provide->accept(f);
+ provides_from_package_id(**e);
- for (DepSpecFlattener<ProvideSpecTree, PackageDepSpec>::ConstIterator
- p(f.begin()), p_end(f.end()) ; p != p_end ; ++p)
- {
- QualifiedPackageName pp((*p)->text());
+ Log::get_instance()->message(ll_debug, lc_no_context) << "Done VDB PROVIDEs map creation";
+}
- if (pp.category != CategoryNamePart("virtual"))
- Log::get_instance()->message(ll_warning, lc_no_context, "PROVIDE of non-virtual '"
- + stringify(pp) + "' from '" + stringify(**e) + "' will not work as expected");
+void
+VDBRepository::write_provides_cache() const
+{
+ Context context("When saving provides cache to '" + stringify(_imp->params.provides_cache) + "':");
- result->push_back(RepositoryProvidesEntry::named_create()
- (k::virtual_name(), pp)
- (k::provided_by(), *e));
- }
- }
- catch (const InternalError &)
- {
- throw;
- }
- catch (const Exception & ee)
- {
- Log::get_instance()->message(ll_warning, lc_no_context, "Skipping VDB PROVIDE entry for '"
- + stringify(**e) + "' due to exception '"
- + stringify(ee.message()) + "' (" + stringify(ee.what()) + ")");
- }
- }
+ std::ofstream f(stringify(_imp->params.provides_cache).c_str());
+ if (! f)
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Cannot write to '" <<
+ _imp->params.provides_cache << "': " << std::strerror(errno);
+ return;
}
- Log::get_instance()->message(ll_debug, lc_no_context) << "Done VDB PROVIDEs map creation";
+ f << "paludis-3" << std::endl;
+ f << name() << std::endl;
- _imp->provides = result;
+ for (ProvidesMap::const_iterator it(_imp->provides_map->begin()),
+ it_end(_imp->provides_map->end()); it_end != it; ++it)
+ {
+ f << it->first.first << " " << it->first.second;
+ for (Sequence<QualifiedPackageName>::ConstIterator it2(it->second->begin()),
+ it2_end(it->second->end()); it2_end != it2; ++it2)
+ f << " " << *it2;
+ f << std::endl;
+ }
}
void
@@ -656,43 +742,8 @@ VDBRepository::regenerate_provides_cache() const
FSEntry(_imp->params.provides_cache).unlink();
_imp->params.provides_cache.dirname().mkdir();
- need_category_names();
- std::for_each(_imp->categories.begin(), _imp->categories.end(),
- tr1::bind(tr1::mem_fn(&VDBRepository::need_package_ids), this,
- tr1::bind<CategoryNamePart>(tr1::mem_fn(
- &std::pair<const CategoryNamePart, tr1::shared_ptr<QualifiedPackageNameSet> >::first), _1)));
-
- std::ofstream f(stringify(_imp->params.provides_cache).c_str());
- if (! f)
- {
- Log::get_instance()->message(ll_warning, lc_context) << "Cannot write to '" <<
- _imp->params.provides_cache << "'";
- return;
- }
-
- f << "paludis-2" << std::endl;
- f << name() << std::endl;
-
- for (IDMap::const_iterator i(_imp->ids.begin()), i_end(_imp->ids.end()) ;
- i != i_end ; ++i)
- {
- for (PackageIDSequence::ConstIterator e(i->second->begin()), e_end(i->second->end()) ;
- e != e_end ; ++e)
- {
- if (! (*e)->provide_key())
- continue;
-
- tr1::shared_ptr<const ProvideSpecTree::ConstItem> provide((*e)->provide_key()->value());
- StringifyFormatter ff;
- DepSpecPrettyPrinter p(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
- provide->accept(p);
- std::string provide_str(strip_leading(strip_trailing(stringify(p), " \t\r\n"), " \t\r\n"));
- if (provide_str.empty())
- continue;
-
- f << (*e)->name() << " " << (*e)->version() << " " << provide_str << std::endl;
- }
- }
+ load_provided_the_slow_way();
+ write_provides_cache();
}
tr1::shared_ptr<const CategoryNamePartSet>
@@ -797,6 +848,13 @@ VDBRepository::merge(const MergeParams & m)
post_merge_command();
_imp->names_cache->add(m[k::package_id()]->name());
+
+ if (_imp->used_provides_cache || (! _imp->tried_provides_cache && load_provided_using_cache()))
+ {
+ provides_from_package_id(*m[k::package_id()]);
+ write_provides_cache();
+ _imp->provides.reset();
+ }
}
void
diff --git a/paludis/repositories/e/vdb_repository.hh b/paludis/repositories/e/vdb_repository.hh
index 795f67e..95fa4a3 100644
--- a/paludis/repositories/e/vdb_repository.hh
+++ b/paludis/repositories/e/vdb_repository.hh
@@ -60,8 +60,10 @@ namespace paludis
void _add_metadata_keys() const;
bool load_provided_using_cache() const;
+ void provides_from_package_id(const PackageID &) const;
void load_provided_the_slow_way() const;
+ void write_provides_cache() const;
void regenerate_provides_cache() const;
void need_category_names() const;
diff --git a/paludis/repositories/e/vdb_repository_TEST.cc b/paludis/repositories/e/vdb_repository_TEST.cc
index aefc24d..6da5e79 100644
--- a/paludis/repositories/e/vdb_repository_TEST.cc
+++ b/paludis/repositories/e/vdb_repository_TEST.cc
@@ -776,6 +776,295 @@ namespace test_cases
std::ostreambuf_iterator<char>(ss));
return ss.str();
}
- } test_names_cache;
+ } test_names_cache_incremental;
+
+ struct ProvidesCacheTest : TestCase
+ {
+ FSEntry provides_cache;
+
+ ProvidesCacheTest() :
+ TestCase("provides cache"),
+ provides_cache("vdb_repository_TEST_dir/providestest/.cache/provides")
+ {
+ }
+
+ bool repeatable() const
+ {
+ return false;
+ }
+
+ void run()
+ {
+ TestEnvironment env;
+ env.set_paludis_command("/bin/false");
+ tr1::shared_ptr<Map<std::string, std::string> > keys(new Map<std::string, std::string>);
+ keys.reset(new Map<std::string, std::string>);
+ keys->insert("format", "vdb");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("provides_cache", stringify(provides_cache));
+ keys->insert("location", "vdb_repository_TEST_dir/providestest");
+ keys->insert("builddir", stringify(FSEntry::cwd() / "vdb_repository_TEST_dir" / "build"));
+ keys->insert("root", stringify(FSEntry("vdb_repository_TEST_dir/root").realpath()));
+ tr1::shared_ptr<Repository> vdb_repo(VDBRepository::make_vdb_repository(&env, keys));
+ env.package_database()->add_repository(0, vdb_repo);
+
+ TEST_CHECK(! provides_cache.exists());
+
+ {
+ tr1::shared_ptr<const RepositoryProvidesInterface::ProvidesSequence> seq((*vdb_repo)[k::provides_interface()]->provided_packages());
+ TEST_CHECK_EQUAL(std::distance(seq->begin(), seq->end()), 5U);
+
+ RepositoryProvidesInterface::ProvidesSequence::ConstIterator it(seq->begin());
+ TEST_CHECK_STRINGIFY_EQUAL((*it)[k::virtual_name()], "virtual/foo");
+ TEST_CHECK_STRINGIFY_EQUAL(*(*it++)[k::provided_by()], "cat1/pkg1-1::installed");
+ TEST_CHECK_STRINGIFY_EQUAL((*it)[k::virtual_name()], "virtual/foo");
+ TEST_CHECK_STRINGIFY_EQUAL(*(*it++)[k::provided_by()], "cat1/pkg1-2::installed");
+ TEST_CHECK_STRINGIFY_EQUAL((*it)[k::virtual_name()], "virtual/foo");
+ TEST_CHECK_STRINGIFY_EQUAL(*(*it++)[k::provided_by()], "cat1/pkg2-1::installed");
+ TEST_CHECK_STRINGIFY_EQUAL((*it)[k::virtual_name()], "virtual/bar");
+ TEST_CHECK_STRINGIFY_EQUAL(*(*it++)[k::provided_by()], "cat1/pkg2-1::installed");
+ TEST_CHECK_STRINGIFY_EQUAL((*it)[k::virtual_name()], "virtual/bar");
+ TEST_CHECK_STRINGIFY_EQUAL(*(*it++)[k::provided_by()], "cat1/pkg2-2::installed");
+ }
+
+ vdb_repo->regenerate_cache();
+ TEST_CHECK_EQUAL(read_file(provides_cache), "paludis-3\ninstalled\ncat1/pkg1 1 virtual/foo\ncat1/pkg1 2 virtual/foo\ncat1/pkg2 1 virtual/foo virtual/bar\ncat1/pkg2 2 virtual/bar\n");
+ vdb_repo->invalidate();
+
+ {
+ tr1::shared_ptr<const RepositoryProvidesInterface::ProvidesSequence> seq((*vdb_repo)[k::provides_interface()]->provided_packages());
+ TEST_CHECK_EQUAL(std::distance(seq->begin(), seq->end()), 5U);
+
+ RepositoryProvidesInterface::ProvidesSequence::ConstIterator it(seq->begin());
+ TEST_CHECK_STRINGIFY_EQUAL((*it)[k::virtual_name()], "virtual/foo");
+ TEST_CHECK_STRINGIFY_EQUAL(*(*it++)[k::provided_by()], "cat1/pkg1-1::installed");
+ TEST_CHECK_STRINGIFY_EQUAL((*it)[k::virtual_name()], "virtual/foo");
+ TEST_CHECK_STRINGIFY_EQUAL(*(*it++)[k::provided_by()], "cat1/pkg1-2::installed");
+ TEST_CHECK_STRINGIFY_EQUAL((*it)[k::virtual_name()], "virtual/foo");
+ TEST_CHECK_STRINGIFY_EQUAL(*(*it++)[k::provided_by()], "cat1/pkg2-1::installed");
+ TEST_CHECK_STRINGIFY_EQUAL((*it)[k::virtual_name()], "virtual/bar");
+ TEST_CHECK_STRINGIFY_EQUAL(*(*it++)[k::provided_by()], "cat1/pkg2-1::installed");
+ TEST_CHECK_STRINGIFY_EQUAL((*it)[k::virtual_name()], "virtual/bar");
+ TEST_CHECK_STRINGIFY_EQUAL(*(*it++)[k::provided_by()], "cat1/pkg2-2::installed");
+ }
+ }
+
+ std::string read_file(const FSEntry & f)
+ {
+ std::ifstream s(stringify(f).c_str());
+ std::stringstream ss;
+ std::copy(std::istreambuf_iterator<char>(s), std::istreambuf_iterator<char>(),
+ std::ostreambuf_iterator<char>(ss));
+ return ss.str();
+ }
+ } test_provides_cache;
+
+ struct ProvidesCacheIncrementalTest : TestCase
+ {
+ FSEntry provides_cache;
+
+ ProvidesCacheIncrementalTest() :
+ TestCase("provides cache incremental"),
+ provides_cache("vdb_repository_TEST_dir/providesincrtest/.cache/provides")
+ {
+ }
+
+ bool repeatable() const
+ {
+ return false;
+ }
+
+ unsigned max_run_time() const
+ {
+ return 3000;
+ }
+
+ void run()
+ {
+ TestEnvironment env;
+ env.set_paludis_command("/bin/false");
+ tr1::shared_ptr<Map<std::string, std::string> > keys(new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "vdb_repository_TEST_dir/providesincrtest_src1");
+ keys->insert("profiles", "vdb_repository_TEST_dir/providesincrtest_src1/profiles/profile");
+ keys->insert("layout", "traditional");
+ keys->insert("eapi_when_unknown", "0");
+ keys->insert("eapi_when_unspecified", "0");
+ keys->insert("profile_eapi", "0");
+ keys->insert("distdir", stringify(FSEntry::cwd() / "vdb_repository_TEST_dir" / "distdir"));
+ keys->insert("builddir", stringify(FSEntry::cwd() / "vdb_repository_TEST_dir" / "build"));
+ keys->insert("root", stringify(FSEntry("vdb_repository_TEST_dir/root").realpath()));
+ tr1::shared_ptr<ERepository> repo1(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo1);
+
+ keys.reset(new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "vdb_repository_TEST_dir/providesincrtest_src2");
+ keys->insert("profiles", "vdb_repository_TEST_dir/providesincrtest_src1/profiles/profile");
+ keys->insert("layout", "traditional");
+ keys->insert("eapi_when_unknown", "0");
+ keys->insert("eapi_when_unspecified", "0");
+ keys->insert("profile_eapi", "0");
+ keys->insert("distdir", stringify(FSEntry::cwd() / "vdb_repository_TEST_dir" / "distdir"));
+ keys->insert("builddir", stringify(FSEntry::cwd() / "vdb_repository_TEST_dir" / "build"));
+ keys->insert("root", stringify(FSEntry("vdb_repository_TEST_dir/root").realpath()));
+ tr1::shared_ptr<ERepository> repo2(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(2, repo2);
+
+ keys.reset(new Map<std::string, std::string>);
+ keys->insert("format", "vdb");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("provides_cache", stringify(provides_cache));
+ keys->insert("location", "vdb_repository_TEST_dir/providesincrtest");
+ keys->insert("builddir", stringify(FSEntry::cwd() / "vdb_repository_TEST_dir" / "build"));
+ keys->insert("root", stringify(FSEntry("vdb_repository_TEST_dir/root").realpath()));
+ tr1::shared_ptr<Repository> vdb_repo(VDBRepository::make_vdb_repository(&env, keys));
+ env.package_database()->add_repository(0, vdb_repo);
+
+ InstallAction install_action(InstallActionOptions::named_create()
+ (k::debug_build(), iado_none)
+ (k::checks(), iaco_default)
+ (k::no_config_protect(), false)
+ (k::destination(), vdb_repo)
+ );
+
+ UninstallAction uninstall_action(UninstallActionOptions::named_create()
+ (k::no_config_protect(), false)
+ );
+
+ TEST_CHECK_EQUAL(read_file(provides_cache), "paludis-3\ninstalled\n");
+
+ {
+ TestMessageSuffix suffix("install", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec(parse_user_package_dep_spec("=cat1/pkg1-1::providesincrtest_src1",
+ UserPackageDepSpecOptions()))), qo_require_exactly_one)->last());
+ id->perform_action(install_action);
+ vdb_repo->invalidate();
+
+ TEST_CHECK_EQUAL(read_file(provides_cache), "paludis-3\ninstalled\ncat1/pkg1 1 virtual/foo\n");
+ }
+
+ {
+ TestMessageSuffix suffix("reinstall", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec(parse_user_package_dep_spec("=cat1/pkg1-1::providesincrtest_src1",
+ UserPackageDepSpecOptions()))), qo_require_exactly_one)->last());
+ id->perform_action(install_action);
+ vdb_repo->invalidate();
+
+ TEST_CHECK_EQUAL(read_file(provides_cache), "paludis-3\ninstalled\ncat1/pkg1 1 virtual/foo\n");
+ }
+
+ {
+ TestMessageSuffix suffix("upgrade", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec(parse_user_package_dep_spec("=cat1/pkg1-1.1::providesincrtest_src1",
+ UserPackageDepSpecOptions()))), qo_require_exactly_one)->last());
+ const tr1::shared_ptr<const PackageID> inst_id(*env.package_database()->query(query::Matches(
+ PackageDepSpec(parse_user_package_dep_spec("=cat1/pkg1-1::installed",
+ UserPackageDepSpecOptions()))), qo_require_exactly_one)->last());
+ id->perform_action(install_action);
+ vdb_repo->invalidate();
+ inst_id->perform_action(uninstall_action);
+ vdb_repo->invalidate();
+
+ TEST_CHECK_EQUAL(read_file(provides_cache), "paludis-3\ninstalled\ncat1/pkg1 1.1 virtual/foo\n");
+ }
+
+ {
+ TestMessageSuffix suffix("downgrade", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec(parse_user_package_dep_spec("=cat1/pkg1-1::providesincrtest_src1",
+ UserPackageDepSpecOptions()))), qo_require_exactly_one)->last());
+ const tr1::shared_ptr<const PackageID> inst_id(*env.package_database()->query(query::Matches(
+ PackageDepSpec(parse_user_package_dep_spec("=cat1/pkg1-1.1::installed",
+ UserPackageDepSpecOptions()))), qo_require_exactly_one)->last());
+ id->perform_action(install_action);
+ vdb_repo->invalidate();
+ inst_id->perform_action(uninstall_action);
+ vdb_repo->invalidate();
+
+ TEST_CHECK_EQUAL(read_file(provides_cache), "paludis-3\ninstalled\ncat1/pkg1 1 virtual/foo\n");
+ }
+
+ {
+ TestMessageSuffix suffix("reinstall different PROVIDE", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec(parse_user_package_dep_spec("=cat1/pkg1-1::providesincrtest_src2",
+ UserPackageDepSpecOptions()))), qo_require_exactly_one)->last());
+ id->perform_action(install_action);
+ vdb_repo->invalidate();
+
+ TEST_CHECK_EQUAL(read_file(provides_cache), "paludis-3\ninstalled\ncat1/pkg1 1 virtual/bar\n");
+ }
+
+ {
+ TestMessageSuffix suffix("new slot", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec(parse_user_package_dep_spec("=cat1/pkg1-2::providesincrtest_src1",
+ UserPackageDepSpecOptions()))), qo_require_exactly_one)->last());
+ id->perform_action(install_action);
+ vdb_repo->invalidate();
+
+ TEST_CHECK_EQUAL(read_file(provides_cache), "paludis-3\ninstalled\ncat1/pkg1 1 virtual/bar\ncat1/pkg1 2 virtual/foo\n");
+ }
+
+ {
+ TestMessageSuffix suffix("remove other slot", true);
+ const tr1::shared_ptr<const PackageID> inst_id(*env.package_database()->query(query::Matches(
+ PackageDepSpec(parse_user_package_dep_spec("=cat1/pkg1-2::installed",
+ UserPackageDepSpecOptions()))), qo_require_exactly_one)->last());
+ inst_id->perform_action(uninstall_action);
+ vdb_repo->invalidate();
+
+ TEST_CHECK_EQUAL(read_file(provides_cache), "paludis-3\ninstalled\ncat1/pkg1 1 virtual/bar\n");
+ }
+
+ {
+ TestMessageSuffix suffix("new package", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec(parse_user_package_dep_spec("=cat1/pkg2-1::providesincrtest_src1",
+ UserPackageDepSpecOptions()))), qo_require_exactly_one)->last());
+ id->perform_action(install_action);
+ vdb_repo->invalidate();
+
+ TEST_CHECK_EQUAL(read_file(provides_cache), "paludis-3\ninstalled\ncat1/pkg1 1 virtual/bar\ncat1/pkg2 1 virtual/foo\n");
+ }
+
+ {
+ TestMessageSuffix suffix("remove other package", true);
+ const tr1::shared_ptr<const PackageID> inst_id(*env.package_database()->query(query::Matches(
+ PackageDepSpec(parse_user_package_dep_spec("=cat1/pkg2-1::installed",
+ UserPackageDepSpecOptions()))), qo_require_exactly_one)->last());
+ inst_id->perform_action(uninstall_action);
+ vdb_repo->invalidate();
+
+ TEST_CHECK_EQUAL(read_file(provides_cache), "paludis-3\ninstalled\ncat1/pkg1 1 virtual/bar\n");
+ }
+
+ {
+ TestMessageSuffix suffix("uninstall", true);
+ const tr1::shared_ptr<const PackageID> inst_id(*env.package_database()->query(query::Matches(
+ PackageDepSpec(parse_user_package_dep_spec("=cat1/pkg1-1::installed",
+ UserPackageDepSpecOptions()))), qo_require_exactly_one)->last());
+ inst_id->perform_action(uninstall_action);
+ vdb_repo->invalidate();
+
+ TEST_CHECK_EQUAL(read_file(provides_cache), "paludis-3\ninstalled\n");
+ }
+ }
+
+ std::string read_file(const FSEntry & f)
+ {
+ std::ifstream s(stringify(f).c_str());
+ std::stringstream ss;
+ std::copy(std::istreambuf_iterator<char>(s), std::istreambuf_iterator<char>(),
+ std::ostreambuf_iterator<char>(ss));
+ return ss.str();
+ }
+ } test_provides_cache_incremental;
}
diff --git a/paludis/repositories/e/vdb_repository_TEST_setup.sh b/paludis/repositories/e/vdb_repository_TEST_setup.sh
index 9a87a86..cce58ec 100755
--- a/paludis/repositories/e/vdb_repository_TEST_setup.sh
+++ b/paludis/repositories/e/vdb_repository_TEST_setup.sh
@@ -378,3 +378,54 @@ cp namesincrtest_src/cat1/pkg1/pkg1-{1,2}.ebuild
cp namesincrtest_src/cat1/{pkg1/pkg1,pkg2/pkg2}-1.ebuild
cp namesincrtest_src/{cat1,cat2}/pkg1/pkg1-1.ebuild
+mkdir -p providestest/{.cache,cat1/{pkg1,pkg2,pkg3}-{1,2}} || exit 1
+for f in providestest/cat1/{pkg1,pkg2,pkg3}-{1,2}/EAPI; do
+ echo 0 >${f}
+done
+for f in providestest/cat1/{pkg1,pkg2,pkg3}-1/SLOT; do
+ echo 1 >${f}
+done
+for f in providestest/cat1/{pkg1,pkg2,pkg3}-2/SLOT; do
+ echo 2 >${f}
+done
+for f in providestest/cat1/{pkg1,pkg2,pkg3}-{1,2}/USE; do
+ echo enabled >${f}
+done
+
+echo ' virtual/foo' >providestest/cat1/pkg1-1/PROVIDE
+echo 'enabled? ( virtual/foo )' >providestest/cat1/pkg1-2/PROVIDE
+echo 'enabled? ( virtual/foo ) virtual/bar' >providestest/cat1/pkg2-1/PROVIDE
+echo 'disabled? ( virtual/foo ) virtual/bar' >providestest/cat1/pkg2-2/PROVIDE
+echo 'disabled? ( virtual/foo )' >providestest/cat1/pkg3-1/PROVIDE
+echo '' >providestest/cat1/pkg3-2/PROVIDE
+
+mkdir -p providesincrtest/.cache providesincrtest_src{1,2}/{eclass,profiles/profile,cat1/{pkg1,pkg2}} || exit 1
+echo paludis-3 >providesincrtest/.cache/provides
+echo installed >>providesincrtest/.cache/provides
+
+cat <<END > providesincrtest_src1/profiles/profile/make.defaults
+ARCH=test
+USERLAND="GNU"
+KERNEL="linux"
+CHOST="i286-badger-linux-gnu"
+END
+echo providesincrtest_src1 >providesincrtest_src1/profiles/repo_name
+echo providesincrtest_src2 >providesincrtest_src2/profiles/repo_name
+echo cat1 >providesincrtest_src1/profiles/categories
+echo cat1 >providesincrtest_src2/profiles/categories
+
+cat <<END >providesincrtest_src1/cat1/pkg1/pkg1-1.ebuild
+KEYWORDS="test"
+SLOT="${PV:0:1}"
+PROVIDE="enabled? ( virtual/foo ) disabled? ( virtual/bar )"
+END
+cp providesincrtest_src1/cat1/pkg1/pkg1-{1,1.1}.ebuild
+cp providesincrtest_src1/cat1/pkg1/pkg1-{1,2}.ebuild
+cp providesincrtest_src1/cat1/{pkg1/pkg1,pkg2/pkg2}-1.ebuild
+
+cat <<END >providesincrtest_src2/cat1/pkg1/pkg1-1.ebuild
+KEYWORDS="test"
+SLOT="${PV:0:1}"
+PROVIDE="enabled? ( virtual/bar ) disabled? ( virtual/foo )"
+END
+