/* vim: set sw=4 sts=4 et foldmethod=syntax : */ /* * Copyright (c) 2006, 2007, 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace paludis; using namespace paludis::erepository; namespace { template struct FileEntryTraits; template<> struct FileEntryTraits { static const std::string extract_key(const std::string & k) { return k; } }; template struct FileEntryTraits > { static const std::string extract_key(const std::pair & p) { return p.first; } }; template struct MatchesKey { const T_ & _x; explicit MatchesKey(const T_ & x) : _x(x) { } template bool operator() (const U_ & y) { return FileEntryTraits::extract_key(y.second) == _x; } }; } namespace paludis { template struct Imp > { const EAPIForFileFunction eapi_for_file; typedef std::list, const typename std::remove_reference::type> > Lines; Lines lines; std::set removed; Imp(const EAPIForFileFunction & e) : eapi_for_file(e) { } }; template <> struct WrappedForwardIteratorTraits::ConstIteratorTag> { typedef std::list, const std::remove_reference::type> >::const_iterator UnderlyingIterator; }; template <> struct WrappedForwardIteratorTraits::ConstIteratorTag> { typedef std::list, const std::remove_reference::type> >::const_iterator UnderlyingIterator; }; template struct MakeFile { static std::shared_ptr make(const FSPath & p, const LineConfigFileOptions & o, const EAPI & e) { return std::make_shared(p, o, e); } }; template <> struct MakeFile { static std::shared_ptr make(const FSPath & p, const LineConfigFileOptions & o, const EAPI &) { return std::make_shared(p, o); } }; } template void ProfileFile::add_file(const FSPath & f) { Context context("When adding profile configuration file '" + stringify(f) + "':"); if (! f.stat().exists()) return; const std::shared_ptr eapi(EAPIData::get_instance()->eapi_from_string(_imp->eapi_for_file(f))); if (! eapi->supported()) throw ERepositoryConfigurationError("Can't use profile file '" + stringify(f) + "' because it uses an unsupported EAPI"); std::shared_ptr file(MakeFile::make(f, { lcfo_disallow_continuations }, *eapi)); for (typename F_::ConstIterator line(file->begin()), line_end(file->end()) ; line != line_end ; ++line) { const std::string key(FileEntryTraits::type>::extract_key(*line)); if (0 == key.compare(0, 1, "-", 0, 1)) { typename Imp::Lines::iterator i( std::find_if(this->_imp->lines.begin(), this->_imp->lines.end(), MatchesKey(key.substr(1)))); if (this->_imp->lines.end() == i) { /* annoying: Gentoo profiles like to remove the same mask entry * more than once, especially when a particular subprofile * section is inherited more than once. Don't warn when this * happens. */ if (this->_imp->removed.end() == this->_imp->removed.find(key.substr(1))) Log::get_instance()->message("e.profile.no_match", ll_qa, lc_context) << "No match for '" << key << "'. This usually indicates a bug in your profile."; } else { this->_imp->removed.insert(key.substr(1)); while (this->_imp->lines.end() != i) { this->_imp->lines.erase(i++); i = std::find_if(i, this->_imp->lines.end(), MatchesKey(key.substr(1))); } } } else this->_imp->lines.push_back(std::make_pair(eapi, *line)); } } template ProfileFile::ProfileFile(const EAPIForFileFunction & f) : _imp(f) { } template ProfileFile::~ProfileFile() { } template typename ProfileFile::ConstIterator ProfileFile::begin() const { return ConstIterator(this->_imp->lines.begin()); } template typename ProfileFile::ConstIterator ProfileFile::end() const { return ConstIterator(this->_imp->lines.end()); } template class ProfileFile; template class WrappedForwardIterator::ConstIteratorTag, const std::pair< std::shared_ptr, const std::remove_reference::type> >; template class ProfileFile; template class WrappedForwardIterator::ConstIteratorTag, const std::pair< std::shared_ptr, const std::remove_reference::type> >;