aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-11-04 09:14:03 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-11-04 09:14:03 +0000
commitc353065322a0869ecc1edc527e56e39befa592b6 (patch)
tree09c3c4a355379b295017c979316e5ca63f3ab16d
parent01c3a6940286ef2ad1e7a3cd9912e2c0ad057603 (diff)
downloadpaludis-c353065322a0869ecc1edc527e56e39befa592b6.tar.gz
paludis-c353065322a0869ecc1edc527e56e39befa592b6.tar.xz
More QA work
-rw-r--r--paludis/repositories/e/qa/Makefile.am30
-rw-r--r--paludis/repositories/e/qa/kv_variables.cc65
-rw-r--r--paludis/repositories/e/qa/kv_variables.hh43
-rw-r--r--paludis/repositories/e/qa/kv_variables_TEST.cc98
-rw-r--r--paludis/repositories/e/qa/qa_checks.cc18
-rw-r--r--paludis/repositories/e/qa/qa_checks.hh12
-rw-r--r--paludis/repositories/e/qa/qa_checks_group.cc2
-rw-r--r--paludis/repositories/e/qa/qa_controller.cc25
-rw-r--r--paludis/repositories/e/qa/visibility.hh6
-rw-r--r--paludis/repositories/e/qa/whitespace.cc111
-rw-r--r--paludis/repositories/e/qa/whitespace.hh44
11 files changed, 445 insertions, 9 deletions
diff --git a/paludis/repositories/e/qa/Makefile.am b/paludis/repositories/e/qa/Makefile.am
index 023e5b9..3f52279 100644
--- a/paludis/repositories/e/qa/Makefile.am
+++ b/paludis/repositories/e/qa/Makefile.am
@@ -3,7 +3,10 @@ CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
DISTCLEANFILES =
MAINTAINERCLEANFILES = Makefile.in
-AM_CXXFLAGS = -I$(top_srcdir) -I$(top_builddir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
+AM_CXXFLAGS = \
+ -I$(top_srcdir) -I$(top_builddir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@ \
+ $(PCREPLUSPLUS_CFLAGS)
+
DEFS = \
-DSYSCONFDIR=\"$(sysconfdir)\" \
-DLIBEXECDIR=\"$(libexecdir)\" \
@@ -33,7 +36,9 @@ paludis_repositories_e_include_HEADERS = \
qa_controller.hh \
short_description_key.hh \
stray_files.hh \
- visibility.hh
+ kv_variables.hh \
+ visibility.hh \
+ whitespace.hh
lib_LTLIBRARIES = libpaludiserepositoryqa.la
@@ -48,10 +53,15 @@ libpaludiserepositoryqa_la_SOURCES = \
short_description_key.cc \
spec_keys.cc \
stray_files.cc \
+ kv_variables.cc \
visibility.cc \
+ whitespace.cc \
$(paludis_repositories_e_include_HEADERS)
-libpaludiserepositoryqa_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+libpaludiserepositoryqa_la_LDFLAGS = \
+ -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0 \
+ $(PCREPLUSPLUS_LIBS)
+
libpaludiserepositoryqa_la_LIBADD = \
$(top_builddir)/paludis/repositories/e/libpaludiserepository.la \
$(top_builddir)/paludis/libpaludis.la \
@@ -88,6 +98,7 @@ TESTS = \
extractors_TEST \
spec_keys_TEST \
stray_files_TEST \
+ kv_variables_TEST \
visibility_TEST
check_PROGRAMS = $(TESTS)
@@ -140,6 +151,18 @@ visibility_TEST_LDADD = \
$(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
$(top_builddir)/test/libtest.a
+kv_variables_TEST_SOURCES = kv_variables_TEST.cc
+kv_variables_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)
@@ -152,3 +175,4 @@ distcheck-deps : distcheck-deps-subdirs
distcheck-deps-subdirs :
for s in $(SUBDIRS) . ; do if test x$$s = x. ; then $(MAKE) distcheck-deps-local || exit 1 ; \
else $(MAKE) -C $$s distcheck-deps || exit 1 ; fi ; done
+
diff --git a/paludis/repositories/e/qa/kv_variables.cc b/paludis/repositories/e/qa/kv_variables.cc
new file mode 100644
index 0000000..3e2218e
--- /dev/null
+++ b/paludis/repositories/e/qa/kv_variables.cc
@@ -0,0 +1,65 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 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/e/qa/kv_variables.hh>
+#include <paludis/qa.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/tokeniser.hh>
+#include <pcre++.h>
+#include <list>
+
+using namespace paludis;
+
+bool
+paludis::erepository::kv_variables_check(
+ const FSEntry & entry,
+ QAReporter & reporter,
+ const tr1::shared_ptr<const PackageID> & id,
+ const std::string & content,
+ const std::string & name)
+{
+ Context context("When performing check '" + name + "' using kv_variables on '" + stringify(*id) + "':");
+
+ pcrepp::Pcre::Pcre r_global("^[a-zA-Z0-9\\_]+=.*\\$[{}]?KV");
+ pcrepp::Pcre::Pcre r_detect_version("^detect_version$");
+
+ Log::get_instance()->message(ll_debug, lc_context) << "kv_variables '"
+ << entry << "', '" << *id << "', '" << name << "'";
+
+ std::list<std::string> lines;
+ Tokeniser<delim_kind::AnyOfTag>::tokenise(content, "\n", std::back_inserter(lines));
+
+ unsigned line(0);
+ for (std::list<std::string>::const_iterator l(lines.begin()), l_end(lines.end()) ;
+ l != l_end ; ++l)
+ {
+ ++line;
+
+ if (r_detect_version.search(*l))
+ break;
+
+ if (r_global.search(*l))
+ reporter.message(QAMessage(entry, qaml_normal, name, "KV variable with no detect_version on line "
+ + stringify(line) + ": " + strip_leading(*l, " \t")));
+ }
+
+ return true;
+}
+
diff --git a/paludis/repositories/e/qa/kv_variables.hh b/paludis/repositories/e/qa/kv_variables.hh
new file mode 100644
index 0000000..b053bd3
--- /dev/null
+++ b/paludis/repositories/e/qa/kv_variables.hh
@@ -0,0 +1,43 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 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
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_QA_VARIANT_GLOBALS_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_QA_VARIANT_GLOBALS_HH 1
+
+#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>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ bool kv_variables_check(
+ const FSEntry &,
+ QAReporter &,
+ const tr1::shared_ptr<const PackageID> &,
+ const std::string &,
+ const std::string &) PALUDIS_VISIBLE;
+ }
+}
+
+#endif
diff --git a/paludis/repositories/e/qa/kv_variables_TEST.cc b/paludis/repositories/e/qa/kv_variables_TEST.cc
new file mode 100644
index 0000000..4b32be7
--- /dev/null
+++ b/paludis/repositories/e/qa/kv_variables_TEST.cc
@@ -0,0 +1,98 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 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 "kv_variables.hh"
+#include <paludis/repositories/fake/fake_repository.hh>
+#include <paludis/repositories/fake/fake_package_id.hh>
+#include <paludis/environments/test/test_environment.hh>
+#include <paludis/package_database.hh>
+#include <paludis/qa.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.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);
+ }
+
+ void status(const std::string &)
+ {
+ }
+ };
+}
+
+namespace test_cases
+{
+ struct GoodTest : TestCase
+ {
+ GoodTest() : TestCase("good") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<FakeRepository> repo(new FakeRepository(&env, RepositoryName("repo")));
+ env.package_database()->add_repository(1, repo);
+ tr1::shared_ptr<FakePackageID> id(repo->add_version("cat", "pkg", "1"));
+ id->build_dependencies_key()->set_from_string("cat/other");
+
+ TestReporter r;
+ TEST_CHECK(kv_variables_check(FSEntry("/var/empty"), r, id, "X=KV\n", "kv_variables"));
+ TEST_CHECK_EQUAL(r.count, 0u);
+ }
+ } test_good;
+
+ struct BadTest : TestCase
+ {
+ BadTest() : TestCase("bad") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<FakeRepository> repo(new FakeRepository(&env, RepositoryName("repo")));
+ env.package_database()->add_repository(1, repo);
+ tr1::shared_ptr<FakePackageID> id(repo->add_version("cat", "pkg", "1"));
+ id->build_dependencies_key()->set_from_string("cat/other");
+
+ TestReporter r;
+ TEST_CHECK(kv_variables_check(FSEntry("/var/empty"), r, id, "SLOT=\"foo-$KV\"\n", "kv_variables"));
+ TEST_CHECK_EQUAL(r.count, 1u);
+ }
+ } test_bad;
+}
+
diff --git a/paludis/repositories/e/qa/qa_checks.cc b/paludis/repositories/e/qa/qa_checks.cc
index 7ae5f20..f672e98 100644
--- a/paludis/repositories/e/qa/qa_checks.cc
+++ b/paludis/repositories/e/qa/qa_checks.cc
@@ -28,6 +28,8 @@
#include <paludis/repositories/e/qa/spec_keys.hh>
#include <paludis/repositories/e/qa/extractors.hh>
#include <paludis/repositories/e/qa/visibility.hh>
+#include <paludis/repositories/e/qa/kv_variables.hh>
+#include <paludis/repositories/e/qa/whitespace.hh>
using namespace paludis;
using namespace paludis::erepository;
@@ -42,11 +44,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<PackageIDFileContentsCheckFunction> > package_id_file_contents_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>),
+ package_id_file_contents_checks_group(new QAChecksGroup<PackageIDFileContentsCheckFunction>)
{
}
};
@@ -84,6 +88,12 @@ QAChecks::QAChecks() :
_imp->package_id_checks_group->add_check("visibility",
tr1::bind(visibility_check, _1, _2, _3, _4, _5, "visibility"));
+
+ _imp->package_id_file_contents_checks_group->add_check("kv_variables",
+ tr1::bind(kv_variables_check, _1, _2, _5, _6, "kv_variables"));
+
+ _imp->package_id_file_contents_checks_group->add_check("whitespace",
+ tr1::bind(whitespace_check, _1, _2, _5, _6, "whitespace"));
}
QAChecks::~QAChecks()
@@ -108,3 +118,9 @@ QAChecks::package_id_checks_group()
return _imp->package_id_checks_group;
}
+const tr1::shared_ptr<QAChecksGroup<PackageIDFileContentsCheckFunction> >
+QAChecks::package_id_file_contents_checks_group()
+{
+ return _imp->package_id_file_contents_checks_group;
+}
+
diff --git a/paludis/repositories/e/qa/qa_checks.hh b/paludis/repositories/e/qa/qa_checks.hh
index 58977be..e4ca03a 100644
--- a/paludis/repositories/e/qa/qa_checks.hh
+++ b/paludis/repositories/e/qa/qa_checks.hh
@@ -63,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 std::string &
+ )> PackageIDFileContentsCheckFunction;
+
class QAChecks :
private PrivateImplementationPattern<QAChecks>,
public InstantiationPolicy<QAChecks, instantiation_method::SingletonTag>
@@ -82,6 +91,9 @@ namespace paludis
const tr1::shared_ptr<QAChecksGroup<PackageIDCheckFunction> >
package_id_checks_group() PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ const tr1::shared_ptr<QAChecksGroup<PackageIDFileContentsCheckFunction> >
+ package_id_file_contents_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 0432301..0533ac1 100644
--- a/paludis/repositories/e/qa/qa_checks_group.cc
+++ b/paludis/repositories/e/qa/qa_checks_group.cc
@@ -115,7 +115,9 @@ QAChecksGroup<T_>::need_ordering() const
template class QAChecksGroup<TreeCheckFunction>;
template class QAChecksGroup<PackageIDCheckFunction>;
+template class QAChecksGroup<PackageIDFileContentsCheckFunction>;
template class WrappedForwardIterator<QAChecksGroup<TreeCheckFunction>::ConstIteratorTag, TreeCheckFunction>;
template class WrappedForwardIterator<QAChecksGroup<PackageIDCheckFunction>::ConstIteratorTag, PackageIDCheckFunction>;
+template class WrappedForwardIterator<QAChecksGroup<PackageIDFileContentsCheckFunction>::ConstIteratorTag, PackageIDFileContentsCheckFunction>;
diff --git a/paludis/repositories/e/qa/qa_controller.cc b/paludis/repositories/e/qa/qa_controller.cc
index 52de195..2c205d2 100644
--- a/paludis/repositories/e/qa/qa_controller.cc
+++ b/paludis/repositories/e/qa/qa_controller.cc
@@ -31,7 +31,9 @@
#include <paludis/util/thread_pool.hh>
#include <paludis/util/action_queue.hh>
#include <paludis/qa.hh>
+#include <paludis/metadata_key.hh>
+#include <fstream>
#include <unistd.h>
#include <algorithm>
#include <list>
@@ -284,6 +286,7 @@ QAController::_check_id(const tr1::shared_ptr<const PackageID> & i)
try
{
if (_under_base_dir(p_dir))
+ {
std::find_if(
QAChecks::get_instance()->package_id_checks_group()->begin(),
QAChecks::get_instance()->package_id_checks_group()->end(),
@@ -291,11 +294,29 @@ QAController::_check_id(const tr1::shared_ptr<const PackageID> & i)
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))));
+
+ std::ifstream f(stringify(i->fs_location_key()->value()).c_str());
+ std::string content((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
+ if (! f)
+ _imp->reporter.message(
+ QAMessage(_imp->repo->layout()->package_file(*i), qaml_severe, "check_id",
+ "Couldn't get file contents for ID '" + stringify(*i) + ")")
+ .with_associated_id(i)
+ .with_associated_key(i->fs_location_key()));
+ else
+ std::find_if(
+ QAChecks::get_instance()->package_id_file_contents_checks_group()->begin(),
+ QAChecks::get_instance()->package_id_file_contents_checks_group()->end(),
+ tr1::bind(std::equal_to<bool>(), false,
+ tr1::bind<bool>(tr1::mem_fn(&PackageIDFileContentsCheckFunction::operator() ),
+ _1, _imp->repo->layout()->package_file(*i), tr1::ref(_imp->reporter),
+ _imp->env, _imp->repo, tr1::static_pointer_cast<const ERepositoryID>(i), content)));
+ }
}
catch (const Exception & e)
{
_imp->reporter.message(
- QAMessage(_imp->repo->layout()->package_file(*i), qaml_severe, "package_id_checks_group",
+ QAMessage(_imp->repo->layout()->package_file(*i), qaml_severe, "check_id",
"Caught exception '" + e.message() + "' (" + e.what() + ")")
.with_associated_id(i));
}
@@ -341,7 +362,7 @@ QAController::run()
catch (const Exception & e)
{
_imp->reporter.message(
- QAMessage(_imp->repo->params().location, qaml_severe, "tree_checks_group",
+ QAMessage(_imp->repo->params().location, qaml_severe, "run",
"Caught exception '" + e.message() + "' (" + e.what() + ")"));
}
}
diff --git a/paludis/repositories/e/qa/visibility.hh b/paludis/repositories/e/qa/visibility.hh
index 51b2b3d..0fe4fb3 100644
--- a/paludis/repositories/e/qa/visibility.hh
+++ b/paludis/repositories/e/qa/visibility.hh
@@ -17,6 +17,9 @@
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#ifndef PALUDIS_GUARD_PALUDIS_PALUDIS_REPOSITORIES_E_QA_VISIBILITY_HH
+#define PALUDIS_GUARD_PALUDIS_PALUDIS_REPOSITORIES_E_QA_VISIBILITY_HH 1
+
#include <paludis/qa-fwd.hh>
#include <paludis/package_id-fwd.hh>
#include <paludis/environment-fwd.hh>
@@ -24,9 +27,6 @@
#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
diff --git a/paludis/repositories/e/qa/whitespace.cc b/paludis/repositories/e/qa/whitespace.cc
new file mode 100644
index 0000000..705c0ae
--- /dev/null
+++ b/paludis/repositories/e/qa/whitespace.cc
@@ -0,0 +1,111 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 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/e/qa/whitespace.hh>
+#include <paludis/qa.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/tokeniser.hh>
+#include <list>
+
+using namespace paludis;
+
+bool
+paludis::erepository::whitespace_check(
+ const FSEntry & entry,
+ QAReporter & reporter,
+ const tr1::shared_ptr<const PackageID> & id,
+ const std::string & content,
+ const std::string & name)
+{
+ Context context("When performing check '" + name + "' using whitespace_check on '" + stringify(*id) + "':");
+
+ Log::get_instance()->message(ll_debug, lc_context) << "whitespace '"
+ << entry << "', '" << *id << "', '" << name << "'";
+
+ std::list<std::string> lines;
+ Tokeniser<delim_kind::AnyOfTag>::tokenise(content, "\n", std::back_inserter(lines));
+
+ unsigned line(0), err_count(0);
+ for (std::list<std::string>::const_iterator l(lines.begin()), l_end(lines.end()) ;
+ l != l_end ; ++l)
+ {
+ ++line;
+
+ if (l->empty())
+ continue;
+
+ if (err_count >= 3)
+ {
+ reporter.message(QAMessage(entry, qaml_minor, name, "Skipping further whitespace checks")
+ .with_associated_id(id));
+ break;
+ }
+
+ if (' ' == l->at(0))
+ {
+ reporter.message(QAMessage(entry, qaml_minor, name, "Spaces for indenting on line "
+ + stringify(line) + ": " + strip_leading(*l, " \t"))
+ .with_associated_id(id));
+ ++err_count;
+ continue;
+ }
+ else if ('\t' == l->at(0))
+ {
+ std::string::size_type p(l->find_first_of("\t"));
+ if (std::string::npos == p)
+ {
+ reporter.message(QAMessage(entry, qaml_minor, name, "Indent followed by no content on line "
+ + stringify(line) + ": " + strip_leading(*l, " \t"))
+ .with_associated_id(id));
+ ++err_count;
+ continue;
+ }
+ else if (' ' == l->at(p))
+ {
+ reporter.message(QAMessage(entry, qaml_minor, name, "Mixed tabs and spaces for indenting on line "
+ + stringify(line) + ": " + strip_leading(*l, " \t"))
+ .with_associated_id(id));
+ ++err_count;
+ continue;
+ }
+ else if (std::string::npos != l->find(p, '\t'))
+ {
+ reporter.message(QAMessage(entry, qaml_minor, name, "Non-intent tab on line "
+ + stringify(line) + ": " + strip_leading(*l, " \t"))
+ .with_associated_id(id));
+ ++err_count;
+ continue;
+ }
+ }
+
+ if (' ' == l->at(l->length() - 1) || '\t' == l->at(l->length() - 1))
+ {
+ reporter.message(QAMessage(entry, qaml_minor, name, "Trailing space on line "
+ + stringify(line) + ": " + strip_leading(*l, " \t"))
+ .with_associated_id(id));
+ ++err_count;
+ continue;
+ }
+ }
+
+ return true;
+}
+
+
diff --git a/paludis/repositories/e/qa/whitespace.hh b/paludis/repositories/e/qa/whitespace.hh
new file mode 100644
index 0000000..6e84005
--- /dev/null
+++ b/paludis/repositories/e/qa/whitespace.hh
@@ -0,0 +1,44 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 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
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_QA_WHITESPACE_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_QA_WHITESPACE_HH 1
+
+#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>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ bool whitespace_check(
+ const FSEntry &,
+ QAReporter &,
+ const tr1::shared_ptr<const PackageID> &,
+ const std::string &,
+ const std::string &) PALUDIS_VISIBLE;
+ }
+}
+
+
+#endif