aboutsummaryrefslogtreecommitdiff
path: root/paludis/repositories/unavailable/unavailable_repository_store.cc
diff options
context:
space:
mode:
Diffstat (limited to 'paludis/repositories/unavailable/unavailable_repository_store.cc')
-rw-r--r--paludis/repositories/unavailable/unavailable_repository_store.cc216
1 files changed, 216 insertions, 0 deletions
diff --git a/paludis/repositories/unavailable/unavailable_repository_store.cc b/paludis/repositories/unavailable/unavailable_repository_store.cc
new file mode 100644
index 000000000..6795a1724
--- /dev/null
+++ b/paludis/repositories/unavailable/unavailable_repository_store.cc
@@ -0,0 +1,216 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * 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
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repositories/unavailable/unavailable_repository_store.hh>
+#include <paludis/repositories/unavailable/unavailable_repository_file.hh>
+#include <paludis/repositories/unavailable/unavailable_id.hh>
+#include <paludis/repositories/unavailable/unavailable_mask.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/hashes.hh>
+#include <paludis/util/kc.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/log.hh>
+#include <paludis/name.hh>
+#include <paludis/version_spec.hh>
+#include <paludis/literal_metadata_key.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <tr1/functional>
+#include <tr1/unordered_map>
+#include <algorithm>
+#include <set>
+
+using namespace paludis;
+using namespace paludis::unavailable_repository;
+
+typedef std::tr1::unordered_map<CategoryNamePart,
+ std::tr1::shared_ptr<QualifiedPackageNameSet>,
+ Hash<CategoryNamePart> > PackageNames;
+
+typedef std::tr1::unordered_map<QualifiedPackageName,
+ std::tr1::shared_ptr<PackageIDSequence>,
+ Hash<QualifiedPackageName> > IDs;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<UnavailableRepositoryStore>
+ {
+ const UnavailableRepository * const repo;
+ mutable std::tr1::shared_ptr<CategoryNamePartSet> categories;
+ mutable PackageNames package_names;
+ mutable IDs ids;
+
+ std::set<std::string> seen_repo_names;
+
+ Implementation(const UnavailableRepository * const r) :
+ repo(r),
+ categories(new CategoryNamePartSet)
+ {
+ }
+ };
+}
+
+UnavailableRepositoryStore::UnavailableRepositoryStore(
+ const Environment * const env,
+ const UnavailableRepository * const repo,
+ const FSEntry & f) :
+ PrivateImplementationPattern<UnavailableRepositoryStore>(new Implementation<UnavailableRepositoryStore>(repo))
+{
+ _populate(env, f);
+}
+
+UnavailableRepositoryStore::~UnavailableRepositoryStore()
+{
+}
+
+void
+UnavailableRepositoryStore::_populate(const Environment * const env, const FSEntry & f)
+{
+ Context context("When populating UnavailableRepository from directory '" + stringify(f) + "':");
+
+ using namespace std::tr1::placeholders;
+ std::for_each(DirIterator(f), DirIterator(), std::tr1::bind(
+ &UnavailableRepositoryStore::_populate_one, this, env, _1));
+}
+
+void
+UnavailableRepositoryStore::_populate_one(const Environment * const env, const FSEntry & f)
+{
+ if (! is_file_with_extension(f, ".repository", IsFileWithOptions()))
+ return;
+
+ Context context("When populating UnavailableRepository from file '" + stringify(f) + "':");
+
+ UnavailableRepositoryFile file(f);
+
+ if (env->package_database()->has_repository_named(RepositoryName(file.repo_name())))
+ {
+ Log::get_instance()->message("unavailable_repository.file.present", ll_debug, lc_context)
+ << "Skipping file '" << f << "' due to present repo_name '" << file.repo_name() << "'";
+ return;
+ }
+
+ if (! _imp->seen_repo_names.insert(file.repo_name()).second)
+ {
+ Log::get_instance()->message("unavailable_repository.file.duplicate", ll_warning, lc_context)
+ << "Skipping file '" << f << "' due to duplicate repo_name '" << file.repo_name() << "'";
+ return;
+ }
+
+ std::tr1::shared_ptr<Mask> mask(new UnavailableMask);
+ std::tr1::shared_ptr<MetadataValueKey<std::string> > owning_repository(
+ new LiteralMetadataValueKey<std::string>("OWNING_REPOSITORY", "Owning repository",
+ mkt_significant, file.repo_name()));
+
+ QualifiedPackageName old_name("x/x");
+ std::tr1::shared_ptr<QualifiedPackageNameSet> pkgs;
+ std::tr1::shared_ptr<PackageIDSequence> ids;
+ for (UnavailableRepositoryFile::ConstIterator i(file.begin()), i_end(file.end()) ;
+ i != i_end ; ++i)
+ {
+ if (old_name.category != (*i)[k::name()].category)
+ {
+ _imp->categories->insert((*i)[k::name()].category);
+ PackageNames::iterator p(_imp->package_names.find((*i)[k::name()].category));
+ if (_imp->package_names.end() == p)
+ p = _imp->package_names.insert(std::make_pair((*i)[k::name()].category,
+ make_shared_ptr(new QualifiedPackageNameSet))).first;
+ pkgs = p->second;
+ }
+
+ if (old_name != (*i)[k::name()])
+ {
+ pkgs->insert((*i)[k::name()]);
+ IDs::iterator p(_imp->ids.find((*i)[k::name()]));
+ if (_imp->ids.end() == p)
+ p = _imp->ids.insert(std::make_pair((*i)[k::name()],
+ make_shared_ptr(new PackageIDSequence))).first;
+
+ ids = p->second;
+ }
+
+ ids->push_back(make_shared_ptr(new UnavailableID(UnavailableIDParams::named_create()
+ (k::repository(), _imp->repo)
+ (k::name(), (*i)[k::name()])
+ (k::version(), (*i)[k::version()])
+ (k::slot(), (*i)[k::slot()])
+ (k::description(), (*i)[k::description()])
+ (k::owning_repository(), owning_repository)
+ (k::mask(), mask)
+ )));
+
+ old_name = (*i)[k::name()];
+ }
+}
+
+bool
+UnavailableRepositoryStore::has_category_named(const CategoryNamePart & c) const
+{
+ return _imp->categories->end() != _imp->categories->find(c);
+}
+
+bool
+UnavailableRepositoryStore::has_package_named(const QualifiedPackageName & q) const
+{
+ return _imp->ids.end() != _imp->ids.find(q);
+}
+
+std::tr1::shared_ptr<const CategoryNamePartSet>
+UnavailableRepositoryStore::category_names() const
+{
+ return _imp->categories;
+}
+
+std::tr1::shared_ptr<const CategoryNamePartSet>
+UnavailableRepositoryStore::unimportant_category_names() const
+{
+ std::tr1::shared_ptr<CategoryNamePartSet> result(make_shared_ptr(new CategoryNamePartSet));
+ result->insert(CategoryNamePart("virtual"));
+ return result;
+}
+
+std::tr1::shared_ptr<const QualifiedPackageNameSet>
+UnavailableRepositoryStore::package_names(const CategoryNamePart & c) const
+{
+ PackageNames::iterator p(_imp->package_names.find(c));
+ if (_imp->package_names.end() == p)
+ return make_shared_ptr(new QualifiedPackageNameSet);
+ else
+ return p->second;
+}
+
+std::tr1::shared_ptr<const PackageIDSequence>
+UnavailableRepositoryStore::package_ids(const QualifiedPackageName & p) const
+{
+ IDs::iterator i(_imp->ids.find(p));
+ if (_imp->ids.end() == i)
+ return make_shared_ptr(new PackageIDSequence);
+ else
+ return i->second;
+}
+
+template class PrivateImplementationPattern<unavailable_repository::UnavailableRepositoryStore>;
+