aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-08-17 15:45:45 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-08-17 15:45:45 +0000
commitbce62404a274d2d9797db913c33d6c1d2c388631 (patch)
treeff093299f62586483e60f325d1d9a2035fb018ce
parentcdd0e851ec4aa0adf9311fc69d8f54e9957b5d8a (diff)
downloadpaludis-bce62404a274d2d9797db913c33d6c1d2c388631.tar.gz
paludis-bce62404a274d2d9797db913c33d6c1d2c388631.tar.xz
More QA work
-rw-r--r--paludis/repositories/e/e_repository.cc3
-rw-r--r--paludis/repositories/e/e_repository_profile.cc6
-rw-r--r--paludis/repositories/e/e_repository_profile.hh2
-rw-r--r--paludis/repositories/e/qa/Makefile.am27
-rw-r--r--paludis/repositories/e/qa/extractors.cc2
-rw-r--r--paludis/repositories/e/qa/homepage_key.cc3
-rw-r--r--paludis/repositories/e/qa/qa_checks.cc14
-rw-r--r--paludis/repositories/e/qa/qa_checks.hh26
-rw-r--r--paludis/repositories/e/qa/qa_checks_group.cc1
-rw-r--r--paludis/repositories/e/qa/qa_controller.cc38
-rw-r--r--paludis/repositories/e/qa/short_description_key.cc3
-rw-r--r--paludis/repositories/e/qa/spec_keys.cc22
-rw-r--r--paludis/repositories/e/qa/stray_files.cc4
-rw-r--r--paludis/repositories/e/qa/visibility.cc345
-rw-r--r--paludis/repositories/e/qa/visibility.hh45
-rw-r--r--paludis/repositories/e/qa/visibility_TEST.cc113
-rwxr-xr-xpaludis/repositories/e/qa/visibility_TEST_cleanup.sh9
-rwxr-xr-xpaludis/repositories/e/qa/visibility_TEST_setup.sh62
-rw-r--r--src/clients/qualudis/qualudis.cc31
19 files changed, 716 insertions, 40 deletions
diff --git a/paludis/repositories/e/e_repository.cc b/paludis/repositories/e/e_repository.cc
index fabb382..1091752 100644
--- a/paludis/repositories/e/e_repository.cc
+++ b/paludis/repositories/e/e_repository.cc
@@ -203,6 +203,9 @@ namespace paludis
void
Implementation<ERepository>::need_profiles_desc() const
{
+ if (has_profiles_desc)
+ return;
+
Lock l(mutexes->profiles_desc_mutex);
if (has_profiles_desc)
diff --git a/paludis/repositories/e/e_repository_profile.cc b/paludis/repositories/e/e_repository_profile.cc
index 1a98a3b..27c4993 100644
--- a/paludis/repositories/e/e_repository_profile.cc
+++ b/paludis/repositories/e/e_repository_profile.cc
@@ -770,6 +770,12 @@ ERepositoryProfile::begin_virtuals() const
}
ERepositoryProfile::VirtualsIterator
+ERepositoryProfile::find_virtual(const QualifiedPackageName & n) const
+{
+ return VirtualsIterator(_imp->virtuals.find(n));
+}
+
+ERepositoryProfile::VirtualsIterator
ERepositoryProfile::end_virtuals() const
{
return VirtualsIterator(_imp->virtuals.end());
diff --git a/paludis/repositories/e/e_repository_profile.hh b/paludis/repositories/e/e_repository_profile.hh
index eca2951..64d8c84 100644
--- a/paludis/repositories/e/e_repository_profile.hh
+++ b/paludis/repositories/e/e_repository_profile.hh
@@ -123,7 +123,7 @@ namespace paludis
VirtualsIterator begin_virtuals() const;
VirtualsIterator end_virtuals() const;
- VirtualsIterator find_virtual() const;
+ VirtualsIterator find_virtual(const QualifiedPackageName &) const;
///\}
};
diff --git a/paludis/repositories/e/qa/Makefile.am b/paludis/repositories/e/qa/Makefile.am
index 5d19292..477f500 100644
--- a/paludis/repositories/e/qa/Makefile.am
+++ b/paludis/repositories/e/qa/Makefile.am
@@ -32,7 +32,8 @@ paludis_repositories_e_include_HEADERS = \
qa_checks_group.hh \
qa_controller.hh \
short_description_key.hh \
- stray_files.hh
+ stray_files.hh \
+ visibility.hh
lib_LTLIBRARIES = libpaludiserepositoryqa.la
@@ -47,6 +48,7 @@ libpaludiserepositoryqa_la_SOURCES = \
short_description_key.cc \
spec_keys.cc \
stray_files.cc \
+ visibility.cc \
$(paludis_repositories_e_include_HEADERS)
libpaludiserepositoryqa_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
@@ -55,13 +57,15 @@ libpaludiserepositoryqa_la_LIBADD = \
$(top_builddir)/paludis/libpaludis.la \
$(top_builddir)/paludis/util/libpaludisutil.la
+dist_check_SCRIPTS = \
+ visibility_TEST_setup.sh \
+ visibility_TEST_cleanup.sh
+
endif
-EXTRA_DIST = test_extras.cc
+EXTRA_DIST = test_extras.cc $(check_SCRIPTS)
BUILT_SOURCES =
-check_SCRIPTS =
-
TESTS_ENVIRONMENT = env \
TEST_OUTPUT_WRAPPER="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/outputwrapper`" \
PALUDIS_OUTPUTWRAPPER_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/`" \
@@ -83,7 +87,8 @@ if ENABLE_QA
TESTS = \
extractors_TEST \
spec_keys_TEST \
- stray_files_TEST
+ stray_files_TEST \
+ visibility_TEST
check_PROGRAMS = $(TESTS)
@@ -123,6 +128,18 @@ extractors_TEST_LDADD = \
$(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
$(top_builddir)/test/libtest.a
+visibility_TEST_SOURCES = visibility_TEST.cc
+visibility_TEST_LDADD = \
+ libpaludiserepositoryqa.la \
+ test_extras.o \
+ $(top_builddir)/paludis/repositories/e/libpaludiserepository.la \
+ $(top_builddir)/paludis/repositories/fake/libpaludisfakerepository.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a
+
endif
built-sources : $(BUILT_SOURCES)
diff --git a/paludis/repositories/e/qa/extractors.cc b/paludis/repositories/e/qa/extractors.cc
index 838da81..89b6666 100644
--- a/paludis/repositories/e/qa/extractors.cc
+++ b/paludis/repositories/e/qa/extractors.cc
@@ -219,6 +219,8 @@ paludis::erepository::extractors_check(
const std::string & name)
{
Context context("When performing check '" + name + "' on ID '" + stringify(*id) + "':");
+ Log::get_instance()->message(ll_debug, lc_context) << "extractors_check '"
+ << entry << "', " << *id << "', " << name << "'";
if (id->src_uri_key())
{
diff --git a/paludis/repositories/e/qa/homepage_key.cc b/paludis/repositories/e/qa/homepage_key.cc
index 3c66d45..f3a9114 100644
--- a/paludis/repositories/e/qa/homepage_key.cc
+++ b/paludis/repositories/e/qa/homepage_key.cc
@@ -22,6 +22,7 @@
#include <paludis/metadata_key.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/log.hh>
#include <paludis/name.hh>
#include <paludis/dep_spec.hh>
#include <paludis/package_id.hh>
@@ -94,6 +95,8 @@ paludis::erepository::homepage_key_check(
const std::string & name)
{
Context context("When performing check '" + name + "' using homepage_key_check on ID '" + stringify(*id) + "':");
+ Log::get_instance()->message(ll_debug, lc_context) << "homepage_key_check '"
+ << entry << "', " << *id << "', " << name << "'";
if (! id->homepage_key())
reporter.message(QAMessage(entry, qaml_normal, name, "No homepage available"));
diff --git a/paludis/repositories/e/qa/qa_checks.cc b/paludis/repositories/e/qa/qa_checks.cc
index e283b25..25c60f4 100644
--- a/paludis/repositories/e/qa/qa_checks.cc
+++ b/paludis/repositories/e/qa/qa_checks.cc
@@ -27,6 +27,7 @@
#include <paludis/repositories/e/qa/homepage_key.hh>
#include <paludis/repositories/e/qa/spec_keys.hh>
#include <paludis/repositories/e/qa/extractors.hh>
+#include <paludis/repositories/e/qa/visibility.hh>
using namespace paludis;
using namespace paludis::erepository;
@@ -41,11 +42,13 @@ namespace paludis
const tr1::shared_ptr<QAChecksGroup<TreeCheckFunction> > tree_checks_group;
const tr1::shared_ptr<QAChecksGroup<CategoryDirCheckFunction> > category_dir_checks_group;
const tr1::shared_ptr<QAChecksGroup<PackageIDCheckFunction> > package_id_checks_group;
+ const tr1::shared_ptr<QAChecksGroup<PerProfilePackageIDCheckFunction> > per_profile_package_id_checks_group;
Implementation() :
tree_checks_group(new QAChecksGroup<TreeCheckFunction>),
category_dir_checks_group(new QAChecksGroup<CategoryDirCheckFunction>),
- package_id_checks_group(new QAChecksGroup<PackageIDCheckFunction>)
+ package_id_checks_group(new QAChecksGroup<PackageIDCheckFunction>),
+ per_profile_package_id_checks_group(new QAChecksGroup<PerProfilePackageIDCheckFunction>)
{
}
};
@@ -80,6 +83,9 @@ QAChecks::QAChecks() :
_imp->package_id_checks_group->add_check("extractors",
tr1::bind(extractors_check, _1, _2, _5, "extractors"));
_imp->package_id_checks_group->add_prerequirement("extractors", "eapi_supported");
+
+ _imp->per_profile_package_id_checks_group->add_check("visibility",
+ tr1::bind(visibility_check, _1, _2, _3, _4, _5, _6, "visibility"));
}
QAChecks::~QAChecks()
@@ -104,3 +110,9 @@ QAChecks::package_id_checks_group()
return _imp->package_id_checks_group;
}
+const tr1::shared_ptr<QAChecksGroup<PerProfilePackageIDCheckFunction> >
+QAChecks::per_profile_package_id_checks_group()
+{
+ return _imp->per_profile_package_id_checks_group;
+}
+
diff --git a/paludis/repositories/e/qa/qa_checks.hh b/paludis/repositories/e/qa/qa_checks.hh
index b45ca67..aeb6f92 100644
--- a/paludis/repositories/e/qa/qa_checks.hh
+++ b/paludis/repositories/e/qa/qa_checks.hh
@@ -33,11 +33,10 @@
#include <paludis/repositories/e/qa/qa_checks_group.hh>
#include <paludis/repositories/e/e_repository_id.hh>
+#include <paludis/repositories/e/e_repository.hh>
namespace paludis
{
- class ERepository;
-
namespace erepository
{
typedef tr1::function<bool (
@@ -64,6 +63,15 @@ namespace paludis
const tr1::shared_ptr<const ERepositoryID> &
)> PackageIDCheckFunction;
+ typedef tr1::function<bool (
+ const FSEntry &,
+ QAReporter &,
+ const Environment * const,
+ const tr1::shared_ptr<const ERepository> &,
+ const tr1::shared_ptr<const ERepositoryID> &,
+ const ERepository::ProfilesIterator &
+ )> PerProfilePackageIDCheckFunction;
+
class QAChecks :
private PrivateImplementationPattern<QAChecks>,
public InstantiationPolicy<QAChecks, instantiation_method::SingletonTag>
@@ -75,9 +83,17 @@ namespace paludis
~QAChecks();
public:
- const tr1::shared_ptr<QAChecksGroup<TreeCheckFunction> > tree_checks_group() PALUDIS_ATTRIBUTE((warn_unused_result));
- const tr1::shared_ptr<QAChecksGroup<CategoryDirCheckFunction> > category_dir_checks_group() PALUDIS_ATTRIBUTE((warn_unused_result));
- const tr1::shared_ptr<QAChecksGroup<PackageIDCheckFunction> > package_id_checks_group() PALUDIS_ATTRIBUTE((warn_unused_result));
+ const tr1::shared_ptr<QAChecksGroup<TreeCheckFunction> >
+ tree_checks_group() PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const tr1::shared_ptr<QAChecksGroup<CategoryDirCheckFunction> >
+ category_dir_checks_group() PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const tr1::shared_ptr<QAChecksGroup<PackageIDCheckFunction> >
+ package_id_checks_group() PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const tr1::shared_ptr<QAChecksGroup<PerProfilePackageIDCheckFunction> >
+ per_profile_package_id_checks_group() PALUDIS_ATTRIBUTE((warn_unused_result));
};
}
}
diff --git a/paludis/repositories/e/qa/qa_checks_group.cc b/paludis/repositories/e/qa/qa_checks_group.cc
index d2f8111..7b3f7e5 100644
--- a/paludis/repositories/e/qa/qa_checks_group.cc
+++ b/paludis/repositories/e/qa/qa_checks_group.cc
@@ -115,4 +115,5 @@ QAChecksGroup<T_>::need_ordering() const
template class QAChecksGroup<TreeCheckFunction>;
template class QAChecksGroup<PackageIDCheckFunction>;
+template class QAChecksGroup<PerProfilePackageIDCheckFunction>;
diff --git a/paludis/repositories/e/qa/qa_controller.cc b/paludis/repositories/e/qa/qa_controller.cc
index d7c7918..3dab366 100644
--- a/paludis/repositories/e/qa/qa_controller.cc
+++ b/paludis/repositories/e/qa/qa_controller.cc
@@ -149,8 +149,8 @@ QAController::_run_category(const CategoryNamePart & c)
QAChecks::get_instance()->category_dir_checks_group()->end(),
tr1::bind(std::equal_to<bool>(), false,
tr1::bind<bool>(tr1::mem_fn(&CategoryDirCheckFunction::operator() ),
- _1, _imp->repo->layout()->category_directory(c),
- tr1::ref(_imp->reporter), _imp->env, _imp->repo, _imp->repo->layout()->category_directory(c))));
+ _1, _imp->repo->layout()->category_directory(c), tr1::ref(_imp->reporter),
+ _imp->env, _imp->repo, _imp->repo->layout()->category_directory(c))));
}
catch (const Exception & e)
{
@@ -181,13 +181,27 @@ QAController::_run_id(const tr1::shared_ptr<const PackageID> & i)
using namespace tr1::placeholders;
try
{
- std::find_if(
- QAChecks::get_instance()->package_id_checks_group()->begin(),
- QAChecks::get_instance()->package_id_checks_group()->end(),
- tr1::bind(std::equal_to<bool>(), false,
- tr1::bind<bool>(tr1::mem_fn(&PackageIDCheckFunction::operator() ),
- _1, _imp->repo->layout()->package_file(*i),
- tr1::ref(_imp->reporter), _imp->env, _imp->repo, tr1::static_pointer_cast<const ERepositoryID>(i))));
+ if (QAChecks::get_instance()->package_id_checks_group()->end() ==
+ std::find_if(
+ QAChecks::get_instance()->package_id_checks_group()->begin(),
+ QAChecks::get_instance()->package_id_checks_group()->end(),
+ tr1::bind(std::equal_to<bool>(), false,
+ tr1::bind<bool>(tr1::mem_fn(&PackageIDCheckFunction::operator() ),
+ _1, _imp->repo->layout()->package_file(*i), tr1::ref(_imp->reporter),
+ _imp->env, _imp->repo, tr1::static_pointer_cast<const ERepositoryID>(i)))))
+ {
+ for (ERepository::ProfilesIterator p(_imp->repo->begin_profiles()), p_end(_imp->repo->end_profiles()) ;
+ p != p_end ; ++p)
+ {
+ std::find_if(
+ QAChecks::get_instance()->per_profile_package_id_checks_group()->begin(),
+ QAChecks::get_instance()->per_profile_package_id_checks_group()->end(),
+ tr1::bind(std::equal_to<bool>(), false,
+ tr1::bind<bool>(tr1::mem_fn(&PerProfilePackageIDCheckFunction::operator() ),
+ _1, _imp->repo->layout()->package_file(*i), tr1::ref(_imp->reporter),
+ _imp->env, _imp->repo, tr1::static_pointer_cast<const ERepositoryID>(i), p)));
+ }
+ }
}
catch (const Exception & e)
{
@@ -208,9 +222,9 @@ QAController::run()
QAChecks::get_instance()->tree_checks_group()->begin(),
QAChecks::get_instance()->tree_checks_group()->end(),
tr1::bind(std::equal_to<bool>(), false,
- tr1::bind<bool>(tr1::mem_fn(&TreeCheckFunction::operator() ),
- _1, _imp->repo->params().location,
- tr1::ref(_imp->reporter), _imp->env, _imp->repo, _imp->repo->params().location)));
+ tr1::bind<bool>(tr1::mem_fn(&CategoryDirCheckFunction::operator() ),
+ _1, _imp->repo->params().location, tr1::ref(_imp->reporter),
+ _imp->env, _imp->repo, _imp->repo->params().location)));
}
catch (const Exception & e)
{
diff --git a/paludis/repositories/e/qa/short_description_key.cc b/paludis/repositories/e/qa/short_description_key.cc
index b493162..553f174 100644
--- a/paludis/repositories/e/qa/short_description_key.cc
+++ b/paludis/repositories/e/qa/short_description_key.cc
@@ -21,6 +21,7 @@
#include <paludis/qa.hh>
#include <paludis/metadata_key.hh>
#include <paludis/util/stringify.hh>
+#include <paludis/util/log.hh>
#include <paludis/name.hh>
bool
@@ -31,6 +32,8 @@ paludis::erepository::short_description_key_check(
const std::string & name)
{
Context context("When performing check '" + name + "' using short_description_key_check on ID '" + stringify(*id) + "':");
+ Log::get_instance()->message(ll_debug, lc_context) << "short_description_key_check '"
+ << entry << "', " << *id << "', " << name << "'";
if (! id->short_description_key())
reporter.message(QAMessage(entry, qaml_normal, name, "No description available"));
diff --git a/paludis/repositories/e/qa/spec_keys.cc b/paludis/repositories/e/qa/spec_keys.cc
index 90e5d63..ef793ea 100644
--- a/paludis/repositories/e/qa/spec_keys.cc
+++ b/paludis/repositories/e/qa/spec_keys.cc
@@ -118,16 +118,16 @@ namespace
if (pds_blacklist && p.package_ptr())
{
if (pds_blacklist->end() != pds_blacklist->find(*p.package_ptr()))
- reporter.message(QAMessage(entry, qaml_normal, name, "Package specification '" + stringify(p)
- + "' blacklisted in spec key '" + stringify(key.raw_name()) + "'"));
+ reporter.message(QAMessage(entry, qaml_normal, name, "Package '" + stringify(p)
+ + "' blacklisted in '" + stringify(key.raw_name()) + "'"));
}
}
void visit_leaf(const BlockDepSpec & b)
{
if (child_of_any)
- reporter.message(QAMessage(entry, qaml_normal, name, "'|| ( )' block with block child '!"
- + stringify(*b.blocked_spec()) + "' in spec key '" + stringify(key.raw_name()) + "'"));
+ reporter.message(QAMessage(entry, qaml_normal, name, "'|| ( )' with block child '!"
+ + stringify(*b.blocked_spec()) + "' in '" + stringify(key.raw_name()) + "'"));
}
void visit_leaf(const URIDepSpec &)
@@ -148,12 +148,12 @@ namespace
{
if (child_of_any)
reporter.message(QAMessage(entry, qaml_normal, name,
- "'|| ( )' block with 'use? ( )' child in spec key '"
+ "'|| ( )' with 'use? ( )' child in '"
+ stringify(key.raw_name()) + "'"));
if (uses.count(u.flag()))
reporter.message(QAMessage(entry, qaml_normal, name,
- "Recursive use of flag '" + stringify(u.flag()) + "' in spec key '"
+ "Recursive use of flag '" + stringify(u.flag()) + "' in '"
+ stringify(key.raw_name()) + "'"));
Save<unsigned> save_level(&level, level + 1);
@@ -162,7 +162,7 @@ namespace
uses.insert(u.flag());
if (cur == end)
reporter.message(QAMessage(entry, qaml_normal, name,
- "Empty 'use? ( )' block in spec key '" + stringify(key.raw_name()) + "'"));
+ "Empty 'use? ( )' in '" + stringify(key.raw_name()) + "'"));
else
std::for_each(cur, end, accept_visitor(*this));
}
@@ -177,7 +177,7 @@ namespace
{
if (level > 1)
reporter.message(QAMessage(entry, qaml_normal, name,
- "Empty '( )' block in spec key '" + stringify(key.raw_name()) + "'"));
+ "Empty '( )' in '" + stringify(key.raw_name()) + "'"));
}
else
std::for_each(cur, end, accept_visitor(*this));
@@ -191,12 +191,12 @@ namespace
Save<bool> save_child_of_any(&child_of_any, true);
if (cur == end)
reporter.message(QAMessage(entry, qaml_normal, name,
- "Empty '|| ( )' block in spec key '" + stringify(key.raw_name()) + "'"));
+ "Empty '|| ( )' in '" + stringify(key.raw_name()) + "'"));
else if (next(cur) == end)
{
cur->accept(*this);
reporter.message(QAMessage(entry, qaml_normal, name,
- "'|| ( )' block with only one child in spec key '" + stringify(key.raw_name()) + "'"));
+ "'|| ( )' with only one child in '" + stringify(key.raw_name()) + "'"));
}
else
std::for_each(cur, end, accept_visitor(*this));
@@ -348,6 +348,8 @@ paludis::erepository::spec_keys_check(
const std::string & name)
{
Context context("When performing check '" + name + "' using spec_keys_check on ID '" + stringify(*id) + "':");
+ Log::get_instance()->message(ll_debug, lc_context) << "spec_keys_check '"
+ << entry << "', " << *id << "', " << name << "'";
CheckForwarder f(entry, reporter, id, name);
parallel_for_each(indirect_iterator(id->begin_metadata()), indirect_iterator(id->end_metadata()), accept_visitor(f));
diff --git a/paludis/repositories/e/qa/stray_files.cc b/paludis/repositories/e/qa/stray_files.cc
index 08b882c..1a98bde 100644
--- a/paludis/repositories/e/qa/stray_files.cc
+++ b/paludis/repositories/e/qa/stray_files.cc
@@ -18,11 +18,13 @@
*/
#include <paludis/repositories/e/qa/stray_files.hh>
+#include <paludis/repositories/e/e_repository.hh>
#include <paludis/qa.hh>
#include <paludis/util/fs_entry.hh>
#include <paludis/util/dir_iterator.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/log.hh>
using namespace paludis;
using namespace paludis::erepository;
@@ -37,6 +39,8 @@ paludis::erepository::stray_files_check(
)
{
Context context("When performing check '" + name + "' using stray_files_check on directory '" + stringify(dir) + "':");
+ Log::get_instance()->message(ll_debug, lc_context) << "stray_files_check '"
+ << repo->name() << "', '" << dir << "', " << name << "'";
if (dir.exists())
for (DirIterator d(dir), d_end ; d != d_end ; ++d)
diff --git a/paludis/repositories/e/qa/visibility.cc b/paludis/repositories/e/qa/visibility.cc
new file mode 100644
index 0000000..1877858
--- /dev/null
+++ b/paludis/repositories/e/qa/visibility.cc
@@ -0,0 +1,345 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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/e/qa/visibility.hh>
+#include <paludis/repositories/e/dep_spec_pretty_printer.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/query.hh>
+#include <paludis/qa.hh>
+#include <paludis/dep_spec.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <paludis/package_id.hh>
+#include <paludis/version_requirements.hh>
+#include <paludis/metadata_key.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <set>
+#include <algorithm>
+
+using namespace paludis;
+
+namespace
+{
+ struct Checker :
+ ConstVisitor<DependencySpecTree>
+ {
+ const FSEntry entry;
+ QAReporter * const reporter;
+ const Environment * const env;
+ const PackageID & id;
+ const tr1::shared_ptr<const ERepository> repo;
+ const std::set<KeywordName> & accepted_keywords;
+ const ERepository::ProfilesIterator profile;
+ const std::string name;
+ const bool unstable;
+ const MetadataKey & key;
+
+ bool success;
+ bool viable;
+
+ Checker(
+ const FSEntry & e,
+ QAReporter * const r,
+ const Environment * const v,
+ const PackageID & i,
+ const tr1::shared_ptr<const ERepository> o,
+ const std::set<KeywordName> & a,
+ const ERepository::ProfilesIterator & p,
+ const std::string & n,
+ const bool u,
+ const MetadataKey & k) :
+ entry(e),
+ reporter(r),
+ env(v),
+ id(i),
+ repo(o),
+ accepted_keywords(a),
+ profile(p),
+ name(n),
+ unstable(u),
+ key(k),
+ success(true),
+ viable(false)
+ {
+ }
+
+ void visit_leaf(const BlockDepSpec &)
+ {
+ viable = true;
+ }
+
+ void visit_leaf(const PackageDepSpec & orig_p)
+ {
+ success = false;
+ viable = true;
+
+ const PackageDepSpec * p(&orig_p);
+ tr1::shared_ptr<PackageDepSpec> local_p;
+
+ /* rewrite virtuals to avoid problems later on */
+ if (p->package_ptr())
+ {
+ ERepositoryProfile::VirtualsIterator v(profile->profile->find_virtual(*p->package_ptr()));
+ if (profile->profile->end_virtuals() != v)
+ {
+ tr1::shared_ptr<VersionRequirements> reqs;
+ if (v->second->version_requirements_ptr())
+ {
+ reqs.reset(new VersionRequirements);
+ std::copy(v->second->version_requirements_ptr()->begin(), v->second->version_requirements_ptr()->end(),
+ reqs->back_inserter());
+ }
+ if (orig_p.version_requirements_ptr())
+ {
+ if (! reqs)
+ reqs.reset(new VersionRequirements);
+ std::copy(orig_p.version_requirements_ptr()->begin(), orig_p.version_requirements_ptr()->end(),
+ reqs->back_inserter());
+ }
+ local_p.reset(new PackageDepSpec(
+ make_shared_ptr(new QualifiedPackageName(*v->second->package_ptr())),
+ tr1::shared_ptr<CategoryNamePart>(),
+ tr1::shared_ptr<PackageNamePart>(),
+ reqs,
+ vr_and,
+ orig_p.slot_ptr() ?
+ make_shared_ptr(new SlotName(*orig_p.slot_ptr())) :
+ tr1::shared_ptr<SlotName>(),
+ orig_p.repository_ptr() ?
+ make_shared_ptr(new RepositoryName(*orig_p.repository_ptr())) :
+ tr1::shared_ptr<RepositoryName>(),
+ tr1::shared_ptr<UseRequirements>(),
+ orig_p.tag()
+ ));
+ p = local_p.get();
+ }
+ }
+
+ const tr1::shared_ptr<const PackageIDSequence> matches(env->package_database()->query(
+ query::Matches(*p) & query::SupportsAction<InstallAction>(), qo_order_by_version));
+ if (matches->empty())
+ {
+ if (reporter)
+ reporter->message(QAMessage(entry, qaml_normal, name, "No packages matching '"
+ + stringify(orig_p) + "' in dependencies key '" + stringify(key.raw_name()) + "' for profile '"
+ + stringify(profile->path) + "' (" + stringify(profile->arch) + "." + stringify(profile->status)
+ + (unstable ? ".unstable" : ".stable") + ")"));
+ }
+ else
+ {
+ for (PackageIDSequence::Iterator i(matches->begin()), i_end(matches->end()) ;
+ i != i_end ; ++i)
+ {
+ /* can't use the usual masked rules here, so this gets a bit complicated... */
+ if ((*i)->repository() == repo)
+ {
+ if (repo->repository_masked(**i) || profile->profile->profile_masked(**i) || ! (*i)->keywords_key())
+ continue;
+ }
+ else if ((*i)->repository() == repo->params().master_repository)
+ {
+ if (repo->params().master_repository->repository_masked(**i) ||
+ profile->profile->profile_masked(**i) || ! (*i)->keywords_key())
+ continue;
+ }
+ else
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Probably a bug: don't know how to get masks for '"
+ << **i << "' from '" << orig_p << "' -> '" << *p << "'";
+ continue;
+ }
+
+ std::set<KeywordName> overlap;
+ if ((*i)->keywords_key())
+ std::set_intersection(accepted_keywords.begin(), accepted_keywords.end(),
+ (*i)->keywords_key()->value()->begin(), (*i)->keywords_key()->value()->end(),
+ std::inserter(overlap, overlap.begin()));
+
+ if (overlap.empty())
+ continue;
+
+ success = true;
+ break;
+ }
+
+ if (! success)
+ if (reporter)
+ reporter->message(QAMessage(entry, qaml_normal, name, "No visible packages matching '"
+ + stringify(orig_p) + "' in dependencies key '" + stringify(key.raw_name()) + "' for profile '"
+ + stringify(profile->path) + "' (" + stringify(profile->arch) + "." + stringify(profile->status)
+ + (unstable ? ".unstable" : ".stable") + ")"));
+ }
+ }
+
+ void visit_sequence(const UseDepSpec & u,
+ DependencySpecTree::ConstSequenceIterator cur,
+ DependencySpecTree::ConstSequenceIterator end)
+ {
+ viable =
+ ((! u.inverse()) && (! repo->query_use_mask(u.flag(), id))) ||
+ ((u.inverse()) && (! repo->query_use_force(u.flag(), id)));
+
+ if (viable)
+ std::for_each(cur, end, accept_visitor(*this));
+ }
+
+ void visit_sequence(const AnyDepSpec &,
+ DependencySpecTree::ConstSequenceIterator begin,
+ DependencySpecTree::ConstSequenceIterator end)
+ {
+ success = true;
+ viable = true;
+ for (DependencySpecTree::ConstSequenceIterator cur(begin) ; cur != end ; ++cur)
+ {
+ Checker c(entry, 0, env, id, repo, accepted_keywords, profile, name, unstable, key);
+ accept_visitor(c)(*cur);
+ if (c.success)
+ {
+ success = true;
+ break;
+ }
+ else if (c.viable)
+ success = false;
+ }
+
+ if (! success)
+ {
+ if (reporter)
+ {
+ erepository::DepSpecPrettyPrinter printer(0, false);
+ std::for_each(begin, end, accept_visitor(printer));
+ reporter->message(QAMessage(entry, qaml_normal, name, "No item in block '|| ( "
+ + stringify(printer) + " )' visible for profile '"
+ + stringify(profile->path) + "' (" + stringify(profile->arch) + "." + stringify(profile->status)
+ + (unstable ? ".unstable" : ".stable") + ")"));
+ }
+ }
+ }
+
+ void visit_sequence(const AllDepSpec &,
+ DependencySpecTree::ConstSequenceIterator cur,
+ DependencySpecTree::ConstSequenceIterator end)
+ {
+ viable = true;
+ std::for_each(cur, end, accept_visitor(*this));
+ }
+ };
+}
+
+bool
+paludis::erepository::visibility_check(
+ const FSEntry & entry,
+ QAReporter & reporter,
+ const Environment * const env,
+ const tr1::shared_ptr<const ERepository> & repo,
+ const tr1::shared_ptr<const PackageID> & id,
+ const ERepository::ProfilesIterator & profile,
+ const std::string & name)
+{
+ Context context("When performing check '" + name + "' using visibility_check on ID '" + stringify(*id) +
+ "' with profile '" + stringify(profile->path) + "':");
+ Log::get_instance()->message(ll_debug, lc_context) << "visibility_check '"
+ << entry << "', '" << *id << "', '" << profile->path << "', '" << name << "'";
+
+ if (repo->repository_masked(*id) || profile->profile->profile_masked(*id) || ! id->keywords_key())
+ return true;
+
+ std::set<KeywordName> accepted_keywords, overlap;
+ WhitespaceTokeniser::get_instance()->tokenise(profile->profile->environment_variable(
+ repo->accept_keywords_variable()), create_inserter<KeywordName>(std::inserter(accepted_keywords, accepted_keywords.begin())));
+
+ std::set_intersection(accepted_keywords.begin(), accepted_keywords.end(),
+ id->keywords_key()->value()->begin(), id->keywords_key()->value()->end(),
+ std::inserter(overlap, overlap.begin()));
+
+ if (! overlap.empty())
+ {
+ if (id->build_dependencies_key())
+ {
+ Checker c(entry, &reporter, env, *id, repo, accepted_keywords, profile, name, false, *id->build_dependencies_key());
+ id->build_dependencies_key()->value()->accept(c);
+ }
+
+ if (id->run_dependencies_key())
+ {
+ Checker c(entry, &reporter, env, *id, repo, accepted_keywords, profile, name, false, *id->run_dependencies_key());
+ id->run_dependencies_key()->value()->accept(c);
+ }
+
+ if (id->post_dependencies_key())
+ {
+ Checker c(entry, &reporter, env, *id, repo, accepted_keywords, profile, name, false, *id->post_dependencies_key());
+ id->post_dependencies_key()->value()->accept(c);
+ }
+
+ if (id->suggested_dependencies_key())
+ {
+ Checker c(entry, &reporter, env, *id, repo, accepted_keywords, profile, name, false, *id->suggested_dependencies_key());
+ id->post_dependencies_key()->value()->accept(c);
+ }
+ }
+ else
+ {
+ for (std::set<KeywordName>::iterator i(accepted_keywords.begin()), i_end(accepted_keywords.end()) ;
+ i != i_end ; ++i)
+ if ('~' != stringify(*i).at(0))
+ accepted_keywords.insert(KeywordName("~" + stringify(*i)));
+
+ std::set_intersection(accepted_keywords.begin(), accepted_keywords.end(),
+ id->keywords_key()->value()->begin(), id->keywords_key()->value()->end(),
+ std::inserter(overlap, overlap.begin()));
+
+ if (! overlap.empty())
+ {
+ if (id->build_dependencies_key())
+ {
+ Checker c(entry, &reporter, env, *id, repo, accepted_keywords, profile, name, true, *id->build_dependencies_key());
+ id->build_dependencies_key()->value()->accept(c);
+ }
+
+ if (id->run_dependencies_key())
+ {
+ Checker c(entry, &reporter, env, *id, repo, accepted_keywords, profile, name, true, *id->run_dependencies_key());
+ id->run_dependencies_key()->value()->accept(c);
+ }
+
+ if (id->post_dependencies_key())
+ {
+ Checker c(entry, &reporter, env, *id, repo, accepted_keywords, profile, name, true, *id->post_dependencies_key());
+ id->post_dependencies_key()->value()->accept(c);
+ }
+
+ if (id->suggested_dependencies_key())
+ {
+ Checker c(entry, &reporter, env, *id, repo, accepted_keywords, profile, name, true, *id->suggested_dependencies_key());
+ id->post_dependencies_key()->value()->accept(c);
+ }
+ }
+ }
+
+ return true;
+}
+
diff --git a/paludis/repositories/e/qa/visibility.hh b/paludis/repositories/e/qa/visibility.hh
new file mode 100644
index 0000000..1271a80
--- /dev/null
+++ b/paludis/repositories/e/qa/visibility.hh
@@ -0,0 +1,45 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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/qa-fwd.hh>
+#include <paludis/package_id-fwd.hh>
+#include <paludis/environment-fwd.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/fs_entry-fwd.hh>
+#include <paludis/repositories/e/e_repository.hh>
+
+#ifndef PALUDIS_GUARD_PALUDIS_PALUDIS_REPOSITORIES_E_QA_VISIBILITY_HH
+#define PALUDIS_GUARD_PALUDIS_PALUDIS_REPOSITORIES_E_QA_VISIBILITY_HH 1
+
+namespace paludis
+{
+ namespace erepository
+ {
+ bool visibility_check(
+ const FSEntry &,
+ QAReporter &,
+ const Environment * const env,
+ const tr1::shared_ptr<const ERepository> &,
+ const tr1::shared_ptr<const PackageID> &,
+ const ERepository::ProfilesIterator &,
+ const std::string &) PALUDIS_VISIBLE;
+ }
+}
+
+#endif
diff --git a/paludis/repositories/e/qa/visibility_TEST.cc b/paludis/repositories/e/qa/visibility_TEST.cc
new file mode 100644
index 0000000..6fb2222
--- /dev/null
+++ b/paludis/repositories/e/qa/visibility_TEST.cc
@@ -0,0 +1,113 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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 "visibility.hh"
+#include <paludis/repositories/e/e_repository.hh>
+#include <paludis/repositories/e/make_ebuild_repository.hh>
+#include <paludis/environments/test/test_environment.hh>
+#include <paludis/util/map.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/qa.hh>
+#include <paludis/query.hh>
+#include <paludis/package_database.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+
+using namespace paludis;
+using namespace paludis::erepository;
+using namespace test;
+
+namespace
+{
+ struct TestReporter :
+ QAReporter
+ {
+ unsigned count;
+ std::string messages;
+
+ TestReporter() :
+ count(0)
+ {
+ }
+
+ void message(const QAMessage & m)
+ {
+ ++count;
+ if (! messages.empty())
+ messages.append(", ");
+ messages.append(m.message);
+ }
+ };
+}
+
+namespace test_cases
+{
+ struct VisibilityTest : TestCase
+ {
+ VisibilityTest() : TestCase("visibility") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "visibility_TEST_dir/repo1");
+ keys->insert("profiles", stringify(FSEntry::cwd() / "visibility_TEST_dir/repo1/profiles/test"));
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ {
+ tr1::shared_ptr<const PackageID> id1(*env.package_database()->query(query::Matches(PackageDepSpec(
+ "=cat-one/visible-1", pds_pm_unspecific)), qo_require_exactly_one)->begin());
+ TestReporter r1;
+ TEST_CHECK(visibility_check(FSEntry("/var/empty"), r1, &env, repo, id1, repo->begin_profiles(), "visibility"));
+ TEST_CHECK_EQUAL(r1.count, 0u);
+ }
+
+ {
+ tr1::shared_ptr<const PackageID> id2(*env.package_database()->query(query::Matches(PackageDepSpec(
+ "=cat-one/visible-2", pds_pm_unspecific)), qo_require_exactly_one)->begin());
+ TestReporter r2;
+ TEST_CHECK(visibility_check(FSEntry("/var/empty"), r2, &env, repo, id2, repo->begin_profiles(), "visibility"));
+ TEST_CHECK_EQUAL(r2.count, 0u);
+ }
+
+ {
+ tr1::shared_ptr<const PackageID> id3(*env.package_database()->query(query::Matches(PackageDepSpec(
+ "=cat-one/masked-1", pds_pm_unspecific)), qo_require_exactly_one)->begin());
+ TestReporter r3;
+ TEST_CHECK(visibility_check(FSEntry("/var/empty"), r3, &env, repo, id3, repo->begin_profiles(), "visibility"));
+ TEST_CHECK_EQUAL(r3.count, 0u);
+ }
+
+ {
+ tr1::shared_ptr<const PackageID> id4(*env.package_database()->query(query::Matches(PackageDepSpec(
+ "=cat-one/needs-masked-1", pds_pm_unspecific)), qo_require_exactly_one)->begin());
+ TestReporter r4;
+ TEST_CHECK(visibility_check(FSEntry("/var/empty"), r4, &env, repo, id4, repo->begin_profiles(), "visibility"));
+ TestMessageSuffix s4(r4.messages);
+ TEST_CHECK_EQUAL(r4.count, 1u);
+ }
+ }
+ } test_visibility;
+}
+
+
diff --git a/paludis/repositories/e/qa/visibility_TEST_cleanup.sh b/paludis/repositories/e/qa/visibility_TEST_cleanup.sh
new file mode 100755
index 0000000..acda8e2
--- /dev/null
+++ b/paludis/repositories/e/qa/visibility_TEST_cleanup.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d visibility_TEST_dir ] ; then
+ rm -fr visibility_TEST_dir
+else
+ true
+fi
+
diff --git a/paludis/repositories/e/qa/visibility_TEST_setup.sh b/paludis/repositories/e/qa/visibility_TEST_setup.sh
new file mode 100755
index 0000000..d28e36a
--- /dev/null
+++ b/paludis/repositories/e/qa/visibility_TEST_setup.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir visibility_TEST_dir || exit 1
+cd visibility_TEST_dir || exit 1
+
+mkdir -p repo1/{eclass,distfiles,profiles/test,cat-one/{visible,masked,needs-masked}} || exit 1
+cd repo1 || exit 1
+echo "repo1" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat-one
+END
+cat <<END > profiles/test/make.defaults
+ARCH=test
+ACCEPT_KEYWORDS=test
+END
+cat <<END > profiles/profiles.desc
+test test/ stable
+END
+cat <<END > cat-one/visible/visible-1.ebuild
+DESCRIPTION="visible"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE=""
+LICENSE="GPL-2"
+KEYWORDS="test"
+END
+cat <<END > cat-one/visible/visible-2.ebuild
+DESCRIPTION="visible"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE=""
+LICENSE="GPL-2"
+KEYWORDS="~test"
+END
+cat <<END > cat-one/masked/masked-1.ebuild
+DESCRIPTION="masked"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE=""
+LICENSE="GPL-2"
+KEYWORDS="monkey"
+END
+cat <<END > cat-one/needs-masked/needs-masked-1.ebuild
+DESCRIPTION="needs masked"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE=""
+LICENSE="GPL-2"
+KEYWORDS="test"
+DEPEND="cat-one/masked"
+RDEPEND=""
+END
+cd ..
+
+cd ..
+
+
diff --git a/src/clients/qualudis/qualudis.cc b/src/clients/qualudis/qualudis.cc
index 268053f..ad5d661 100644
--- a/src/clients/qualudis/qualudis.cc
+++ b/src/clients/qualudis/qualudis.cc
@@ -58,9 +58,11 @@ namespace
QAReporter
{
FSEntry previous_entry;
+ std::string previous_name;
QualudisReporter() :
- previous_entry("/NONE")
+ previous_entry("/NONE"),
+ previous_name("NONE")
{
}
@@ -71,26 +73,43 @@ namespace
std::cout << colour(cl_package_name, strip_leading_string(stringify(msg.entry.strip_leading(FSEntry::cwd())), "/"))
<< ":" << std::endl;
previous_entry = msg.entry;
+ previous_name = "NONE";
}
- std::cout << " " << msg.name << " [";
+ if (previous_name != msg.name)
+ {
+ std::cout << " " << msg.name << ":" << std::endl;
+ previous_name = msg.name;
+ }
+
+ std::cout << " [";
switch (msg.level)
{
case qaml_maybe:
+ std::cout << "?";
+ break;
+
case qaml_debug:
- std::cout << msg.level;
+ std::cout << "-";
break;
case qaml_minor:
+ std::cout << "*";
+ break;
+
case qaml_normal:
+ std::cout << colour(cl_error, "*");
+ break;
+
case qaml_severe:
+ std::cout << colour(cl_error, "!");
+ break;
+
case last_qaml:
- std::cout << colour(cl_error, stringify(msg.level));
break;
}
- std::cout << "]:" << std::endl;
- std::cout << " " << msg.message << std::endl;
+ std::cout << "]: " << msg.message << std::endl;
}
};
}