Exheredludis/paludis/repositories/unwritten/unwritten_repository_file.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

386 lines
15 KiB
C++

/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
* Copyright (c) 2008, 2009, 2010, 2011 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_file.hh>
#include <paludis/repositories/unwritten/unwritten_repository.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/log.hh>
#include <paludis/util/simple_parser.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/tokeniser.hh>
#include <paludis/util/join.hh>
#include <paludis/util/safe_ifstream.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
#include <paludis/name.hh>
#include <paludis/version_spec.hh>
#include <paludis/literal_metadata_key.hh>
#include <paludis/metadata_key-fwd.hh>
#include <paludis/dep_spec.hh>
#include <paludis/user_dep_spec.hh>
#include <paludis/spec_tree.hh>
#include <paludis/pretty_printer.hh>
#include <paludis/slot.hh>
#include <paludis/util/pimp-impl.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
#include <paludis/util/indirect_iterator-impl.hh>
#include <list>
#include <algorithm>
using namespace paludis;
using namespace paludis::unwritten_repository;
typedef std::list<UnwrittenRepositoryFileEntry> Entries;
namespace paludis
{
template <>
struct Imp<UnwrittenRepositoryFile>
{
Entries entries;
};
template <>
struct WrappedForwardIteratorTraits<UnwrittenRepositoryFile::ConstIteratorTag>
{
typedef Entries::const_iterator UnderlyingIterator;
};
}
UnwrittenRepositoryFile::UnwrittenRepositoryFile(const FSPath & f) :
_imp()
{
_load(f);
}
UnwrittenRepositoryFile::~UnwrittenRepositoryFile() = default;
UnwrittenRepositoryFile::ConstIterator
UnwrittenRepositoryFile::begin() const
{
return ConstIterator(_imp->entries.begin());
}
UnwrittenRepositoryFile::ConstIterator
UnwrittenRepositoryFile::end() const
{
return ConstIterator(_imp->entries.end());
}
namespace
{
struct UnwrittenHomepagePrettyPrinter
{
std::stringstream s;
const PrettyPrinter & pretty_printer;
UnwrittenHomepagePrettyPrinter(const PrettyPrinter & p) :
pretty_printer(p)
{
}
void visit(const SimpleURISpecTree::NodeType<AllDepSpec>::Type & node)
{
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
}
void visit(const SimpleURISpecTree::NodeType<ConditionalDepSpec>::Type & node)
{
std::for_each(indirect_iterator(node.begin()), indirect_iterator(node.end()), accept_visitor(*this));
}
void visit(const SimpleURISpecTree::NodeType<SimpleURIDepSpec>::Type & node)
{
if (! s.str().empty())
s << " ";
s << pretty_printer.prettify(*node.spec());
}
};
struct UnwrittenHomepageKey :
MetadataSpecTreeKey<SimpleURISpecTree>
{
const std::shared_ptr<const SimpleURISpecTree> vv;
const std::string _raw_name;
const std::string _human_name;
const MetadataKeyType _type;
UnwrittenHomepageKey(const std::string & r, const std::string & h, const MetadataKeyType t,
const std::shared_ptr<const SimpleURISpecTree> & v) :
vv(v),
_raw_name(r),
_human_name(h),
_type(t)
{
}
const std::shared_ptr<const SimpleURISpecTree> parse_value() const override
{
return vv;
}
const std::string raw_name() const override PALUDIS_ATTRIBUTE((warn_unused_result))
{
return _raw_name;
}
const std::string human_name() const override PALUDIS_ATTRIBUTE((warn_unused_result))
{
return _human_name;
}
MetadataKeyType type() const override PALUDIS_ATTRIBUTE((warn_unused_result))
{
return _type;
}
const std::string pretty_print_value(
const PrettyPrinter & pretty_printer,
const PrettyPrintOptions &) const override
{
UnwrittenHomepagePrettyPrinter p(pretty_printer);
parse_value()->top()->accept(p);
return p.s.str();
}
};
}
void
UnwrittenRepositoryFile::_load(const FSPath & f)
{
SafeIFStream file(f);
std::string line;
while (std::getline(file, line))
{
if (line.empty())
break;
std::string key, value;
SimpleParser line_parser(line);
if (line_parser.consume(
(+simple_parser::any_except(" \t") >> key) &
(*simple_parser::any_of(" \t")) &
(simple_parser::exact("=")) &
(*simple_parser::any_of(" \t")) &
(*simple_parser::any_except("") >> value)
))
{
if (key == "format")
{
if (value != "unwritten-1")
throw UnwrittenRepositoryConfigurationError(
"Unsupported format '" + value + "' in '" + stringify(f) + "'");
}
else
Log::get_instance()->message("unwritten_repository.file.unknown_key", ll_warning, lc_context)
<< "Ignoring unknown key '" << key << "' with value '" << value << "'";
}
else
throw UnwrittenRepositoryConfigurationError(
"Cannot parse header line '" + line + "' in '" + stringify(f) + "'");
}
CategoryNamePart category("x");
PackageNamePart package("x");
std::shared_ptr<MetadataValueKey<Slot> > slot;
std::list<VersionSpec> versions;
std::shared_ptr<UnwrittenRepositoryFileEntry> entry;
while (std::getline(file, line))
{
SimpleParser line_parser(line);
std::string token, token2;
if (line.empty())
{
}
else if (line_parser.consume(
(*simple_parser::any_of(" \t")) &
(simple_parser::exact("#")) &
(*simple_parser::any_except(""))))
{
}
else if (line_parser.consume(
(+simple_parser::any_except(" \t/") >> token) &
(simple_parser::exact("/"))
))
{
if (! line_parser.eof())
throw UnwrittenRepositoryConfigurationError(
"Cannot parse body category line '" + line + "' in '" + stringify(f) + "'");
category = CategoryNamePart(token);
}
else if (line_parser.consume(
(+simple_parser::any_of(" \t")) &
(+simple_parser::any_except(" \t/") >> token) &
(simple_parser::exact("/"))
))
{
if (! line_parser.eof())
throw UnwrittenRepositoryConfigurationError(
"Cannot parse body package line '" + line + " in '" + stringify(f) + "'");
package = PackageNamePart(token);
}
else if (line_parser.consume(
(+simple_parser::any_of(" \t")) &
(+simple_parser::exact(":")) &
(+simple_parser::any_except(" \t") >> token) &
(+simple_parser::any_of(" \t"))
))
{
slot = std::make_shared<LiteralMetadataValueKey<Slot>>("SLOT", "Slot", mkt_internal, make_named_values<Slot>(
n::match_values() = std::make_pair(SlotName(token), SlotName(token)),
n::parallel_value() = SlotName(token),
n::raw_value() = token));
if (entry)
{
for (std::list<VersionSpec>::const_iterator v(versions.begin()), v_end(versions.end()) ;
v != v_end ; ++v)
{
entry->version() = *v;
_imp->entries.push_back(*entry);
}
versions.clear();
entry.reset();
}
while (! line_parser.eof())
{
if (line_parser.consume(
(+simple_parser::any_except(" \t") >> token) &
(*simple_parser::any_of(" \t"))
))
versions.push_back(VersionSpec(token, user_version_spec_options()));
else
throw UnwrittenRepositoryConfigurationError(
"Cannot parse body slot+version line '" + line + " in '" + stringify(f) + "'");
}
if (versions.empty())
throw UnwrittenRepositoryConfigurationError(
"Cannot parse body slot+version line '" + line + " in '" + stringify(f) + "'");
}
else if (line_parser.consume(
(+simple_parser::any_of(" \t")) &
(+simple_parser::any_except(" \t") >> token) &
(+simple_parser::any_of(" \t")) &
(+simple_parser::exact("=")) &
(+simple_parser::any_of(" \t")) &
(+simple_parser::any_except("") >> token2)
))
{
if (! line_parser.eof())
throw UnwrittenRepositoryConfigurationError(
"Cannot parse body key = value line '" + line + " in '" + stringify(f) + "'");
if (! entry)
entry = std::make_shared<UnwrittenRepositoryFileEntry>(make_named_values<UnwrittenRepositoryFileEntry>(
n::added_by() = std::shared_ptr<const MetadataValueKey<std::string> >(),
n::bug_ids() = std::shared_ptr<const MetadataCollectionKey<Sequence<std::string> > >(),
n::comment() = std::shared_ptr<const MetadataValueKey<std::string> >(),
n::commit_id() = std::shared_ptr<const MetadataValueKey<std::string> >(),
n::description() = std::shared_ptr<const MetadataValueKey<std::string> >(),
n::homepage() = std::shared_ptr<const MetadataSpecTreeKey<SimpleURISpecTree> >(),
n::name() = category + package,
n::remote_ids() = std::shared_ptr<const MetadataCollectionKey<Sequence<std::string> > >(),
n::removed_by() = std::shared_ptr<const MetadataValueKey<std::string> >(),
n::removed_from() = std::shared_ptr<const MetadataCollectionKey<Set<std::string> > >(),
n::slot() = slot,
n::version() = VersionSpec("0", { })
));
if (token == "description")
entry->description() = std::make_shared<LiteralMetadataValueKey<std::string>>("description", "Description", mkt_significant, token2);
else if (token == "homepage")
{
std::shared_ptr<AllDepSpec> all_spec(std::make_shared<AllDepSpec>());
std::shared_ptr<SimpleURISpecTree> tree(std::make_shared<SimpleURISpecTree>(all_spec));
std::list<std::string> tokens;
tokenise_whitespace(token2, std::back_inserter(tokens));
for (std::list<std::string>::const_iterator t(tokens.begin()), t_end(tokens.end()) ;
t != t_end ; ++t)
tree->top()->append(std::make_shared<SimpleURIDepSpec>(*t));
entry->homepage() = std::make_shared<UnwrittenHomepageKey>("homepage", "Homepage", mkt_normal, tree);
}
else if (token == "comment")
entry->comment() = std::make_shared<LiteralMetadataValueKey<std::string>>("comment", "Comment", mkt_normal, token2);
else if (token == "commit-id")
entry->commit_id() = std::make_shared<LiteralMetadataValueKey<std::string>>("commit-id", "Commit ID", mkt_normal, token2);
else if (token == "added-by")
entry->added_by() = std::make_shared<LiteralMetadataValueKey<std::string>>("added-by", "Added by", mkt_author, token2);
else if (token == "removed-by")
entry->removed_by() = std::make_shared<LiteralMetadataValueKey<std::string>>("removed-by", "Removed by", mkt_author, token2);
else if (token == "removed-from")
{
auto t2s(std::make_shared<Set<std::string> >());
t2s->insert(token2);
entry->removed_from() = std::make_shared<LiteralMetadataStringSetKey>("removed-from", "Removed from", mkt_author, t2s);
}
else if (token == "bug-ids")
{
std::shared_ptr<Sequence<std::string> > seq(std::make_shared<Sequence<std::string>>());
std::list<std::string> tokens;
tokenise_whitespace(token2, std::back_inserter(tokens));
for (std::list<std::string>::const_iterator t(tokens.begin()), t_end(tokens.end()) ;
t != t_end ; ++t)
seq->push_back(*t);
entry->bug_ids() = std::make_shared<LiteralMetadataStringSequenceKey>("bug-ids", "Bug IDs", mkt_normal, seq);
}
else if (token == "remote-ids")
{
std::shared_ptr<Sequence<std::string> > seq(std::make_shared<Sequence<std::string>>());
std::list<std::string> tokens;
tokenise_whitespace(token2, std::back_inserter(tokens));
for (std::list<std::string>::const_iterator t(tokens.begin()), t_end(tokens.end()) ;
t != t_end ; ++t)
seq->push_back(*t);
entry->remote_ids() = std::make_shared<LiteralMetadataStringSequenceKey>("remote-ids", "Remote IDs", mkt_internal, seq);
}
else
Log::get_instance()->message("unwritten_repository.file.unknown_key", ll_warning, lc_context)
<< "Ignoring unknown key '" << token << "' with value '" << token2 << "'";
}
else
throw UnwrittenRepositoryConfigurationError(
"Cannot parse body line '" + line + " in '" + stringify(f) + "'");
}
if (entry)
{
for (std::list<VersionSpec>::const_iterator v(versions.begin()), v_end(versions.end()) ;
v != v_end ; ++v)
{
entry->version() = *v;
_imp->entries.push_back(*entry);
}
}
}
namespace paludis
{
template class Pimp<UnwrittenRepositoryFile>;
template class WrappedForwardIterator<UnwrittenRepositoryFile::ConstIteratorTag,
const UnwrittenRepositoryFileEntry>;
}