Exheredludis/paludis/repositories/unwritten/unwritten_repository.cc
Saleem Abdulrasool 64ba7d5be8 modernize: use default method synthesis
Convert a number of destructors to default synthesized functions.  Try to
inline a few instances into the header.  It should be possible to inline all of
them, however, gcc seems to emit a number of warnings.  Furthermore, some of the
destructors are pure-virtualed, but provide an implementation.  Placing the
definition into the header causes ODR violations.
2016-08-06 11:58:04 -07:00

388 lines
13 KiB
C++

/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
* Copyright (c) 2008, 2009, 2010, 2011, 2013 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/unwritten/unwritten_repository.hh>
#include <paludis/repositories/unwritten/unwritten_repository_store.hh>
#include <paludis/util/pimp-impl.hh>
#include <paludis/util/active_object_ptr.hh>
#include <paludis/util/deferred_construction_ptr.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/tokeniser.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/extract_host_from_url.hh>
#include <paludis/util/fs_stat.hh>
#include <paludis/literal_metadata_key.hh>
#include <paludis/action.hh>
#include <paludis/syncer.hh>
#include <paludis/hook.hh>
#include <vector>
#include <list>
using namespace paludis;
using namespace paludis::unwritten_repository;
namespace
{
std::shared_ptr<UnwrittenRepositoryStore>
make_store(const UnwrittenRepository * const repo, const UnwrittenRepositoryParams & p)
{
return std::make_shared<UnwrittenRepositoryStore>(p.environment(), repo, p.location());
}
}
namespace paludis
{
template <>
struct Imp<UnwrittenRepository>
{
const UnwrittenRepositoryParams params;
const std::shared_ptr<LiteralMetadataValueKey<std::string> > format_key;
const std::shared_ptr<LiteralMetadataValueKey<FSPath> > location_key;
const std::shared_ptr<LiteralMetadataStringStringMapKey> sync_key;
const std::shared_ptr<LiteralMetadataStringStringMapKey> sync_options_key;
const std::shared_ptr<Map<std::string, std::string> > sync_hosts;
const std::shared_ptr<LiteralMetadataStringStringMapKey> sync_host_key;
const ActiveObjectPtr<DeferredConstructionPtr<
std::shared_ptr<UnwrittenRepositoryStore> > > store;
Imp(const UnwrittenRepository * const repo, const UnwrittenRepositoryParams & p) :
params(p),
format_key(std::make_shared<LiteralMetadataValueKey<std::string> >("format", "format",
mkt_significant, "unwritten")),
location_key(std::make_shared<LiteralMetadataValueKey<FSPath> >("location", "location",
mkt_significant, params.location())),
sync_key(std::make_shared<LiteralMetadataStringStringMapKey>(
"sync", "sync", mkt_normal, params.sync())),
sync_options_key(std::make_shared<LiteralMetadataStringStringMapKey>(
"sync_options", "sync_options", mkt_normal, params.sync_options())),
sync_hosts(std::make_shared<Map<std::string, std::string> >()),
sync_host_key(std::make_shared<LiteralMetadataStringStringMapKey>("sync_host", "sync_host", mkt_internal, sync_hosts)),
store(DeferredConstructionPtr<std::shared_ptr<UnwrittenRepositoryStore> > (
std::bind(&make_store, repo, std::cref(params))))
{
for (auto i(params.sync()->begin()), i_end(params.sync()->end()) ;
i != i_end ; ++i)
sync_hosts->insert(i->first, extract_host_from_url(i->second));
}
};
}
UnwrittenRepositoryConfigurationError::UnwrittenRepositoryConfigurationError(const std::string & s) noexcept :
ConfigurationError("UnwrittenRepository configuration error: " + s)
{
}
UnwrittenRepository::UnwrittenRepository(const UnwrittenRepositoryParams & p) :
Repository(
p.environment(),
p.name(),
make_named_values<RepositoryCapabilities>(
n::destination_interface() = static_cast<RepositoryDestinationInterface *>(nullptr),
n::environment_variable_interface() = static_cast<RepositoryEnvironmentVariableInterface *>(nullptr),
n::manifest_interface() = static_cast<RepositoryManifestInterface *>(nullptr)
)),
_imp(this, p)
{
_add_metadata_keys();
}
UnwrittenRepository::~UnwrittenRepository() = default;
const bool
UnwrittenRepository::is_unimportant() const
{
return true;
}
void
UnwrittenRepository::_add_metadata_keys()
{
clear_metadata_keys();
add_metadata_key(_imp->format_key);
add_metadata_key(_imp->location_key);
add_metadata_key(_imp->sync_key);
add_metadata_key(_imp->sync_options_key);
add_metadata_key(_imp->sync_host_key);
}
void
UnwrittenRepository::need_keys_added() const
{
}
const std::shared_ptr<const MetadataValueKey<std::string> >
UnwrittenRepository::format_key() const
{
return _imp->format_key;
}
const std::shared_ptr<const MetadataValueKey<FSPath> >
UnwrittenRepository::location_key() const
{
return _imp->location_key;
}
const std::shared_ptr<const MetadataValueKey<FSPath> >
UnwrittenRepository::installed_root_key() const
{
return std::shared_ptr<const MetadataValueKey<FSPath> >();
}
void
UnwrittenRepository::invalidate()
{
_imp.reset(new Imp<UnwrittenRepository>(this, _imp->params));
_add_metadata_keys();
}
bool
UnwrittenRepository::has_category_named(const CategoryNamePart & c, const RepositoryContentMayExcludes &) const
{
return _imp->store->has_category_named(c);
}
bool
UnwrittenRepository::has_package_named(const QualifiedPackageName & q, const RepositoryContentMayExcludes &) const
{
return _imp->store->has_package_named(q);
}
std::shared_ptr<const CategoryNamePartSet>
UnwrittenRepository::category_names(const RepositoryContentMayExcludes &) const
{
return _imp->store->category_names();
}
std::shared_ptr<const CategoryNamePartSet>
UnwrittenRepository::unimportant_category_names(const RepositoryContentMayExcludes &) const
{
return _imp->store->unimportant_category_names();
}
std::shared_ptr<const CategoryNamePartSet>
UnwrittenRepository::category_names_containing_package(const PackageNamePart & p, const RepositoryContentMayExcludes & x) const
{
return Repository::category_names_containing_package(p, x);
}
std::shared_ptr<const QualifiedPackageNameSet>
UnwrittenRepository::package_names(const CategoryNamePart & c, const RepositoryContentMayExcludes &) const
{
return _imp->store->package_names(c);
}
std::shared_ptr<const PackageIDSequence>
UnwrittenRepository::package_ids(const QualifiedPackageName & p, const RepositoryContentMayExcludes &) const
{
return _imp->store->package_ids(p);
}
bool
UnwrittenRepository::some_ids_might_support_action(const SupportsActionTestBase & a) const
{
return a.make_accept_returning(
[&] (const SupportsActionTest<InstallAction> &) { return true; },
[&] (const SupportsActionTest<FetchAction> &) { return false; },
[&] (const SupportsActionTest<PretendFetchAction> &) { return false; },
[&] (const SupportsActionTest<ConfigAction> &) { return false; },
[&] (const SupportsActionTest<PretendAction> &) { return false; },
[&] (const SupportsActionTest<InfoAction> &) { return false; },
[&] (const SupportsActionTest<UninstallAction> &) { return false; }
);
}
bool
UnwrittenRepository::some_ids_might_not_be_masked() const
{
return false;
}
bool
UnwrittenRepository::sync(
const std::string & source,
const std::string & revision,
const std::shared_ptr<OutputManager> & output_manager) const
{
Context context("When syncing repository '" + stringify(name()) + "':");
std::string sync_uri, sync_options;
if (_imp->params.sync()->end() != _imp->params.sync()->find(source))
sync_uri = _imp->params.sync()->find(source)->second;
if (sync_uri.empty())
return false;
if (_imp->params.sync_options()->end() != _imp->params.sync_options()->find(source))
sync_options = _imp->params.sync_options()->find(source)->second;
std::list<std::string> sync_list;
tokenise_whitespace(sync_uri, std::back_inserter(sync_list));
bool ok(false);
for (std::list<std::string>::const_iterator s(sync_list.begin()),
s_end(sync_list.end()) ; s != s_end ; ++s)
{
DefaultSyncer syncer(make_named_values<SyncerParams>(
n::environment() = _imp->params.environment(),
n::local() = stringify(_imp->params.location()),
n::remote() = *s,
n::revision() = revision
));
SyncOptions opts(make_named_values<SyncOptions>(
n::filter_file() = FSPath("/dev/null"),
n::options() = sync_options,
n::output_manager() = output_manager
));
try
{
syncer.sync(opts);
}
catch (const SyncFailedError &)
{
continue;
}
ok = true;
break;
}
if (! ok)
throw SyncFailedError(stringify(_imp->params.location()), sync_uri);
return true;
}
std::shared_ptr<Repository>
UnwrittenRepository::repository_factory_create(
Environment * const env,
const std::function<std::string (const std::string &)> & f)
{
Context context("When making unwritten repository from repo_file '" + f("repo_file") + "':");
std::string location(f("location"));
if (location.empty())
throw UnwrittenRepositoryConfigurationError("Key 'location' not specified or empty");
FSPath location_path(location);
std::string name_str(f("name"));
if (name_str.empty() && location_path.stat().exists())
{
auto info(UnwrittenRepositoryStore::repository_information(location_path));
name_str = info.name();
}
if (name_str.empty())
name_str = "x-" + FSPath(f("location")).basename();
auto sync(std::make_shared<Map<std::string, std::string> >());
std::vector<std::string> sync_tokens;
tokenise_whitespace(f("sync"), std::back_inserter(sync_tokens));
std::string source;
for (auto & sync_token : sync_tokens)
if ((! sync_token.empty()) && (':' == sync_token.at(sync_token.length() - 1)))
source = sync_token.substr(0, sync_token.length() - 1);
else
{
std::string v;
if (sync->end() != sync->find(source))
v = sync->find(source)->second + " ";
sync->erase(source);
sync->insert(source, v + sync_token);
}
auto sync_options(std::make_shared<Map<std::string, std::string> >());
std::vector<std::string> sync_options_tokens;
tokenise_whitespace(f("sync_options"), std::back_inserter(sync_options_tokens));
source = "";
for (auto & sync_options_token : sync_options_tokens)
if ((! sync_options_token.empty()) && (':' == sync_options_token.at(sync_options_token.length() - 1)))
source = sync_options_token.substr(0, sync_options_token.length() - 1);
else
{
std::string v;
if (sync_options->end() != sync_options->find(source))
v = sync_options->find(source)->second + " ";
sync_options->erase(source);
sync_options->insert(source, v + sync_options_token);
}
return std::make_shared<UnwrittenRepository>(
make_named_values<UnwrittenRepositoryParams>(
n::environment() = env,
n::location() = location,
n::name() = RepositoryName(name_str),
n::sync() = sync,
n::sync_options() = sync_options
));
}
RepositoryName
UnwrittenRepository::repository_factory_name(
const Environment * const,
const std::function<std::string (const std::string &)> & f)
{
if (f("name").empty())
{
UnwrittenRepositoryInformation info(UnwrittenRepositoryStore::repository_information(FSPath(f("location"))));
return RepositoryName(info.name());
}
else
return RepositoryName(f("name"));
}
std::shared_ptr<const RepositoryNameSet>
UnwrittenRepository::repository_factory_dependencies(
const Environment * const,
const std::function<std::string (const std::string &)> &)
{
return std::make_shared<RepositoryNameSet>();
}
void
UnwrittenRepository::populate_sets() const
{
}
HookResult
UnwrittenRepository::perform_hook(const Hook &, const std::shared_ptr<OutputManager> &)
{
return make_named_values<HookResult>(n::max_exit_status() = 0, n::output() = "");
}
const std::shared_ptr<const MetadataCollectionKey<Map<std::string, std::string> > >
UnwrittenRepository::sync_host_key() const
{
return _imp->sync_host_key;
}
const std::shared_ptr<const Set<std::string> >
UnwrittenRepository::maybe_expand_licence_nonrecursively(const std::string &) const
{
return nullptr;
}
namespace paludis
{
template class Pimp<unwritten_repository::UnwrittenRepository>;
}