aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar David Leverton <levertond@googlemail.com> 2008-08-12 19:25:21 +0100
committerAvatar David Leverton <levertond@googlemail.com> 2008-08-16 21:43:31 +0100
commit767fb3805f9629ebc36888a35023eda943089819 (patch)
tree99f37ccbbd138ea72ea435b4005b57e5aa9698db
parent9035495cebefab9829c69d8abea3caf0e8b6ff2b (diff)
downloadpaludis-767fb3805f9629ebc36888a35023eda943089819.tar.gz
paludis-767fb3805f9629ebc36888a35023eda943089819.tar.xz
Support for Portage's flat_hash cache format. Fixes: ticket:630
Use flat_hash for the write_cache, and drop flat_list support for non-Gentoo EAPIs.
-rw-r--r--paludis/repositories/e/eapi.cc4
-rw-r--r--paludis/repositories/e/eapi.hh8
-rw-r--r--paludis/repositories/e/eapis/0.conf46
-rw-r--r--paludis/repositories/e/eapis/exheres-0.conf46
-rw-r--r--paludis/repositories/e/eapis/kdebuild-1.conf3
-rw-r--r--paludis/repositories/e/eapis/paludis-1.conf48
-rw-r--r--paludis/repositories/e/eapis/pbin-1+0.conf3
-rw-r--r--paludis/repositories/e/eapis/pbin-1+1.conf3
-rw-r--r--paludis/repositories/e/eapis/pbin-1+exheres-0.conf2
-rw-r--r--paludis/repositories/e/eapis/pbin-1+paludis-1.conf3
-rw-r--r--paludis/repositories/e/ebuild_entries.cc2
-rw-r--r--paludis/repositories/e/ebuild_flat_metadata_cache.cc890
-rw-r--r--paludis/repositories/e/ebuild_flat_metadata_cache.hh21
-rw-r--r--paludis/repositories/e/eclass_mtimes.cc79
-rw-r--r--paludis/repositories/e/eclass_mtimes.hh16
15 files changed, 751 insertions, 423 deletions
diff --git a/paludis/repositories/e/eapi.cc b/paludis/repositories/e/eapi.cc
index 44103df..b77af58 100644
--- a/paludis/repositories/e/eapi.cc
+++ b/paludis/repositories/e/eapi.cc
@@ -88,7 +88,7 @@ namespace
{
return make_named_values<EAPIMetadataVariable>(
value_for<n::description>(check_get(k, "description_" + s)),
- value_for<n::flat_cache_index>(destringify_key<int>(k, "flat_cache_" + s)),
+ value_for<n::flat_list_index>(destringify_key<int>(k, "flat_list_" + s)),
value_for<n::name>(check_get(k, "metadata_" + s))
);
}
@@ -106,7 +106,7 @@ namespace
value_for<n::keywords>(make_metadata_variable(k, "keywords")),
value_for<n::license>(make_metadata_variable(k, "license")),
value_for<n::long_description>(make_metadata_variable(k, "long_description")),
- value_for<n::minimum_flat_cache_size>(destringify_key<int>(k, "flat_cache_minimum_size")),
+ value_for<n::minimum_flat_list_size>(destringify_key<int>(k, "flat_list_minimum_size")),
value_for<n::pdepend>(make_metadata_variable(k, "pdepend")),
value_for<n::provide>(make_metadata_variable(k, "provide")),
value_for<n::remote_ids>(make_metadata_variable(k, "remote_ids")),
diff --git a/paludis/repositories/e/eapi.hh b/paludis/repositories/e/eapi.hh
index e40382b..e26d444 100644
--- a/paludis/repositories/e/eapi.hh
+++ b/paludis/repositories/e/eapi.hh
@@ -82,7 +82,7 @@ namespace paludis
struct exported_name;
struct f_function_prefix;
struct failure_is_fatal;
- struct flat_cache_index;
+ struct flat_list_index;
struct homepage;
struct ignore_pivot_env_functions;
struct ignore_pivot_env_variables;
@@ -95,7 +95,7 @@ namespace paludis
struct long_description;
struct merger_options;
struct metadata_key;
- struct minimum_flat_cache_size;
+ struct minimum_flat_list_size;
struct must_not_change_variables;
struct name;
struct no_slot_or_repo;
@@ -237,7 +237,7 @@ namespace paludis
struct EAPIMetadataVariable
{
NamedValue<n::description, std::string> description;
- NamedValue<n::flat_cache_index, int> flat_cache_index;
+ NamedValue<n::flat_list_index, int> flat_list_index;
NamedValue<n::name, std::string> name;
};
@@ -253,7 +253,7 @@ namespace paludis
NamedValue<n::keywords, EAPIMetadataVariable> keywords;
NamedValue<n::license, EAPIMetadataVariable> license;
NamedValue<n::long_description, EAPIMetadataVariable> long_description;
- NamedValue<n::minimum_flat_cache_size, int> minimum_flat_cache_size;
+ NamedValue<n::minimum_flat_list_size, int> minimum_flat_list_size;
NamedValue<n::pdepend, EAPIMetadataVariable> pdepend;
NamedValue<n::provide, EAPIMetadataVariable> provide;
NamedValue<n::remote_ids, EAPIMetadataVariable> remote_ids;
diff --git a/paludis/repositories/e/eapis/0.conf b/paludis/repositories/e/eapis/0.conf
index 97d3898..0440cc4 100644
--- a/paludis/repositories/e/eapis/0.conf
+++ b/paludis/repositories/e/eapis/0.conf
@@ -174,29 +174,29 @@ metadata_src_uri = SRC_URI
metadata_use =
metadata_dependencies =
-flat_cache_minimum_size = 15
-flat_cache_build_depend = 0
-flat_cache_short_description = 7
-flat_cache_long_description = -1
-flat_cache_eapi = 14
-flat_cache_dependencies = -1
-flat_cache_homepage = 5
-flat_cache_inherited = 9
-flat_cache_iuse = 10
-flat_cache_keywords = 8
-flat_cache_license = 6
-flat_cache_pdepend = 12
-flat_cache_provide = 13
-flat_cache_restrict = 4
-flat_cache_run_depend = 1
-flat_cache_slot = 2
-flat_cache_src_uri = 3
-flat_cache_use = -1
-flat_cache_bugs_to = -1
-flat_cache_remote_ids = -1
-flat_cache_upstream_changelog = -1
-flat_cache_upstream_release_notes = -1
-flat_cache_upstream_documentation = -1
+flat_list_minimum_size = 15
+flat_list_build_depend = 0
+flat_list_short_description = 7
+flat_list_long_description = -1
+flat_list_eapi = 14
+flat_list_dependencies = -1
+flat_list_homepage = 5
+flat_list_inherited = 9
+flat_list_iuse = 10
+flat_list_keywords = 8
+flat_list_license = 6
+flat_list_pdepend = 12
+flat_list_provide = 13
+flat_list_restrict = 4
+flat_list_run_depend = 1
+flat_list_slot = 2
+flat_list_src_uri = 3
+flat_list_use = -1
+flat_list_bugs_to = -1
+flat_list_remote_ids = -1
+flat_list_upstream_changelog = -1
+flat_list_upstream_release_notes = -1
+flat_list_upstream_documentation = -1
env_use = USE
env_use_expand = USE_EXPAND
diff --git a/paludis/repositories/e/eapis/exheres-0.conf b/paludis/repositories/e/eapis/exheres-0.conf
index cc2feca..d3639bb 100644
--- a/paludis/repositories/e/eapis/exheres-0.conf
+++ b/paludis/repositories/e/eapis/exheres-0.conf
@@ -193,29 +193,29 @@ description_upstream_changelog = Upstream changelog
description_upstream_release_notes = Upstream release notes
description_upstream_documentation = Upstream documentation
-flat_cache_minimum_size = 18
-flat_cache_build_depend = -1
-flat_cache_short_description = 7
-flat_cache_long_description = 11
-flat_cache_eapi = 14
-flat_cache_dependencies = 1
-flat_cache_homepage = 5
-flat_cache_inherited = 9
-flat_cache_iuse = 10
-flat_cache_keywords = 8
-flat_cache_license = 6
-flat_cache_pdepend = -1
-flat_cache_provide = -1
-flat_cache_restrict = 4
-flat_cache_run_depend = -1
-flat_cache_slot = 2
-flat_cache_src_uri = 3
-flat_cache_use = -1
-flat_cache_bugs_to = 12
-flat_cache_remote_ids = 13
-flat_cache_upstream_changelog = 15
-flat_cache_upstream_release_notes = 16
-flat_cache_upstream_documentation = 17
+flat_list_minimum_size = -1
+flat_list_build_depend = -1
+flat_list_short_description = -1
+flat_list_long_description = -1
+flat_list_eapi = -1
+flat_list_dependencies = -1
+flat_list_homepage = -1
+flat_list_inherited = -1
+flat_list_iuse = -1
+flat_list_keywords = -1
+flat_list_license = -1
+flat_list_pdepend = -1
+flat_list_provide = -1
+flat_list_restrict = -1
+flat_list_run_depend = -1
+flat_list_slot = -1
+flat_list_src_uri = -1
+flat_list_use = -1
+flat_list_bugs_to = -1
+flat_list_remote_ids = -1
+flat_list_upstream_changelog = -1
+flat_list_upstream_release_notes = -1
+flat_list_upstream_documentation = -1
env_use = OPTIONS
env_use_expand = SUBOPTIONS
diff --git a/paludis/repositories/e/eapis/kdebuild-1.conf b/paludis/repositories/e/eapis/kdebuild-1.conf
index f191379..fe4d0fe 100644
--- a/paludis/repositories/e/eapis/kdebuild-1.conf
+++ b/paludis/repositories/e/eapis/kdebuild-1.conf
@@ -20,7 +20,8 @@ ebuild_must_not_set_variables = ${ebuild_must_not_set_variables} PROVIDE
must_not_change_variables = ${must_not_change_variables} EAPI
description_provide =
metadata_provide =
-flat_cache_provide = -1
+
+flat_list_minimum_size = -1
ebuild_install = \
: killold ; \
diff --git a/paludis/repositories/e/eapis/paludis-1.conf b/paludis/repositories/e/eapis/paludis-1.conf
index 799d2bc..28a6099 100644
--- a/paludis/repositories/e/eapis/paludis-1.conf
+++ b/paludis/repositories/e/eapis/paludis-1.conf
@@ -179,30 +179,30 @@ description_src_uri = Source URI
description_use = Selected USE flags
description_dependencies =
-flat_cache_minimum_size = 15
-flat_cache_build_depend = 0
-flat_cache_short_description = 7
-flat_cache_long_description = -1
-flat_cache_eapi = 14
-flat_cache_dependencies = -1
-flat_cache_homepage = 5
-flat_cache_inherited = 9
-flat_cache_iuse = 10
-flat_cache_keywords = 8
-flat_cache_license = 6
-flat_cache_pdepend = 12
-flat_cache_provide = 13
-flat_cache_restrict = 4
-flat_cache_run_depend = 1
-flat_cache_slot = 2
-flat_cache_src_uri = 3
-flat_cache_use = -1
-flat_cache_use = -1
-flat_cache_bugs_to = -1
-flat_cache_remote_ids = -1
-flat_cache_upstream_changelog = -1
-flat_cache_upstream_release_notes = -1
-flat_cache_upstream_documentation = -1
+flat_list_minimum_size = -1
+flat_list_build_depend = -1
+flat_list_short_description = -1
+flat_list_long_description = -1
+flat_list_eapi = -1
+flat_list_dependencies = -1
+flat_list_homepage = -1
+flat_list_inherited = -1
+flat_list_iuse = -1
+flat_list_keywords = -1
+flat_list_license = -1
+flat_list_pdepend = -1
+flat_list_provide = -1
+flat_list_restrict = -1
+flat_list_run_depend = -1
+flat_list_slot = -1
+flat_list_src_uri = -1
+flat_list_use = -1
+flat_list_use = -1
+flat_list_bugs_to = -1
+flat_list_remote_ids = -1
+flat_list_upstream_changelog = -1
+flat_list_upstream_release_notes = -1
+flat_list_upstream_documentation = -1
env_use = USE
env_use_expand = USE_EXPAND
diff --git a/paludis/repositories/e/eapis/pbin-1+0.conf b/paludis/repositories/e/eapis/pbin-1+0.conf
index accc132..fa035b6 100644
--- a/paludis/repositories/e/eapis/pbin-1+0.conf
+++ b/paludis/repositories/e/eapis/pbin-1+0.conf
@@ -36,6 +36,5 @@ metadata_keywords = BINARY_KEYWORDS
metadata_src_uri = BINARY_URI
metadata_use = USE
-flat_cache_minimum_size = 16
-flat_cache_use = 15
+flat_list_minimum_size = -1
diff --git a/paludis/repositories/e/eapis/pbin-1+1.conf b/paludis/repositories/e/eapis/pbin-1+1.conf
index 9864980..529a6e7 100644
--- a/paludis/repositories/e/eapis/pbin-1+1.conf
+++ b/paludis/repositories/e/eapis/pbin-1+1.conf
@@ -36,6 +36,5 @@ metadata_keywords = BINARY_KEYWORDS
metadata_src_uri = BINARY_URI
metadata_use = USE
-flat_cache_minimum_size = 16
-flat_cache_use = 15
+flat_list_minimum_size = -1
diff --git a/paludis/repositories/e/eapis/pbin-1+exheres-0.conf b/paludis/repositories/e/eapis/pbin-1+exheres-0.conf
index 60e0616..99272bb 100644
--- a/paludis/repositories/e/eapis/pbin-1+exheres-0.conf
+++ b/paludis/repositories/e/eapis/pbin-1+exheres-0.conf
@@ -36,5 +36,5 @@ metadata_keywords = BINARY_PLATFORMS
metadata_src_uri = BINARY_URI
metadata_use = OPTIONS
-flat_cache_use = 12
+flat_list_minimum_size = -1
diff --git a/paludis/repositories/e/eapis/pbin-1+paludis-1.conf b/paludis/repositories/e/eapis/pbin-1+paludis-1.conf
index 8b7335f..7e87c47 100644
--- a/paludis/repositories/e/eapis/pbin-1+paludis-1.conf
+++ b/paludis/repositories/e/eapis/pbin-1+paludis-1.conf
@@ -36,6 +36,5 @@ metadata_keywords = BINARY_KEYWORDS
metadata_src_uri = BINARY_URI
metadata_use = USE
-flat_cache_minimum_size = 16
-flat_cache_use = 15
+flat_list_minimum_size = -1
diff --git a/paludis/repositories/e/ebuild_entries.cc b/paludis/repositories/e/ebuild_entries.cc
index e8f9db6..82616f4 100644
--- a/paludis/repositories/e/ebuild_entries.cc
+++ b/paludis/repositories/e/ebuild_entries.cc
@@ -124,7 +124,7 @@ namespace paludis
environment(e),
e_repository(p),
params(k),
- eclass_mtimes(new EclassMtimes(k.eclassdirs)),
+ eclass_mtimes(new EclassMtimes(p, k.eclassdirs)),
master_mtime(0)
{
FSEntry m(k.location / "metadata" / "timestamp");
diff --git a/paludis/repositories/e/ebuild_flat_metadata_cache.cc b/paludis/repositories/e/ebuild_flat_metadata_cache.cc
index 0ad3366..4d570ed 100644
--- a/paludis/repositories/e/ebuild_flat_metadata_cache.cc
+++ b/paludis/repositories/e/ebuild_flat_metadata_cache.cc
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2008 David Leverton
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -23,6 +24,7 @@
#include <paludis/util/join.hh>
#include <paludis/util/visitor-impl.hh>
#include <paludis/util/set.hh>
+#include <paludis/util/destringify.hh>
#include <paludis/repositories/e/dep_spec_pretty_printer.hh>
#include <paludis/repositories/e/dep_parser.hh>
#include <paludis/repositories/e/dependencies_rewriter.hh>
@@ -31,6 +33,7 @@
#include <tr1/functional>
#include <fstream>
#include <set>
+#include <map>
#include <list>
#include <vector>
#include <functional>
@@ -41,14 +44,230 @@
using namespace paludis;
using namespace paludis::erepository;
+namespace paludis
+{
+ template <>
+ struct Implementation<EbuildFlatMetadataCache>
+ {
+ const Environment * const env;
+ const FSEntry & filename;
+ const FSEntry & ebuild;
+ time_t master_mtime;
+ std::tr1::shared_ptr<const EclassMtimes> eclass_mtimes;
+ bool silent;
+
+ Implementation(const Environment * const e, const FSEntry & f, const FSEntry & eb,
+ time_t m, const std::tr1::shared_ptr<const EclassMtimes> em, bool s) :
+ env(e),
+ filename(f),
+ ebuild(eb),
+ master_mtime(m),
+ eclass_mtimes(em),
+ silent(s)
+ {
+ }
+ };
+}
+
+namespace
+{
+ bool load_flat_list(
+ const std::tr1::shared_ptr<const EbuildID> & id, const std::vector<std::string> & lines, Implementation<EbuildFlatMetadataCache> * _imp)
+ {
+ Context ctx("When loading flat_list format cache file:");
+
+ if (lines.size() < 15)
+ {
+ Log::get_instance()->message("e.cache.flat_list.truncated", ll_warning, lc_no_context)
+ << "cache file has " << lines.size() << " lines, but expected at least 15";
+ return false;
+ }
+
+ id->set_eapi(lines[14]);
+
+ if (id->eapi()->supported())
+ {
+ const EAPIEbuildMetadataVariables & m(*id->eapi()->supported()->ebuild_metadata_variables());
+ if (-1 == m.minimum_flat_list_size())
+ {
+ Log::get_instance()->message("e.cache.flat_list.unsupported", ll_warning, lc_context)
+ << "flat_list cache is not supported for EAPI '" << id->eapi()->name() << "'";
+ return false;
+ }
+
+ if (static_cast<int>(lines.size()) < m.minimum_flat_list_size())
+ {
+ Log::get_instance()->message("e.cache.flat_list.truncated", ll_warning, lc_context)
+ << "cache file has " << lines.size() << " lines, but expected at least " << m.minimum_flat_list_size();
+ return false;
+ }
+
+ {
+ time_t cache_time(std::max(_imp->master_mtime, _imp->filename.mtime()));
+ bool ok(_imp->ebuild.mtime() <= cache_time);
+ if (! ok)
+ Log::get_instance()->message("e.cache.flat_list.mtime", ll_debug, lc_context)
+ << "ebuild has mtime " << _imp->ebuild.mtime() << ", but expected at most " << cache_time;
+
+ if (ok)
+ {
+ std::set<std::string> tokens;
+ tokenise_whitespace(lines[m.inherited().flat_list_index()], std::inserter(tokens, tokens.begin()));
+ FSEntry eclassdir(id->repository()->location_key()->value() / "eclass");
+ for (std::set<std::string>::const_iterator it(tokens.begin()),
+ it_end(tokens.end()); it_end != it; ++it)
+ {
+ const FSEntry * eclass(_imp->eclass_mtimes->eclass(*it));
+ if (! eclass)
+ {
+ Log::get_instance()->message("e.cache.flat_list.eclass.missing", ll_debug, lc_context)
+ << "Can't find cache-requested eclass '" << *it << "'";
+ ok = false;
+ }
+
+ else if (eclass->dirname() != eclassdir)
+ {
+ Log::get_instance()->message("e.cache.flat_list.eclass.wrong_location", ll_debug, lc_context)
+ << "Cache-requested eclass '" << *it << "' was found at '"
+ << eclass->dirname() << "', but expected '" << eclassdir << "'";
+ ok = false;
+ }
+
+ else if (eclass->mtime() > cache_time)
+ {
+ Log::get_instance()->message("e.cache.flat_list.eclass.wrong_mtime", ll_debug, lc_context)
+ << "Cache-requested eclass '" << *it << "' has mtime "
+ << eclass->mtime() << ", but expected at most " << cache_time;
+ ok = false;
+ }
+
+ if (! ok)
+ break;
+ }
+ }
+
+ if (! ok)
+ {
+ Log::get_instance()->message("e.cache.stale", ll_warning, lc_no_context)
+ << "Stale cache file at '" << _imp->filename << "'";
+ return false;
+ }
+ }
+
+ if (-1 != m.dependencies().flat_list_index() && ! m.dependencies().name().empty())
+ {
+ DependenciesRewriter rewriter;
+ parse_depend(lines.at(m.dependencies().flat_list_index()), _imp->env, id, *id->eapi())->accept(rewriter);
+ id->load_build_depend(m.dependencies().name() + ".DEPEND", m.dependencies().description() + " (build)", rewriter.depend());
+ id->load_run_depend(m.dependencies().name() + ".RDEPEND", m.dependencies().description() + " (run)", rewriter.rdepend());
+ id->load_post_depend(m.dependencies().name() + ".PDEPEND", m.dependencies().description() + " (post)", rewriter.pdepend());
+ }
+
+ if (-1 != m.build_depend().flat_list_index() && ! m.build_depend().name().empty())
+ id->load_build_depend(m.build_depend().name(), m.build_depend().description(), lines.at(m.build_depend().flat_list_index()));
+
+ if (-1 != m.run_depend().flat_list_index() && ! m.run_depend().name().empty())
+ id->load_run_depend(m.run_depend().name(), m.run_depend().description(), lines.at(m.run_depend().flat_list_index()));
+
+ id->set_slot(SlotName(lines.at(m.slot().flat_list_index())));
+
+ if (-1 != m.src_uri().flat_list_index() && ! m.src_uri().name().empty())
+ id->load_src_uri(m.src_uri().name(), m.src_uri().description(), lines.at(m.src_uri().flat_list_index()));
+
+ if (-1 != m.restrictions().flat_list_index() && ! m.restrictions().name().empty())
+ id->load_restrict(m.restrictions().name(), m.restrictions().description(), lines.at(m.restrictions().flat_list_index()));
+
+ if (-1 != m.homepage().flat_list_index() && ! m.homepage().name().empty())
+ id->load_homepage(m.homepage().name(), m.homepage().description(), lines.at(m.homepage().flat_list_index()));
+
+ if (-1 != m.license().flat_list_index() && ! m.license().name().empty())
+ id->load_license(m.license().name(), m.license().description(), lines.at(m.license().flat_list_index()));
+
+ if (-1 != m.short_description().flat_list_index() && ! m.short_description().name().empty())
+ id->load_short_description(m.short_description().name(),
+ m.short_description().description(),
+ lines.at(m.short_description().flat_list_index()));
+
+ if (-1 != m.long_description().flat_list_index() && ! m.long_description().name().empty())
+ {
+ std::string value(lines.at(m.long_description().flat_list_index()));
+ if (! value.empty())
+ id->load_long_description(m.long_description().name(),
+ m.long_description().description(), value);
+ }
+
+ if (-1 != m.keywords().flat_list_index() && ! m.keywords().name().empty())
+ id->load_keywords(m.keywords().name(), m.keywords().description(), lines.at(m.keywords().flat_list_index()));
+
+ if (-1 != m.inherited().flat_list_index() && ! m.inherited().name().empty())
+ id->load_inherited(m.inherited().name(), m.inherited().description(), lines.at(m.inherited().flat_list_index()));
+
+ if (-1 != m.iuse().flat_list_index() && ! m.iuse().name().empty())
+ id->load_iuse(m.iuse().name(), m.iuse().description(), lines.at(m.iuse().flat_list_index()));
+
+ if (-1 != m.pdepend().flat_list_index() && ! m.pdepend().name().empty())
+ id->load_post_depend(m.pdepend().name(), m.pdepend().description(), lines.at(m.pdepend().flat_list_index()));
+
+ if (-1 != m.provide().flat_list_index() && ! m.provide().name().empty())
+ id->load_provide(m.provide().name(), m.provide().description(), lines.at(m.provide().flat_list_index()));
+
+ if (-1 != m.use().flat_list_index() && ! m.use().name().empty())
+ id->load_use(m.use().name(), m.use().description(), lines.at(m.use().flat_list_index()));
+
+ if (-1 != m.upstream_changelog().flat_list_index() && ! m.upstream_changelog().name().empty())
+ {
+ std::string value(lines.at(m.upstream_changelog().flat_list_index()));
+ if (! value.empty())
+ id->load_upstream_changelog(m.upstream_changelog().name(),
+ m.upstream_changelog().description(), value);
+ }
+
+ if (-1 != m.upstream_documentation().flat_list_index() && ! m.upstream_documentation().name().empty())
+ {
+ std::string value(lines.at(m.upstream_documentation().flat_list_index()));
+ if (! value.empty())
+ id->load_upstream_documentation(m.upstream_documentation().name(),
+ m.upstream_documentation().description(), value);
+ }
+
+ if (-1 != m.upstream_release_notes().flat_list_index() && ! m.upstream_release_notes().name().empty())
+ {
+ std::string value(lines.at(m.upstream_release_notes().flat_list_index()));
+ if (! value.empty())
+ id->load_upstream_release_notes(m.upstream_release_notes().name(),
+ m.upstream_release_notes().description(), value);
+ }
+
+ if (-1 != m.bugs_to().flat_list_index() && ! m.bugs_to().name().empty())
+ {
+ std::string value(lines.at(m.bugs_to().flat_list_index()));
+ if (! value.empty())
+ id->load_bugs_to(m.bugs_to().name(),
+ m.bugs_to().description(), value);
+ }
+
+ if (-1 != m.remote_ids().flat_list_index() && ! m.remote_ids().name().empty())
+ {
+ std::string value(lines.at(m.remote_ids().flat_list_index()));
+ if (! value.empty())
+ id->load_remote_ids(m.remote_ids().name(),
+ m.remote_ids().description(), value);
+ }
+ }
+ else
+ id->set_slot(SlotName("UNKNOWN"));
+
+ return true;
+ }
+}
+
EbuildFlatMetadataCache::EbuildFlatMetadataCache(const Environment * const v, const FSEntry & f,
const FSEntry & e, time_t t, std::tr1::shared_ptr<const EclassMtimes> m, bool s) :
- _env(v),
- _filename(f),
- _ebuild(e),
- _master_mtime(t),
- _eclass_mtimes(m),
- _silent(s)
+ PrivateImplementationPattern<EbuildFlatMetadataCache>(new Implementation<EbuildFlatMetadataCache>(v, f, e, t, m, s))
+{
+}
+
+EbuildFlatMetadataCache::~EbuildFlatMetadataCache()
{
}
@@ -57,9 +276,9 @@ EbuildFlatMetadataCache::load(const std::tr1::shared_ptr<const EbuildID> & id)
{
using namespace std::tr1::placeholders;
- Context context("When loading version metadata from '" + stringify(_filename) + "':");
+ Context context("When loading version metadata from '" + stringify(_imp->filename) + "':");
- std::ifstream cache(stringify(_filename).c_str());
+ std::ifstream cache(stringify(_imp->filename).c_str());
if (cache)
{
@@ -70,167 +289,282 @@ EbuildFlatMetadataCache::load(const std::tr1::shared_ptr<const EbuildID> & id)
try
{
- if (lines.size() >= 15)
+ std::map<std::string, std::string> keys;
+ std::string duplicate;
+ for (std::vector<std::string>::const_iterator it(lines.begin()),
+ it_end(lines.end()); it_end != it; ++it)
{
- id->set_eapi(lines[14]);
- bool ok(true);
-
- if (id->eapi()->supported())
+ std::string::size_type equals(it->find('='));
+ if (std::string::npos == equals)
{
- const EAPIEbuildMetadataVariables & m(*id->eapi()->supported()->ebuild_metadata_variables());
-
- {
- time_t cache_time(std::max(_master_mtime, _filename.mtime()));
- std::set<std::string> tokens;
- tokenise_whitespace(lines[9], std::inserter(tokens, tokens.begin()));
- ok = _ebuild.mtime() <= cache_time;
-
- if (ok && ! tokens.empty())
- ok = tokens.end() == std::find_if(tokens.begin(), tokens.end(),
- std::tr1::bind(std::greater<time_t>(), std::tr1::bind(
- std::tr1::mem_fn(&EclassMtimes::mtime), _eclass_mtimes.get(), _1), cache_time));
- }
-
- if (ok)
- ok = static_cast<int>(lines.size()) >= m.minimum_flat_cache_size();
-
- if (ok)
- {
- if (-1 != m.dependencies().flat_cache_index())
- if (! m.dependencies().name().empty())
- {
- DependenciesRewriter rewriter;
- parse_depend(lines.at(m.dependencies().flat_cache_index()), _env, id, *id->eapi())->accept(rewriter);
- id->load_build_depend(m.dependencies().name() + ".DEPEND", m.dependencies().description() + " (build)", rewriter.depend());
- id->load_run_depend(m.dependencies().name() + ".RDEPEND", m.dependencies().description() + " (run)", rewriter.rdepend());
- id->load_post_depend(m.dependencies().name() + ".PDEPEND", m.dependencies().description() + " (post)", rewriter.pdepend());
- }
-
- if (-1 != m.build_depend().flat_cache_index())
- if (! m.build_depend().name().empty())
- id->load_build_depend(m.build_depend().name(), m.build_depend().description(), lines.at(m.build_depend().flat_cache_index()));
-
- if (-1 != m.run_depend().flat_cache_index())
- if (! m.run_depend().name().empty())
- id->load_run_depend(m.run_depend().name(), m.run_depend().description(), lines.at(m.run_depend().flat_cache_index()));
+ Log::get_instance()->message("e.cache.flat_hash.not", ll_debug, lc_context)
+ << "cache file lacks = on line " << ((it - lines.begin()) + 1) << ", assuming flat_list";
+ return load_flat_list(id, lines, _imp.get());
+ }
- id->set_slot(SlotName(lines.at(m.slot().flat_cache_index())));
+ if (! keys.insert(std::make_pair(it->substr(0, equals), it->substr(equals + 1))).second)
+ duplicate = it->substr(0, equals);
+ }
- if (-1 != m.src_uri().flat_cache_index())
- if (! m.src_uri().name().empty())
- id->load_src_uri(m.src_uri().name(), m.src_uri().description(), lines.at(m.src_uri().flat_cache_index()));
+ Context ctx("When loading flat_hash format cache file:");
- if (-1 != m.restrictions().flat_cache_index())
- if (! m.restrictions().name().empty())
- id->load_restrict(m.restrictions().name(), m.restrictions().description(), lines.at(m.restrictions().flat_cache_index()));
+ if (! duplicate.empty())
+ {
+ Log::get_instance()->message("e.cache.flat_hash.broken", ll_warning, lc_context)
+ << "cache file contains duplicate key '" << duplicate << "'";
+ return false;
+ }
- if (-1 != m.homepage().flat_cache_index())
- if (! m.homepage().name().empty())
- id->load_homepage(m.homepage().name(), m.homepage().description(), lines.at(m.homepage().flat_cache_index()));
+ std::map<std::string, std::string>::const_iterator eapi(keys.find("EAPI"));
+ if (keys.end() == eapi)
+ {
+ Log::get_instance()->message("e.cache.flat_hash.broken", ll_warning, lc_context)
+ << "cache file contains no 'EAPI' key";
+ return false;
+ }
+ id->set_eapi(eapi->second);
- if (-1 != m.license().flat_cache_index())
- if (! m.license().name().empty())
- id->load_license(m.license().name(), m.license().description(), lines.at(m.license().flat_cache_index()));
+ if (id->eapi()->supported())
+ {
+ const EAPIEbuildMetadataVariables & m(*id->eapi()->supported()->ebuild_metadata_variables());
- if (-1 != m.short_description().flat_cache_index())
- if (! m.short_description().name().empty())
- id->load_short_description(m.short_description().name(),
- m.short_description().description(),
- lines.at(m.short_description().flat_cache_index()));
+ {
+ bool ok(_imp->ebuild.mtime() == destringify<std::time_t>(keys["_mtime_"]));
+ if (! ok)
+ Log::get_instance()->message("e.cache.flat_hash.mtime", ll_debug, lc_context)
+ << "ebuild has mtime " << _imp->ebuild.mtime() << ", but expected " << keys["_mtime_"];
- if (-1 != m.long_description().flat_cache_index())
- if (! m.long_description().name().empty())
+ if (ok && id->eapi()->supported()->ebuild_options()->support_eclasses())
+ {
+ std::vector<std::string> eclasses;
+ tokenise<delim_kind::AnyOfTag, delim_mode::DelimiterTag>(keys["_eclasses_"], "\t", "", std::back_inserter(eclasses));
+ FSEntry eclassdir(id->repository()->location_key()->value() / "eclass");
+ for (std::vector<std::string>::const_iterator it(eclasses.begin()),
+ it_end(eclasses.end()); it_end != it; ++it)
+ {
+ std::string eclass_name(*it);
+ if (eclasses.end() == ++it)
{
- std::string value(lines.at(m.long_description().flat_cache_index()));
- if (! value.empty())
- id->load_long_description(m.long_description().name(),
- m.long_description().description(), value);
+ Log::get_instance()->message("e.cache.flat_hash.eclass.truncated", ll_warning, lc_context)
+ << "_eclasses_ entry is incomplete";
+ return false;
}
+ FSEntry eclass_dir(std::string::npos != it->find('/') ? *(it++) : eclassdir);
+ if (eclasses.end() == it)
+ {
+ Log::get_instance()->message("e.cache.flat_hash.eclass.truncated", ll_warning, lc_context)
+ << "_eclasses_ entry is incomplete";
+ return false;
+ }
+ std::time_t eclass_mtime(destringify<std::time_t>(*it));
- if (-1 != m.keywords().flat_cache_index())
- if (! m.keywords().name().empty())
- id->load_keywords(m.keywords().name(), m.keywords().description(), lines.at(m.keywords().flat_cache_index()));
-
- if (-1 != m.inherited().flat_cache_index())
- if (! m.inherited().name().empty())
- id->load_inherited(m.inherited().name(), m.inherited().description(), lines.at(m.inherited().flat_cache_index()));
-
- if (-1 != m.iuse().flat_cache_index())
- if (! m.iuse().name().empty())
- id->load_iuse(m.iuse().name(), m.iuse().description(), lines.at(m.iuse().flat_cache_index()));
+ const FSEntry * eclass(_imp->eclass_mtimes->eclass(eclass_name));
+ if (! eclass)
+ {
+ Log::get_instance()->message("e.cache.flat_hash.eclass.missing", ll_debug, lc_context)
+ << "Can't find cache-requested eclass '" << eclass_name << "'";
+ ok = false;
+ }
- if (-1 != m.pdepend().flat_cache_index())
- if (! m.pdepend().name().empty())
- id->load_post_depend(m.pdepend().name(), m.pdepend().description(), lines.at(m.pdepend().flat_cache_index()));
+ else if (eclass->dirname() != eclass_dir)
+ {
+ Log::get_instance()->message("e.cache.flat_hash.eclass.wrong_location", ll_debug, lc_context)
+ << "Cache-requested eclass '" << eclass_name << "' was found at '"
+ << eclass->dirname() << "', but expected '" << eclass_dir << "'";
+ ok = false;
+ }
- if (-1 != m.provide().flat_cache_index())
- if (! m.provide().name().empty())
- id->load_provide(m.provide().name(), m.provide().description(), lines.at(m.provide().flat_cache_index()));
+ else if (eclass->mtime() != eclass_mtime)
+ {
+ Log::get_instance()->message("e.cache.flat_hash.eclass.wrong_mtime", ll_debug, lc_context)
+ << "Cache-requested eclass '" << eclass_name << "' has mtime "
+ << eclass->mtime() << ", but expected " << eclass_mtime;
+ ok = false;
+ }
- if (-1 != m.use().flat_cache_index())
- if (! m.use().name().empty())
- id->load_use(m.use().name(), m.use().description(), lines.at(m.use().flat_cache_index()));
+ if (! ok)
+ break;
+ }
+ }
- if (-1 != m.upstream_changelog().flat_cache_index())
- if (! m.upstream_changelog().name().empty())
+ else if (ok && id->eapi()->supported()->ebuild_options()->support_exlibs())
+ {
+ std::vector<std::string> exlibs;
+ tokenise<delim_kind::AnyOfTag, delim_mode::DelimiterTag>(keys["_exlibs_"], "\t", "", std::back_inserter(exlibs));
+ for (std::vector<std::string>::const_iterator it(exlibs.begin()),
+ it_end(exlibs.end()); it_end != it; ++it)
+ {
+ std::string exlib_name(*it);
+ if (exlibs.end() == ++it)
{
- std::string value(lines.at(m.upstream_changelog().flat_cache_index()));
- if (! value.empty())
- id->load_upstream_changelog(m.upstream_changelog().name(),
- m.upstream_changelog().description(), value);
+ Log::get_instance()->message("e.cache.flat_hash.exlib.truncated", ll_warning, lc_context)
+ << "_exlibs_ entry is incomplete";
+ return false;
}
-
- if (-1 != m.upstream_documentation().flat_cache_index())
- if (! m.upstream_documentation().name().empty())
+ FSEntry exlib_dir(*it);
+ if (exlibs.end() == ++it)
{
- std::string value(lines.at(m.upstream_documentation().flat_cache_index()));
- if (! value.empty())
- id->load_upstream_documentation(m.upstream_documentation().name(),
- m.upstream_documentation().description(), value);
+ Log::get_instance()->message("e.cache.flat_hash.exlibs.truncated", ll_warning, lc_context)
+ << "_exlibs_ entry is incomplete";
+ return false;
}
+ std::time_t exlib_mtime(destringify<std::time_t>(*it));
- if (-1 != m.upstream_release_notes().flat_cache_index())
- if (! m.upstream_release_notes().name().empty())
+ const FSEntry * exlib(_imp->eclass_mtimes->exlib(exlib_name, id->name()));
+ if (! exlib)
{
- std::string value(lines.at(m.upstream_release_notes().flat_cache_index()));
- if (! value.empty())
- id->load_upstream_release_notes(m.upstream_release_notes().name(),
- m.upstream_release_notes().description(), value);
+ Log::get_instance()->message("e.cache.flat_hash.exlib.missing", ll_debug, lc_context)
+ << "Can't find cache-requested exlib '" << exlib_name << "'";
+ ok = false;
}
- if (-1 != m.bugs_to().flat_cache_index())
- if (! m.bugs_to().name().empty())
+ else if (exlib->dirname() != exlib_dir)
{
- std::string value(lines.at(m.bugs_to().flat_cache_index()));
- if (! value.empty())
- id->load_bugs_to(m.bugs_to().name(),
- m.bugs_to().description(), value);
+ Log::get_instance()->message("e.cache.flat_hash.exlib.wrong_location", ll_debug, lc_context)
+ << "Cache-requested exlib '" << exlib_name << "' was found at '"
+ << exlib->dirname() << "', but expected '" << exlib_dir << "'";
+ ok = false;
}
- if (-1 != m.remote_ids().flat_cache_index())
- if (! m.remote_ids().name().empty())
+ else if (exlib->mtime() != exlib_mtime)
{
- std::string value(lines.at(m.remote_ids().flat_cache_index()));
- if (! value.empty())
- id->load_remote_ids(m.remote_ids().name(),
- m.remote_ids().description(), value);
+ Log::get_instance()->message("e.cache.flat_hash.exlib.wrong_mtime", ll_debug, lc_context)
+ << "Cache-requested exlib '" << exlib_name << "' has mtime "
+ << exlib->mtime() << ", but expected " << exlib_mtime;
+ ok = false;
}
+
+ if (! ok)
+ break;
+ }
+ }
+
+ if (! ok)
+ {
+ Log::get_instance()->message("e.cache.stale", ll_warning, lc_no_context)
+ << "Stale cache file at '" << _imp->filename << "'";
+ return false;
}
}
- else
- id->set_slot(SlotName("UNKNOWN"));
- if (! ok)
- Log::get_instance()->message("e.cache.stale", ll_warning, lc_no_context) << "Stale cache file at '"
- << _filename << "'";
- return ok;
+ if (! m.dependencies().name().empty())
+ {
+ DependenciesRewriter rewriter;
+ parse_depend(keys[m.dependencies().name()], _imp->env, id, *id->eapi())->accept(rewriter);
+ id->load_build_depend(m.dependencies().name() + ".DEPEND", m.dependencies().description() + " (build)", rewriter.depend());
+ id->load_run_depend(m.dependencies().name() + ".RDEPEND", m.dependencies().description() + " (run)", rewriter.rdepend());
+ id->load_post_depend(m.dependencies().name() + ".PDEPEND", m.dependencies().description() + " (post)", rewriter.pdepend());
+ }
+
+ if (! m.build_depend().name().empty())
+ id->load_build_depend(m.build_depend().name(), m.build_depend().description(), keys[m.build_depend().name()]);
+
+ if (! m.run_depend().name().empty())
+ id->load_run_depend(m.run_depend().name(), m.run_depend().description(), keys[m.run_depend().name()]);
+
+ id->set_slot(SlotName(keys[m.slot().name()]));
+
+ if (! m.src_uri().name().empty())
+ id->load_src_uri(m.src_uri().name(), m.src_uri().description(), keys[m.src_uri().name()]);
+
+ if (! m.restrictions().name().empty())
+ id->load_restrict(m.restrictions().name(), m.restrictions().description(), keys[m.restrictions().name()]);
+
+ if (! m.homepage().name().empty())
+ id->load_homepage(m.homepage().name(), m.homepage().description(), keys[m.homepage().name()]);
+
+ if (! m.license().name().empty())
+ id->load_license(m.license().name(), m.license().description(), keys[m.license().name()]);
+
+ if (! m.short_description().name().empty())
+ id->load_short_description(m.short_description().name(),
+ m.short_description().description(),
+ keys[m.short_description().name()]);
+
+ if (! m.long_description().name().empty())
+ {
+ std::string value(keys[m.long_description().name()]);
+ if (! value.empty())
+ id->load_long_description(m.long_description().name(),
+ m.long_description().description(), value);
+ }
+
+ if (! m.keywords().name().empty())
+ id->load_keywords(m.keywords().name(), m.keywords().description(), keys[m.keywords().name()]);
+
+ if (! m.inherited().name().empty())
+ {
+ std::vector<std::string> full, brief;
+ if (id->eapi()->supported()->ebuild_options()->support_eclasses())
+ tokenise<delim_kind::AnyOfTag, delim_mode::DelimiterTag>(keys["_eclasses_"], "\t", "", std::back_inserter(full));
+ else if (id->eapi()->supported()->ebuild_options()->support_exlibs())
+ tokenise<delim_kind::AnyOfTag, delim_mode::DelimiterTag>(keys["_exlibs_"], "\t", "", std::back_inserter(full));
+ for (std::vector<std::string>::const_iterator it(full.begin()),
+ it_end(full.end()); it_end != it; ++it)
+ {
+ brief.push_back(*it);
+ if (std::string::npos != (++it)->find('/'))
+ ++it;
+ }
+ id->load_inherited(m.inherited().name(), m.inherited().description(), join(brief.begin(), brief.end(), " "));
+ }
+
+ if (! m.iuse().name().empty())
+ id->load_iuse(m.iuse().name(), m.iuse().description(), keys[m.iuse().name()]);
+
+ if (! m.pdepend().name().empty())
+ id->load_post_depend(m.pdepend().name(), m.pdepend().description(), keys[m.pdepend().name()]);
+
+ if (! m.provide().name().empty())
+ id->load_provide(m.provide().name(), m.provide().description(), keys[m.provide().name()]);
+
+ if (! m.use().name().empty())
+ id->load_use(m.use().name(), m.use().description(), keys[m.use().name()]);
+
+ if (! m.upstream_changelog().name().empty())
+ {
+ std::string value(keys[m.upstream_changelog().name()]);
+ if (! value.empty())
+ id->load_upstream_changelog(m.upstream_changelog().name(),
+ m.upstream_changelog().description(), value);
+ }
+
+ if (! m.upstream_documentation().name().empty())
+ {
+ std::string value(keys[m.upstream_documentation().name()]);
+ if (! value.empty())
+ id->load_upstream_documentation(m.upstream_documentation().name(),
+ m.upstream_documentation().description(), value);
+ }
+
+ if (! m.upstream_release_notes().name().empty())
+ {
+ std::string value(keys[m.upstream_release_notes().name()]);
+ if (! value.empty())
+ id->load_upstream_release_notes(m.upstream_release_notes().name(),
+ m.upstream_release_notes().description(), value);
+ }
+
+ if (! m.bugs_to().name().empty())
+ {
+ std::string value(keys[m.bugs_to().name()]);
+ if (! value.empty())
+ id->load_bugs_to(m.bugs_to().name(),
+ m.bugs_to().description(), value);
+ }
+
+ if (! m.remote_ids().name().empty())
+ {
+ std::string value(keys[m.remote_ids().name()]);
+ if (! value.empty())
+ id->load_remote_ids(m.remote_ids().name(),
+ m.remote_ids().description(), value);
+ }
}
else
- {
- Log::get_instance()->message("e.cache.incomplete", ll_warning, lc_no_context) << "Incomplete cache file at '"
- << _filename << "'";
- return false;
- }
+ id->set_slot(SlotName("UNKNOWN"));
+
+ return true;
}
catch (const InternalError &)
{
@@ -239,14 +573,14 @@ EbuildFlatMetadataCache::load(const std::tr1::shared_ptr<const EbuildID> & id)
catch (const Exception & e)
{
Log::get_instance()->message("e.cache.failure", ll_warning, lc_no_context) << "Not using cache file at '"
- << _filename << "' due to exception '" << e.message() << "' (" << e.what() << ")";
+ << _imp->filename << "' due to exception '" << e.message() << "' (" << e.what() << ")";
return false;
}
}
else
{
- Log::get_instance()->message("e.cache.failure", _silent ? ll_debug : ll_warning, lc_no_context)
- << "Couldn't use the cache file at '" << _filename << "'";
+ Log::get_instance()->message("e.cache.failure", _imp->silent ? ll_debug : ll_warning, lc_no_context)
+ << "Couldn't use the cache file at '" << _imp->filename << "': " << std::strerror(errno);
return false;
}
}
@@ -269,17 +603,25 @@ namespace
d->accept(p);
return stringify(p);
}
+
+ template <typename T_>
+ void write_kv(std::ostream & stream, const std::string & key, const T_ & value)
+ {
+ std::string str_value(stringify(value));
+ if (! str_value.empty())
+ stream << key << "=" << str_value << std::endl;
+ }
}
void
EbuildFlatMetadataCache::save(const std::tr1::shared_ptr<const EbuildID> & id)
{
- Context context("When saving version metadata to '" + stringify(_filename) + "':");
+ Context context("When saving version metadata to '" + stringify(_imp->filename) + "':");
try
{
- _filename.dirname().dirname().mkdir();
- _filename.dirname().mkdir();
+ _imp->filename.dirname().dirname().mkdir();
+ _imp->filename.dirname().mkdir();
}
catch (const FSError & e)
{
@@ -290,174 +632,120 @@ EbuildFlatMetadataCache::save(const std::tr1::shared_ptr<const EbuildID> & id)
if (! id->eapi()->supported())
{
Log::get_instance()->message("e.cache.save.eapi_unsupoprted", ll_warning, lc_no_context) << "Not writing cache file to '"
- << _filename << "' because EAPI '" << id->eapi()->name() << "' is not supported";
+ << _imp->filename << "' because EAPI '" << id->eapi()->name() << "' is not supported";
return;
}
std::ostringstream cache;
+ write_kv(cache, "_mtime_", _imp->ebuild.mtime());
+
+ if (id->eapi()->supported()->ebuild_options()->support_eclasses() && id->inherited_key())
+ {
+ std::vector<std::string> eclasses;
+ for (Set<std::string>::ConstIterator it(id->inherited_key()->value()->begin()),
+ it_end(id->inherited_key()->value()->end()); it_end != it; ++it)
+ {
+ const FSEntry * eclass(_imp->eclass_mtimes->eclass(*it));
+ if (! eclass)
+ throw InternalError(PALUDIS_HERE, "eclass '" + *it + "' disappeared?");
+ eclasses.push_back(*it);
+ eclasses.push_back(stringify(eclass->dirname()));
+ eclasses.push_back(stringify(eclass->mtime()));
+ }
+ write_kv(cache, "_eclasses_", join(eclasses.begin(), eclasses.end(), "\t"));
+ }
+
+ else if (id->eapi()->supported()->ebuild_options()->support_exlibs() && id->inherited_key())
+ {
+ std::vector<std::string> exlibs;
+ for (Set<std::string>::ConstIterator it(id->inherited_key()->value()->begin()),
+ it_end(id->inherited_key()->value()->end()); it_end != it; ++it)
+ {
+ const FSEntry * exlib(_imp->eclass_mtimes->exlib(*it, id->name()));
+ if (! exlib)
+ throw InternalError(PALUDIS_HERE, "exlib '" + *it + "' for '" + stringify(id->name()) + "' disappeared?");
+ exlibs.push_back(*it);
+ exlibs.push_back(stringify(exlib->dirname()));
+ exlibs.push_back(stringify(exlib->mtime()));
+ }
+ write_kv(cache, "_exlibs_", join(exlibs.begin(), exlibs.end(), "\t"));
+ }
try
{
const EAPIEbuildMetadataVariables & m(*id->eapi()->supported()->ebuild_metadata_variables());
- for (int x(0), x_end(m.minimum_flat_cache_size()) ; x != x_end ; ++x)
+
+ if (! m.dependencies().name().empty())
{
- if (x == m.dependencies().flat_cache_index())
- {
- std::string s;
+ std::string s;
- if (id->build_dependencies_key())
- s.append(flatten(id->build_dependencies_key()->value()) + " ");
- if (id->run_dependencies_key())
- s.append(flatten(id->run_dependencies_key()->value()) + " ");
- if (id->post_dependencies_key())
- s.append(flatten(id->post_dependencies_key()->value()) + " ");
+ if (id->build_dependencies_key())
+ s.append(flatten(id->build_dependencies_key()->value()) + " ");
+ if (id->run_dependencies_key())
+ s.append(flatten(id->run_dependencies_key()->value()) + " ");
+ if (id->post_dependencies_key())
+ s.append(flatten(id->post_dependencies_key()->value()) + " ");
- cache << s << std::endl;
- }
- else if (x == m.use().flat_cache_index())
- {
- if (id->use_key())
- cache << join(id->use_key()->value()->begin(), id->use_key()->value()->end(), " ") << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.build_depend().flat_cache_index())
- {
- if (id->build_dependencies_key())
- cache << flatten(id->build_dependencies_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.run_depend().flat_cache_index())
- {
- if (id->run_dependencies_key())
- cache << flatten(id->run_dependencies_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.slot().flat_cache_index())
- {
- cache << normalise(id->slot()) << std::endl;
- }
- else if (x == m.src_uri().flat_cache_index())
- {
- if (id->fetches_key())
- cache << flatten(id->fetches_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.restrictions().flat_cache_index())
- {
- if (id->restrict_key())
- cache << flatten(id->restrict_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.homepage().flat_cache_index())
- {
- if (id->homepage_key())
- cache << flatten(id->homepage_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.license().flat_cache_index())
- {
- if (id->license_key())
- cache << flatten(id->license_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.short_description().flat_cache_index())
- {
- if (id->short_description_key())
- cache << normalise(id->short_description_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.keywords().flat_cache_index())
- {
- if (id->keywords_key())
- cache << join(id->keywords_key()->value()->begin(), id->keywords_key()->value()->end(), " ") << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.inherited().flat_cache_index())
- {
- if (id->inherited_key())
- cache << join(id->inherited_key()->value()->begin(), id->inherited_key()->value()->end(), " ") << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.iuse().flat_cache_index())
- {
- if (id->iuse_key())
- cache << join(id->iuse_key()->value()->begin(), id->iuse_key()->value()->end(), " ") << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.pdepend().flat_cache_index())
- {
- if (id->post_dependencies_key())
- cache << flatten(id->post_dependencies_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.provide().flat_cache_index())
- {
- if (id->provide_key())
- cache << flatten(id->provide_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.eapi().flat_cache_index())
- {
- cache << normalise(id->eapi()->name()) << std::endl;
- }
- else if (x == m.long_description().flat_cache_index())
- {
- if (id->long_description_key())
- cache << normalise(id->long_description_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.bugs_to().flat_cache_index())
- {
- if (id->bugs_to_key())
- cache << flatten(id->bugs_to_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.remote_ids().flat_cache_index())
- {
- if (id->remote_ids_key())
- cache << flatten(id->remote_ids_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.upstream_changelog().flat_cache_index())
- {
- if (id->upstream_changelog_key())
- cache << flatten(id->upstream_changelog_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.upstream_documentation().flat_cache_index())
- {
- if (id->upstream_documentation_key())
- cache << flatten(id->upstream_documentation_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else if (x == m.upstream_release_notes().flat_cache_index())
- {
- if (id->upstream_release_notes_key())
- cache << flatten(id->upstream_release_notes_key()->value()) << std::endl;
- else
- cache << std::endl;
- }
- else
- cache << std::endl;
+ write_kv(cache, m.dependencies().name(), s);
}
+
+ if (! m.use().name().empty() && id->use_key())
+ write_kv(cache, m.use().name(), join(id->use_key()->value()->begin(), id->use_key()->value()->end(), " "));
+
+ if (! m.build_depend().name().empty() && id->build_dependencies_key())
+ write_kv(cache, m.build_depend().name(), flatten(id->build_dependencies_key()->value()));
+
+ if (! m.run_depend().name().empty() && id->run_dependencies_key())
+ write_kv(cache, m.run_depend().name(), flatten(id->run_dependencies_key()->value()));
+
+ write_kv(cache, m.slot().name(), normalise(id->slot()));
+
+ if (! m.src_uri().name().empty() && id->fetches_key())
+ write_kv(cache, m.src_uri().name(), flatten(id->fetches_key()->value()));
+
+ if (! m.restrictions().name().empty() && id->restrict_key())
+ write_kv(cache, m.restrictions().name(), flatten(id->restrict_key()->value()));
+
+ if (! m.homepage().name().empty() && id->homepage_key())
+ write_kv(cache, m.homepage().name(), flatten(id->homepage_key()->value()));
+
+ if (! m.license().name().empty() && id->license_key())
+ write_kv(cache, m.license().name(), flatten(id->license_key()->value()));
+
+ if (! m.short_description().name().empty() && id->short_description_key())
+ write_kv(cache, m.short_description().name(), normalise(id->short_description_key()->value()));
+
+ if (! m.keywords().name().empty() && id->keywords_key())
+ write_kv(cache, m.keywords().name(), join(id->keywords_key()->value()->begin(), id->keywords_key()->value()->end(), " "));
+
+ if (! m.iuse().name().empty() && id->iuse_key())
+ write_kv(cache, m.iuse().name(), join(id->iuse_key()->value()->begin(), id->iuse_key()->value()->end(), " "));
+
+ if (! m.pdepend().name().empty() && id->post_dependencies_key())
+ write_kv(cache, m.pdepend().name(), flatten(id->post_dependencies_key()->value()));
+
+ if (! m.provide().name().empty() && id->provide_key())
+ write_kv(cache, m.provide().name(), flatten(id->provide_key()->value()));
+
+ write_kv(cache, "EAPI", normalise(id->eapi()->name()));
+
+ if (! m.long_description().name().empty() && id->long_description_key())
+ write_kv(cache, m.long_description().name(), normalise(id->long_description_key()->value()));
+
+ if (! m.bugs_to().name().empty() && id->bugs_to_key())
+ write_kv(cache, m.bugs_to().name(), flatten(id->bugs_to_key()->value()));
+
+ if (! m.remote_ids().name().empty() && id->remote_ids_key())
+ write_kv(cache, m.remote_ids().name(), flatten(id->remote_ids_key()->value()));
+
+ if (! m.upstream_changelog().name().empty() && id->upstream_changelog_key())
+ write_kv(cache, m.upstream_changelog().name(), flatten(id->upstream_changelog_key()->value()));
+
+ if (! m.upstream_documentation().name().empty() && id->upstream_documentation_key())
+ write_kv(cache, m.upstream_documentation().name(), flatten(id->upstream_documentation_key()->value()));
+
+ if (! m.upstream_release_notes().name().empty() && id->upstream_release_notes_key())
+ write_kv(cache, m.upstream_release_notes().name(), flatten(id->upstream_release_notes_key()->value()));
}
catch (const InternalError &)
{
@@ -466,18 +754,20 @@ EbuildFlatMetadataCache::save(const std::tr1::shared_ptr<const EbuildID> & id)
catch (const Exception & e)
{
Log::get_instance()->message("e.cache.save.failure", ll_warning, lc_no_context) << "Not writing cache file to '"
- << _filename << "' due to exception '" << e.message() << "' (" << e.what() << ")";
+ << _imp->filename << "' due to exception '" << e.message() << "' (" << e.what() << ")";
return;
}
- std::ofstream cache_file(stringify(_filename).c_str());
+ std::ofstream cache_file(stringify(_imp->filename).c_str());
if (cache_file)
cache_file << cache.str();
else
{
Log::get_instance()->message("e.cache.save.failure", ll_warning, lc_no_context) << "Couldn't write cache file to '"
- << _filename << "': " << std::strerror(errno);
+ << _imp->filename << "': " << std::strerror(errno);
}
}
+template class PrivateImplementationPattern<EbuildFlatMetadataCache>;
+
diff --git a/paludis/repositories/e/ebuild_flat_metadata_cache.hh b/paludis/repositories/e/ebuild_flat_metadata_cache.hh
index 85ebf9f..88f6b52 100644
--- a/paludis/repositories/e/ebuild_flat_metadata_cache.hh
+++ b/paludis/repositories/e/ebuild_flat_metadata_cache.hh
@@ -24,36 +24,31 @@
#include <paludis/repositories/e/ebuild_id.hh>
#include <paludis/util/fs_entry.hh>
#include <paludis/repositories/e/eclass_mtimes.hh>
+#include <paludis/util/private_implementation_pattern.hh>
namespace paludis
{
namespace erepository
{
/**
- * Implements flat file metadata cache handling for a ERepository
- * using EbuildEntries.
+ * Implements metadata cache handling for a ERepository using
+ * EbuildEntries.
*
* \see EbuildEntries
* \see ERepository
* \ingroup grperepository
* \nosubgrouping
*/
- class EbuildFlatMetadataCache
+ class EbuildFlatMetadataCache :
+ private PrivateImplementationPattern<EbuildFlatMetadataCache>
{
- private:
- const Environment * const _env;
- const FSEntry & _filename;
- const FSEntry & _ebuild;
- time_t _master_mtime;
- std::tr1::shared_ptr<const EclassMtimes> _eclass_mtimes;
- bool _silent;
-
public:
///\name Basic operations
///\{
EbuildFlatMetadataCache(const Environment * const, const FSEntry & filename, const FSEntry & ebuild,
time_t master_mtime, std::tr1::shared_ptr<const EclassMtimes> eclass_mtimes, bool silent);
+ ~EbuildFlatMetadataCache();
///\}
@@ -66,6 +61,10 @@ namespace paludis
///\}
};
}
+
+#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE
+ extern template class PrivateImplementationPattern<erepository::EbuildFlatMetadataCache>;
+#endif
}
#endif
diff --git a/paludis/repositories/e/eclass_mtimes.cc b/paludis/repositories/e/eclass_mtimes.cc
index 428dc0b..e8136c7 100644
--- a/paludis/repositories/e/eclass_mtimes.cc
+++ b/paludis/repositories/e/eclass_mtimes.cc
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2008 David Leverton
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -18,6 +19,9 @@
*/
#include "eclass_mtimes.hh"
+#include <paludis/repositories/e/e_repository.hh>
+#include <paludis/repositories/e/layout.hh>
+#include <paludis/name.hh>
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/sequence.hh>
#include <paludis/util/fs_entry.hh>
@@ -28,24 +32,58 @@
using namespace paludis;
+namespace
+{
+ struct Cache
+ {
+ std::tr1::shared_ptr<const FSEntrySequence> dirs;
+ std::tr1::unordered_map<std::string, FSEntry, Hash<std::string> > files;
+
+ Cache(const std::tr1::shared_ptr<const FSEntrySequence> & d) :
+ dirs(d)
+ {
+ }
+ };
+
+ const FSEntry *
+ lookup(const std::string & e, Cache & c)
+ {
+ std::tr1::unordered_map<std::string, FSEntry, Hash<std::string> >::const_iterator i(c.files.find(e));
+ if (i != c.files.end())
+ return & i->second;
+
+ for (FSEntrySequence::ReverseConstIterator d(c.dirs->rbegin()),
+ d_end(c.dirs->rend()) ; d != d_end ; ++d)
+ {
+ FSEntry f(*d / e);
+ if (f.exists())
+ return & c.files.insert(std::make_pair(e, f)).first->second;
+ }
+
+ return 0;
+ }
+}
+
namespace paludis
{
template<>
struct Implementation<EclassMtimes>
{
- std::tr1::shared_ptr<const FSEntrySequence> eclass_dirs;
+ const ERepository * repo;
+ mutable Cache eclasses;
+ mutable std::tr1::unordered_map<QualifiedPackageName, Cache, Hash<QualifiedPackageName> > exlibs;
mutable Mutex mutex;
- mutable std::tr1::unordered_map<std::string, time_t, Hash<std::string> > eclass_mtimes;
- Implementation(std::tr1::shared_ptr<const FSEntrySequence> d) :
- eclass_dirs(d)
+ Implementation(const ERepository * r, const std::tr1::shared_ptr<const FSEntrySequence> & d) :
+ repo(r),
+ eclasses(d)
{
}
};
}
-EclassMtimes::EclassMtimes(std::tr1::shared_ptr<const FSEntrySequence> d) :
- PrivateImplementationPattern<EclassMtimes>(new Implementation<EclassMtimes>(d))
+EclassMtimes::EclassMtimes(const ERepository * r, const std::tr1::shared_ptr<const FSEntrySequence> & d) :
+ PrivateImplementationPattern<EclassMtimes>(new Implementation<EclassMtimes>(r, d))
{
}
@@ -53,25 +91,20 @@ EclassMtimes::~EclassMtimes()
{
}
-time_t
-EclassMtimes::mtime(const std::string & e) const
+const FSEntry *
+EclassMtimes::eclass(const std::string & e) const
{
Lock l(_imp->mutex);
+ return lookup(e + ".eclass", _imp->eclasses);
+}
- std::tr1::unordered_map<std::string, time_t, Hash<std::string> >::const_iterator i(_imp->eclass_mtimes.find(e));
- if (i != _imp->eclass_mtimes.end())
- return i->second;
-
- time_t r(0);
- for (FSEntrySequence::ConstIterator d(_imp->eclass_dirs->begin()),
- d_end(_imp->eclass_dirs->end()) ; d != d_end ; ++d)
- {
- FSEntry f(*d / (e + ".eclass"));
- if (f.exists())
- r = std::max(r, f.mtime());
- }
-
- _imp->eclass_mtimes.insert(std::make_pair(e, r));
- return r;
+const FSEntry *
+EclassMtimes::exlib(const std::string & e, const QualifiedPackageName & qpn) const
+{
+ Lock l(_imp->mutex);
+ std::tr1::unordered_map<QualifiedPackageName, Cache, Hash<QualifiedPackageName> >::iterator cache(_imp->exlibs.find(qpn));
+ if (_imp->exlibs.end() == cache)
+ cache = _imp->exlibs.insert(std::make_pair(qpn, Cache(_imp->repo->layout()->exlibsdirs(qpn)))).first;
+ return lookup(e + ".exlib", cache->second);
}
diff --git a/paludis/repositories/e/eclass_mtimes.hh b/paludis/repositories/e/eclass_mtimes.hh
index 891f29e..40ca5cb 100644
--- a/paludis/repositories/e/eclass_mtimes.hh
+++ b/paludis/repositories/e/eclass_mtimes.hh
@@ -20,14 +20,17 @@
#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_ECLASS_MTIMES_HH
#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_ECLASS_MTIMES_HH 1
+#include <paludis/name-fwd.hh>
#include <paludis/util/private_implementation_pattern.hh>
#include <paludis/util/fs_entry-fwd.hh>
#include <tr1/memory>
namespace paludis
{
+ class ERepository;
+
/**
- * Holds an eclass mtimes cache for a ERepository.
+ * Holds an eclass mtimes cache for an ERepository.
*
* \see ERepository
* \ingroup grperepository
@@ -40,15 +43,20 @@ namespace paludis
///\name Basic operations
///\{
- EclassMtimes(std::tr1::shared_ptr<const FSEntrySequence>);
+ EclassMtimes(const ERepository *, const std::tr1::shared_ptr<const FSEntrySequence> &);
~EclassMtimes();
///\}
/**
- * Fetch the mtime for a given eclass.
+ * Fetch the full path of a given eclass.
+ */
+ const FSEntry * eclass(const std::string &) const;
+
+ /**
+ * Fetch the full path of a given exlib, on the path of a given package.
*/
- time_t mtime(const std::string &) const;
+ const FSEntry * exlib(const std::string &, const QualifiedPackageName &) const;
};
}