aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar David Leverton <levertond@googlemail.com> 2008-02-04 03:45:35 +0000
committerAvatar David Leverton <levertond@googlemail.com> 2008-02-04 03:45:35 +0000
commit75b00b4896cb797755649293d3ab2490c4c0956e (patch)
tree2ceb6b8d58c740064054907a93d17d8f262b0fa0
parent22fff6b52785cdf2f9ba1cccc29ec0c8f8eff3c8 (diff)
downloadpaludis-75b00b4896cb797755649293d3ab2490c4c0956e.tar.gz
paludis-75b00b4896cb797755649293d3ab2490c4c0956e.tar.xz
Rename gpg check to manifest, and make it verify the digests.
-rw-r--r--paludis/repositories/e/qa/Makefile.am14
-rw-r--r--paludis/repositories/e/qa/gpg.cc81
-rw-r--r--paludis/repositories/e/qa/gpg_TEST.cc90
-rwxr-xr-xpaludis/repositories/e/qa/gpg_TEST_cleanup.sh8
-rwxr-xr-xpaludis/repositories/e/qa/gpg_TEST_setup.sh9
-rw-r--r--paludis/repositories/e/qa/manifest.cc288
-rw-r--r--paludis/repositories/e/qa/manifest.hh (renamed from paludis/repositories/e/qa/gpg.hh)8
-rw-r--r--paludis/repositories/e/qa/manifest_TEST.cc287
-rwxr-xr-xpaludis/repositories/e/qa/manifest_TEST_cleanup.sh8
-rwxr-xr-xpaludis/repositories/e/qa/manifest_TEST_setup.sh145
-rw-r--r--paludis/repositories/e/qa/qa_checks.cc6
11 files changed, 743 insertions, 201 deletions
diff --git a/paludis/repositories/e/qa/Makefile.am b/paludis/repositories/e/qa/Makefile.am
index 9786a71..1f2a05e 100644
--- a/paludis/repositories/e/qa/Makefile.am
+++ b/paludis/repositories/e/qa/Makefile.am
@@ -56,7 +56,7 @@ paludis_repositories_e_include_HEADERS = \
header.hh \
variable_assigns.hh \
deprecated_functions.hh \
- gpg.hh \
+ manifest.hh \
ebuild_count.hh \
changelog.hh \
misc_files.hh \
@@ -94,7 +94,7 @@ libpaludiserepositoryqa_la_SOURCES = \
header.cc \
variable_assigns.cc \
deprecated_functions.cc \
- gpg.cc \
+ manifest.cc \
ebuild_count.cc \
changelog.cc \
misc_files.cc \
@@ -117,8 +117,8 @@ dist_check_SCRIPTS = \
visibility_TEST_cleanup.sh \
misc_files_TEST_setup.sh \
misc_files_TEST_cleanup.sh \
- gpg_TEST_setup.sh \
- gpg_TEST_cleanup.sh
+ manifest_TEST_setup.sh \
+ manifest_TEST_cleanup.sh
endif
@@ -154,7 +154,7 @@ TESTS = \
kv_variables_TEST \
visibility_TEST \
misc_files_TEST \
- gpg_TEST \
+ manifest_TEST \
subshell_die_TEST \
function_keyword_TEST
@@ -256,8 +256,8 @@ misc_files_TEST_LDADD = \
$(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
$(top_builddir)/test/libtest.a
-gpg_TEST_SOURCES = gpg_TEST.cc
-gpg_TEST_LDADD = \
+manifest_TEST_SOURCES = manifest_TEST.cc
+manifest_TEST_LDADD = \
libpaludiserepositoryqa.la \
test_extras.o \
$(top_builddir)/paludis/repositories/e/libpaludiserepository.la \
diff --git a/paludis/repositories/e/qa/gpg.cc b/paludis/repositories/e/qa/gpg.cc
deleted file mode 100644
index fe86c0d..0000000
--- a/paludis/repositories/e/qa/gpg.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-/* vim: set sw=4 sts=4 et foldmethod=syntax : */
-
-/*
- * Copyright (c) 2006 Fernando J. Pereda
- *
- * 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 "gpg.hh"
-#include <paludis/qa.hh>
-#include <paludis/util/log.hh>
-#include <paludis/util/system.hh>
-#include <paludis/util/fd_holder.hh>
-#include <fstream>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-using namespace paludis;
-using namespace paludis::erepository;
-
-bool
-paludis::erepository::gpg_check(
- QAReporter & reporter,
- const FSEntry & dir,
- const std::string & name
- )
-{
- Context context("When performing check '" + name + "' using gpg_check on directory '" + stringify(dir) + "':");
- Log::get_instance()->message(ll_debug, lc_context) << "gpg_check '"
- << dir << "', " << name << "'";
-
- FSEntry manifest(dir / "Manifest");
-
- if (! manifest.is_regular_file())
- {
- reporter.message(QAMessage(manifest, qaml_normal, name, "Manifest is missing or not a regular file"));
- return true;
- }
-
- bool is_signed(false);
- {
- std::ifstream ff(stringify(manifest).c_str());
- if (! ff)
- {
- reporter.message(QAMessage(manifest, qaml_normal, name, "Can't read Manifest file"));
- return true;
- }
-
- std::string s;
- if (std::getline(ff, s))
- is_signed = (0 == s.compare("-----BEGIN PGP SIGNED MESSAGE-----"));
- }
-
- if (is_signed)
- {
- int status(run_command("gpg --verify " + stringify(manifest) + " >/dev/null 2>/dev/null"));
-
- if (1 == status)
- reporter.message(QAMessage(manifest, qaml_normal, name, "Broken Manifest signature"));
- else if (2 == status)
- reporter.message(QAMessage(manifest, qaml_maybe, name, "Manifest signature cannot be verified"));
- }
- else
- reporter.message(QAMessage(manifest, qaml_minor, name, "Manifest not signed"));
-
- return true;
-}
-
diff --git a/paludis/repositories/e/qa/gpg_TEST.cc b/paludis/repositories/e/qa/gpg_TEST.cc
deleted file mode 100644
index 35a5b2a..0000000
--- a/paludis/repositories/e/qa/gpg_TEST.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-/* vim: set sw=4 sts=4 et foldmethod=syntax : */
-
-/*
- * Copyright (c) 2006 Fernando J. Pereda
- *
- * 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 "gpg.hh"
-#include <paludis/qa.hh>
-#include <paludis/util/system.hh>
-#include <paludis/util/fd_holder.hh>
-#include <paludis/util/fs_entry.hh>
-#include <test/test_framework.hh>
-#include <test/test_runner.hh>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-using namespace paludis;
-using namespace paludis::erepository;
-using namespace test;
-
-namespace
-{
- struct TestReporter :
- QAReporter
- {
- unsigned count;
-
- TestReporter() :
- count(0)
- {
- }
-
- void message(const QAMessage &)
- {
- ++count;
- }
-
- void status(const std::string &)
- {
- }
- };
-}
-
-namespace test_cases
-{
- struct GPGCheckTest : TestCase
- {
- GPGCheckTest() : TestCase("signed Manifest") { }
-
- bool skip() const
- {
- FDHolder dev_null(::open("/dev/null", O_WRONLY));
- set_run_command_stdout_fds(dev_null, -1);
- set_run_command_stderr_fds(dev_null, -1);
-
- return (0 != run_command("gpg --help"));
- }
-
- void run()
- {
- FSEntry e("gpg_TEST_dir");
- TEST_CHECK(e.exists());
- TEST_CHECK(e.is_directory());
-
- FSEntry package(e / "cat" / "not-signed");
- TEST_CHECK(package.exists());
- TEST_CHECK(package.is_directory());
-
- TestReporter r;
- TEST_CHECK(gpg_check(r, package, "gpg"));
- TEST_CHECK_EQUAL(r.count, 1u);
-
- }
- } test_gpg_check;
-}
diff --git a/paludis/repositories/e/qa/gpg_TEST_cleanup.sh b/paludis/repositories/e/qa/gpg_TEST_cleanup.sh
deleted file mode 100755
index 0bc4985..0000000
--- a/paludis/repositories/e/qa/gpg_TEST_cleanup.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-# vim: set ft=sh sw=4 sts=4 et :
-
-if [ -d gpg_TEST_dir ] ; then
- rm -fr gpg_TEST_dir
-else
- true
-fi
diff --git a/paludis/repositories/e/qa/gpg_TEST_setup.sh b/paludis/repositories/e/qa/gpg_TEST_setup.sh
deleted file mode 100755
index ce9c7f8..0000000
--- a/paludis/repositories/e/qa/gpg_TEST_setup.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-# vim: set ft=sh sw=4 sts=4 et :
-
-mkdir gpg_TEST_dir || exit 2
-cd gpg_TEST_dir || exit 3
-
-mkdir "cat" || exit 4
-mkdir "cat/not-signed" || exit 5
-touch "cat/not-signed/Manifest" || exit 6
diff --git a/paludis/repositories/e/qa/manifest.cc b/paludis/repositories/e/qa/manifest.cc
new file mode 100644
index 0000000..b65e607
--- /dev/null
+++ b/paludis/repositories/e/qa/manifest.cc
@@ -0,0 +1,288 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Fernando J. Pereda
+ * Copyright (c) 2008 David Leverton
+ *
+ * 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 <iostream>
+#include "manifest.hh"
+#include <paludis/qa.hh>
+#include <paludis/dep_tree.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/map.hh>
+#include <paludis/util/member_iterator-impl.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/sha1.hh>
+#include <paludis/util/sha256.hh>
+#include <paludis/util/rmd160.hh>
+#include <paludis/util/md5.hh>
+#include <paludis/repositories/e/e_repository.hh>
+#include <paludis/repositories/e/layout.hh>
+#include <paludis/repositories/e/manifest2_reader.hh>
+#include <fstream>
+#include <set>
+#include <map>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+namespace
+{
+ struct DistfilesCollector :
+ ConstVisitor<FetchableURISpecTree>,
+ ConstVisitor<FetchableURISpecTree>::VisitConstSequence<DistfilesCollector, AllDepSpec>,
+ ConstVisitor<FetchableURISpecTree>::VisitConstSequence<DistfilesCollector, UseDepSpec>
+ {
+ tr1::shared_ptr<const PackageID> id;
+ std::multimap<std::string, tr1::shared_ptr<const PackageID> > & distfiles;
+
+ using ConstVisitor<FetchableURISpecTree>::VisitConstSequence<DistfilesCollector, AllDepSpec>::visit_sequence;
+ using ConstVisitor<FetchableURISpecTree>::VisitConstSequence<DistfilesCollector, UseDepSpec>::visit_sequence;
+
+ DistfilesCollector(const tr1::shared_ptr<const PackageID> & i,
+ std::multimap<std::string, tr1::shared_ptr<const PackageID> > & d) :
+ id(i),
+ distfiles(d)
+ {
+ }
+
+ void visit_leaf(const URILabelsDepSpec &)
+ {
+ }
+
+ void visit_leaf(const FetchableURIDepSpec & u)
+ {
+ distfiles.insert(std::make_pair(u.filename(), id));
+ }
+ };
+
+ struct Manifest2Checker
+ {
+ QAReporter & reporter;
+ FSEntry dir;
+ std::string name;
+
+ FSEntry manifest;
+ tr1::shared_ptr<Map<FSEntry, std::string> > files;
+ tr1::shared_ptr<const PackageIDSequence> packages;
+
+ std::set<FSEntry> accounted_files;
+ std::multimap<std::string, tr1::shared_ptr<const PackageID> > distfiles;
+ std::set<std::string> accounted_distfiles;
+
+ Manifest2Checker(QAReporter & r, const FSEntry & d, const std::string & n,
+ const FSEntry & m, const tr1::shared_ptr<Map<FSEntry, std::string> > & f,
+ const tr1::shared_ptr<const PackageIDSequence> & p) :
+ reporter(r),
+ dir(d),
+ name(n),
+ manifest(m),
+ files(f),
+ packages(p)
+ {
+ }
+
+ void check_file(const Manifest2Entry & entry)
+ {
+ if ("DIST" == entry.type)
+ {
+ if (distfiles.end() == distfiles.find(entry.name))
+ {
+ QAMessage m(manifest, qaml_minor, name, "DIST file '" + entry.name + "' is not used by any package");
+ for (PackageIDSequence::ConstIterator it(packages->begin()),
+ it_end(packages->end()); it_end != it; ++it)
+ {
+ m = m.with_associated_id(*it);
+ if ((*it)->fetches_key())
+ m = m.with_associated_key(*it, (*it)->fetches_key());
+ }
+ reporter.message(m);
+ }
+
+ accounted_distfiles.insert(entry.name);
+ return;
+ }
+
+ FSEntry file("AUX" == entry.type ? dir / "files" / entry.name : dir / entry.name);
+ Map<FSEntry, std::string>::ConstIterator it(files->find(file));
+ if (files->end() == it)
+ {
+ reporter.message(QAMessage(file, qaml_normal, name, "File is not present but listed in the Manifest"));
+ return;
+ }
+
+ if (entry.type != it->second)
+ reporter.message(QAMessage(file, qaml_normal, name, "File is of type '" + it->second + "', but Manifest lists '" + entry.type + "'"));
+ if (entry.size != file.file_size())
+ reporter.message(QAMessage(file, qaml_normal, name, "File size is '" + stringify(file.file_size()) + "', but Manifest lists '" + stringify(entry.size) + "'"));
+
+ if (! entry.sha1.empty())
+ {
+ std::ifstream s(stringify(file).c_str());
+ SHA1 sha1(s);
+ if (entry.sha1 != sha1.hexsum())
+ reporter.message(QAMessage(file, qaml_normal, name, "File SHA1 is '" + sha1.hexsum() + "', but Manifest lists '" + entry.sha1 + "'"));
+
+ }
+
+ if (! entry.sha256.empty())
+ {
+ std::ifstream s(stringify(file).c_str());
+ SHA256 sha256(s);
+ if (entry.sha256 != sha256.hexsum())
+ reporter.message(QAMessage(file, qaml_normal, name, "File SHA256 is '" + sha256.hexsum() + "', but Manifest lists '" + entry.sha256 + "'"));
+
+ }
+
+ if (! entry.rmd160.empty())
+ {
+ std::ifstream s(stringify(file).c_str());
+ RMD160 rmd160(s);
+ if (entry.rmd160 != rmd160.hexsum())
+ reporter.message(QAMessage(file, qaml_normal, name, "File RMD160 is '" + rmd160.hexsum() + "', but Manifest lists '" + entry.rmd160 + "'"));
+
+ }
+
+ if (! entry.md5.empty())
+ {
+ std::ifstream s(stringify(file).c_str());
+ MD5 md5(s);
+ if (entry.md5 != md5.hexsum())
+ reporter.message(QAMessage(file, qaml_normal, name, "File MD5 is '" + md5.hexsum() + "', but Manifest lists '" + entry.md5 + "'"));
+
+ }
+
+ accounted_files.insert(it->first);
+ }
+
+ void check_unmanifested()
+ {
+ std::set<FSEntry> stray_files;
+ std::set_difference(first_iterator(files->begin()), first_iterator(files->end()),
+ accounted_files.begin(), accounted_files.end(),
+ std::inserter(stray_files, stray_files.end()));
+
+ for (std::set<FSEntry>::const_iterator it(stray_files.begin()),
+ it_end(stray_files.end()); it_end != it; ++it)
+ reporter.message(QAMessage(*it, qaml_normal, name, "File is not listed in the Manifest"));
+
+ std::set<std::string> unique_distfiles;
+ std::unique_copy(first_iterator(distfiles.begin()), first_iterator(distfiles.end()),
+ std::inserter(unique_distfiles, unique_distfiles.end()));
+ std::set<std::string> stray_distfiles;
+ std::set_difference(unique_distfiles.begin(), unique_distfiles.end(),
+ accounted_distfiles.begin(), accounted_distfiles.end(),
+ std::inserter(stray_distfiles, stray_distfiles.end()));
+
+ for (std::set<std::string>::const_iterator it(stray_distfiles.begin()),
+ it_end(stray_distfiles.end()); it_end != it; ++it)
+ {
+ QAMessage m(manifest, qaml_normal, name, "DIST file '" + *it + "' is not listed in the Manifest");
+ for (std::multimap<std::string, tr1::shared_ptr<const PackageID> >::const_iterator it2(distfiles.lower_bound(*it)),
+ it2_end(distfiles.upper_bound(*it)); it2_end != it2; ++it2)
+ m = m.with_associated_id(it2->second)
+ .with_associated_key(it2->second, it2->second->fetches_key());
+ reporter.message(m);
+ }
+ }
+ };
+}
+
+bool
+paludis::erepository::manifest_check(
+ QAReporter & reporter,
+ const FSEntry & dir,
+ const tr1::shared_ptr<const ERepository> & repo,
+ const QualifiedPackageName & qpn,
+ const std::string & name
+ )
+{
+ using namespace tr1::placeholders;
+
+ Context context("When performing check '" + name + "' using manifest_check on directory '" + stringify(dir) + "':");
+ Log::get_instance()->message(ll_debug, lc_context) << "manifest_check '"
+ << dir << "', " << name << "'";
+
+ try
+ {
+ FSEntry manifest(dir / "Manifest");
+
+ if (! manifest.is_regular_file())
+ {
+ reporter.message(QAMessage(manifest, qaml_normal, name, "Manifest is missing or not a regular file"));
+ return true;
+ }
+
+ tr1::shared_ptr<const PackageIDSequence> ids(repo->package_ids(qpn));
+ Manifest2Checker checker(reporter, dir, name, manifest, repo->layout()->manifest_files(qpn), ids);
+ for (PackageIDSequence::ConstIterator it(ids->begin()),
+ it_end(ids->end()); it_end != it; ++it)
+ {
+ if ((*it)->fetches_key())
+ {
+ DistfilesCollector c(*it, checker.distfiles);
+ (*it)->fetches_key()->value()->accept(c);
+ }
+ }
+
+ Manifest2Reader reader(manifest);
+ std::for_each(reader.begin(), reader.end(), tr1::bind(&Manifest2Checker::check_file, tr1::ref(checker), _1));
+ checker.check_unmanifested();
+
+ bool is_signed(false);
+ {
+ std::ifstream ff(stringify(manifest).c_str());
+ if (! ff)
+ {
+ reporter.message(QAMessage(manifest, qaml_normal, name, "Can't read Manifest file"));
+ return true;
+ }
+
+ std::string s;
+ if (std::getline(ff, s))
+ is_signed = (0 == s.compare("-----BEGIN PGP SIGNED MESSAGE-----"));
+ }
+
+ if (is_signed)
+ {
+ int status(run_command("gpg --verify " + stringify(manifest) + " >/dev/null 2>/dev/null"));
+
+ if (1 == status)
+ reporter.message(QAMessage(manifest, qaml_normal, name, "Broken Manifest signature"));
+ else if (2 == status)
+ reporter.message(QAMessage(manifest, qaml_maybe, name, "Manifest signature cannot be verified"));
+ }
+ else
+ reporter.message(QAMessage(manifest, qaml_minor, name, "Manifest not signed"));
+ }
+ catch (const Exception & e)
+ {
+ reporter.message(QAMessage(dir, qaml_severe, name,
+ "Caught exception '" + stringify(e.message()) + "' ("
+ + stringify(e.what()) + ") when checking Manifest for '" + stringify(qpn) + "'"));
+ }
+
+ return true;
+}
+
diff --git a/paludis/repositories/e/qa/gpg.hh b/paludis/repositories/e/qa/manifest.hh
index c4764e9..f71d623 100644
--- a/paludis/repositories/e/qa/gpg.hh
+++ b/paludis/repositories/e/qa/manifest.hh
@@ -17,8 +17,8 @@
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_QA_GPG_HH
-#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_QA_GPG_HH 1
+#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_QA_MANIFEST_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_QA_MANIFEST_HH 1
#include <paludis/repositories/e/qa/qa_controller.hh>
@@ -26,9 +26,11 @@ namespace paludis
{
namespace erepository
{
- bool gpg_check(
+ bool manifest_check(
QAReporter &,
const FSEntry & dir,
+ const tr1::shared_ptr<const ERepository> &,
+ const QualifiedPackageName &,
const std::string & s
) PALUDIS_VISIBLE;
}
diff --git a/paludis/repositories/e/qa/manifest_TEST.cc b/paludis/repositories/e/qa/manifest_TEST.cc
new file mode 100644
index 0000000..7252b54
--- /dev/null
+++ b/paludis/repositories/e/qa/manifest_TEST.cc
@@ -0,0 +1,287 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Fernando J. Pereda
+ * Copyright (c) 2008 David Leverton
+ *
+ * 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 "manifest.hh"
+#include <paludis/qa.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/fd_holder.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/map.hh>
+#include <paludis/environments/test/test_environment.hh>
+#include <paludis/repositories/e/make_ebuild_repository.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+using namespace paludis;
+using namespace paludis::erepository;
+using namespace test;
+
+namespace
+{
+ struct TestReporter :
+ QAReporter
+ {
+ unsigned count;
+
+ TestReporter() :
+ count(0)
+ {
+ }
+
+ void message(const QAMessage &)
+ {
+ ++count;
+ }
+
+ void status(const std::string &)
+ {
+ }
+ };
+}
+
+namespace test_cases
+{
+ struct GPGCheckTest : TestCase
+ {
+ GPGCheckTest() : TestCase("signed Manifest") { }
+
+ bool skip() const
+ {
+ return (0 != run_command("gpg --help >/dev/null 2>/dev/null"));
+ }
+
+ 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", "manifest_TEST_dir/repo1");
+ keys->insert("profiles", stringify(FSEntry::cwd() / "manifest_TEST_dir/repo1/profiles/test"));
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ QualifiedPackageName qpn("cat/not-signed");
+ FSEntry dir(repo->layout()->package_directory(qpn));
+
+ TestReporter r;
+ TEST_CHECK(manifest_check(r, dir, repo, qpn, "manifest"));
+ TEST_CHECK_EQUAL(r.count, 1u);
+
+ }
+ } test_gpg_check;
+
+ struct ManifestGoodTest : TestCase
+ {
+ ManifestGoodTest() : TestCase("Manifest good") { }
+
+ 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", "manifest_TEST_dir/repo1");
+ keys->insert("profiles", stringify(FSEntry::cwd() / "manifest_TEST_dir/repo1/profiles/test"));
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ QualifiedPackageName qpn("cat/good");
+ FSEntry dir(repo->layout()->package_directory(qpn));
+
+ TestReporter r;
+ TEST_CHECK(manifest_check(r, dir, repo, qpn, "manifest"));
+ TEST_CHECK_EQUAL(r.count, 1u);
+ }
+ } test_manifest_good;
+
+ struct ManifestBadTypeTest : TestCase
+ {
+ ManifestBadTypeTest() : TestCase("Manifest bad type") { }
+
+ 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", "manifest_TEST_dir/repo1");
+ keys->insert("profiles", stringify(FSEntry::cwd() / "manifest_TEST_dir/repo1/profiles/test"));
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ QualifiedPackageName qpn("cat/bad-type");
+ FSEntry dir(repo->layout()->package_directory(qpn));
+
+ TestReporter r;
+ TEST_CHECK(manifest_check(r, dir, repo, qpn, "manifest"));
+ TEST_CHECK_EQUAL(r.count, 3u);
+ }
+ } test_manifest_bad_type;
+
+ struct ManifestBadSizeTest : TestCase
+ {
+ ManifestBadSizeTest() : TestCase("Manifest bad size") { }
+
+ 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", "manifest_TEST_dir/repo1");
+ keys->insert("profiles", stringify(FSEntry::cwd() / "manifest_TEST_dir/repo1/profiles/test"));
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ QualifiedPackageName qpn("cat/bad-size");
+ FSEntry dir(repo->layout()->package_directory(qpn));
+
+ TestReporter r;
+ TEST_CHECK(manifest_check(r, dir, repo, qpn, "manifest"));
+ TEST_CHECK_EQUAL(r.count, 2u);
+ }
+ } test_manifest_bad_size;
+
+ struct ManifestBadHashTest : TestCase
+ {
+ ManifestBadHashTest() : TestCase("Manifest bad hash") { }
+
+ 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", "manifest_TEST_dir/repo1");
+ keys->insert("profiles", stringify(FSEntry::cwd() / "manifest_TEST_dir/repo1/profiles/test"));
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ QualifiedPackageName qpn("cat/bad-hash");
+ FSEntry dir(repo->layout()->package_directory(qpn));
+
+ TestReporter r;
+ TEST_CHECK(manifest_check(r, dir, repo, qpn, "manifest"));
+ TEST_CHECK_EQUAL(r.count, 5u);
+ }
+ } test_manifest_bad_hash;
+
+ struct ManifestMissingFileTest : TestCase
+ {
+ ManifestMissingFileTest() : TestCase("Manifest missing file") { }
+
+ 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", "manifest_TEST_dir/repo1");
+ keys->insert("profiles", stringify(FSEntry::cwd() / "manifest_TEST_dir/repo1/profiles/test"));
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ QualifiedPackageName qpn("cat/missing");
+ FSEntry dir(repo->layout()->package_directory(qpn));
+
+ TestReporter r;
+ TEST_CHECK(manifest_check(r, dir, repo, qpn, "manifest"));
+ TEST_CHECK_EQUAL(r.count, 2u);
+ }
+ } test_manifest_missing_file;
+
+ struct ManifestStrayFileTest : TestCase
+ {
+ ManifestStrayFileTest() : TestCase("Manifest stray file") { }
+
+ 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", "manifest_TEST_dir/repo1");
+ keys->insert("profiles", stringify(FSEntry::cwd() / "manifest_TEST_dir/repo1/profiles/test"));
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ QualifiedPackageName qpn("cat/stray");
+ FSEntry dir(repo->layout()->package_directory(qpn));
+
+ TestReporter r;
+ TEST_CHECK(manifest_check(r, dir, repo, qpn, "manifest"));
+ TEST_CHECK_EQUAL(r.count, 2u);
+ }
+ } test_manifest_stray_file;
+
+ struct ManifestUnusedDistfileTest : TestCase
+ {
+ ManifestUnusedDistfileTest() : TestCase("Manifest unused distfile file") { }
+
+ 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", "manifest_TEST_dir/repo1");
+ keys->insert("profiles", stringify(FSEntry::cwd() / "manifest_TEST_dir/repo1/profiles/test"));
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ QualifiedPackageName qpn("cat/unused-distfile");
+ FSEntry dir(repo->layout()->package_directory(qpn));
+
+ TestReporter r;
+ TEST_CHECK(manifest_check(r, dir, repo, qpn, "manifest"));
+ TEST_CHECK_EQUAL(r.count, 2u);
+ }
+ } test_manifest_unused_distfile;
+
+ struct ManifestUndigestedDistfileTest : TestCase
+ {
+ ManifestUndigestedDistfileTest() : TestCase("Manifest undigested distfile file") { }
+
+ 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", "manifest_TEST_dir/repo1");
+ keys->insert("profiles", stringify(FSEntry::cwd() / "manifest_TEST_dir/repo1/profiles/test"));
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ QualifiedPackageName qpn("cat/undigested-distfile");
+ FSEntry dir(repo->layout()->package_directory(qpn));
+
+ TestReporter r;
+ TEST_CHECK(manifest_check(r, dir, repo, qpn, "manifest"));
+ TEST_CHECK_EQUAL(r.count, 2u);
+ }
+ } test_manifest_undigested_distfile;
+}
+
diff --git a/paludis/repositories/e/qa/manifest_TEST_cleanup.sh b/paludis/repositories/e/qa/manifest_TEST_cleanup.sh
new file mode 100755
index 0000000..9f08606
--- /dev/null
+++ b/paludis/repositories/e/qa/manifest_TEST_cleanup.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d manifest_TEST_dir ] ; then
+ rm -fr manifest_TEST_dir
+else
+ true
+fi
diff --git a/paludis/repositories/e/qa/manifest_TEST_setup.sh b/paludis/repositories/e/qa/manifest_TEST_setup.sh
new file mode 100755
index 0000000..2033a6f
--- /dev/null
+++ b/paludis/repositories/e/qa/manifest_TEST_setup.sh
@@ -0,0 +1,145 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir -p manifest_TEST_dir/repo1 || exit 2
+cd manifest_TEST_dir/repo1 || exit 3
+
+mkdir -p {eclass,distfiles,profiles/test,cat-one/{visible,masked,needs-masked}} || exit 1
+echo "repo1" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat
+END
+cat <<END > profiles/test/make.defaults
+ARCH=test
+ACCEPT_KEYWORDS=test
+END
+cat <<END > profiles/profiles.desc
+test test/ stable
+END
+
+mkdir "cat" || exit 4
+mkdir "cat/not-signed" || exit 5
+touch "cat/not-signed/Manifest" || exit 6
+
+mkdir "cat/good" || exit 7
+mkdir "cat/good/files" || exit 8
+echo foo >cat/good/ChangeLog || exit 10
+echo foo >cat/good/files/foo.patch || exit 11
+cat >cat/good/good-0.ebuild <<END || exit 9
+SLOT="0"
+SRC_URI="monkey.tar.bz2"
+END
+cat >cat/good/Manifest <<END || exit 12
+DIST monkey.tar.bz2 7 SHA1 744a9a056f145b86339221bb457aa57129f55bc2 SHA256 5a6e48105fea75ccccc66a038318f398c42761495d738786dc8a6d43179aa16a RMD160 7dbf02c6e0bbfda1550fc7ba0ebc4fdd866e2d3c MD5 2f548f61bd37f628077e552ae1537be2
+EBUILD good-0.ebuild 34 SHA1 6834113b3fed0c3833d3b7a42f7ead07c13209e8 SHA256 b68ae58845b2f3d15dad3eae2f02aaa2cfdbb14140c7d4a537a6bf4417fb0b30 RMD160 7bf5c52f5c2acf42d66961af3de9c97e4d2b1207 MD5 75fa0dc852d3c76e4741c650465bfa6c
+MISC ChangeLog 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+AUX foo.patch 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+END
+
+mkdir "cat/bad-type" || exit 7
+mkdir "cat/bad-type/files" || exit 8
+echo foo >cat/bad-type/ChangeLog || exit 10
+echo foo >cat/bad-type/files/foo.patch || exit 11
+cat >cat/bad-type/bad-type-0.ebuild <<END || exit 9
+SLOT="0"
+SRC_URI="monkey.tar.bz2"
+END
+cat >cat/bad-type/Manifest <<END || exit 12
+DIST monkey.tar.bz2 7 SHA1 744a9a056f145b86339221bb457aa57129f55bc2 SHA256 5a6e48105fea75ccccc66a038318f398c42761495d738786dc8a6d43179aa16a RMD160 7dbf02c6e0bbfda1550fc7ba0ebc4fdd866e2d3c MD5 2f548f61bd37f628077e552ae1537be2
+MISC bad-type-0.ebuild 34 SHA1 6834113b3fed0c3833d3b7a42f7ead07c13209e8 SHA256 b68ae58845b2f3d15dad3eae2f02aaa2cfdbb14140c7d4a537a6bf4417fb0b30 RMD160 7bf5c52f5c2acf42d66961af3de9c97e4d2b1207 MD5 75fa0dc852d3c76e4741c650465bfa6c
+EBUILD ChangeLog 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+AUX foo.patch 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+END
+
+mkdir "cat/bad-size" || exit 7
+mkdir "cat/bad-size/files" || exit 8
+echo foo >cat/bad-size/ChangeLog || exit 10
+echo foo >cat/bad-size/files/foo.patch || exit 11
+cat >cat/bad-size/bad-size-0.ebuild <<END || exit 9
+SLOT="0"
+SRC_URI="monkey.tar.bz2"
+END
+cat >cat/bad-size/Manifest <<END || exit 12
+DIST monkey.tar.bz2 7 SHA1 744a9a056f145b86339221bb457aa57129f55bc2 SHA256 5a6e48105fea75ccccc66a038318f398c42761495d738786dc8a6d43179aa16a RMD160 7dbf02c6e0bbfda1550fc7ba0ebc4fdd866e2d3c MD5 2f548f61bd37f628077e552ae1537be2
+EBUILD bad-size-0.ebuild 35 SHA1 6834113b3fed0c3833d3b7a42f7ead07c13209e8 SHA256 b68ae58845b2f3d15dad3eae2f02aaa2cfdbb14140c7d4a537a6bf4417fb0b30 RMD160 7bf5c52f5c2acf42d66961af3de9c97e4d2b1207 MD5 75fa0dc852d3c76e4741c650465bfa6c
+MISC ChangeLog 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+AUX foo.patch 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+END
+
+mkdir "cat/bad-hash" || exit 7
+mkdir "cat/bad-hash/files" || exit 8
+echo foo >cat/bad-hash/ChangeLog || exit 10
+echo foo >cat/bad-hash/files/foo.patch || exit 11
+cat >cat/bad-hash/bad-hash-0.ebuild <<END || exit 9
+SLOT="0"
+SRC_URI="monkey.tar.bz2"
+END
+cat >cat/bad-hash/Manifest <<END || exit 12
+DIST monkey.tar.bz2 7 SHA1 744a9a056f145b86339221bb457aa57129f55bc2 SHA256 5a6e48105fea75ccccc66a038318f398c42761495d738786dc8a6d43179aa16a RMD160 7dbf02c6e0bbfda1550fc7ba0ebc4fdd866e2d3c MD5 2f548f61bd37f628077e552ae1537be2
+EBUILD bad-hash-0.ebuild 34 SHA1 7834113b3fed0c3833d3b7a42f7ead07c13209e8 SHA256 c68ae58845b2f3d15dad3eae2f02aaa2cfdbb14140c7d4a537a6bf4417fb0b30 RMD160 7bf5c52f5c2acf42d66961af3de9c97e4d2b1207 MD5 75fa0dc852d3c76e4741c650465bfa6c
+MISC ChangeLog 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 fc0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+AUX foo.patch 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 e3b07384d113edec49eaa6238ad5ff00
+END
+
+mkdir "cat/missing" || exit 7
+mkdir "cat/missing/files" || exit 8
+echo foo >cat/missing/ChangeLog || exit 10
+echo foo >cat/missing/files/foo.patch || exit 11
+cat >cat/missing/missing-0.ebuild <<END || exit 9
+SLOT="0"
+SRC_URI="monkey.tar.bz2"
+END
+cat >cat/missing/Manifest <<END || exit 12
+DIST monkey.tar.bz2 7 SHA1 744a9a056f145b86339221bb457aa57129f55bc2 SHA256 5a6e48105fea75ccccc66a038318f398c42761495d738786dc8a6d43179aa16a RMD160 7dbf02c6e0bbfda1550fc7ba0ebc4fdd866e2d3c MD5 2f548f61bd37f628077e552ae1537be2
+EBUILD missing-0.ebuild 34 SHA1 6834113b3fed0c3833d3b7a42f7ead07c13209e8 SHA256 b68ae58845b2f3d15dad3eae2f02aaa2cfdbb14140c7d4a537a6bf4417fb0b30 RMD160 7bf5c52f5c2acf42d66961af3de9c97e4d2b1207 MD5 75fa0dc852d3c76e4741c650465bfa6c
+MISC ChangeLog 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+AUX foo.patch 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+AUX bar.patch 4 SHA1 e242ed3bffccdf271b7fbaf34ed72d089537b42f SHA256 7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730 RMD160 7d4e874a231f57b72509087d1e509942fdb6eac6 MD5 c157a79031e1c40f85931829bc5fc552
+END
+
+mkdir "cat/stray" || exit 7
+mkdir "cat/stray/files" || exit 8
+echo foo >cat/stray/ChangeLog || exit 10
+echo foo >cat/stray/files/foo.patch || exit 11
+echo foo >cat/stray/metadata.xml || exit 13
+cat >cat/stray/stray-0.ebuild <<END || exit 9
+SLOT="0"
+SRC_URI="monkey.tar.bz2"
+END
+cat >cat/stray/Manifest <<END || exit 12
+DIST monkey.tar.bz2 7 SHA1 744a9a056f145b86339221bb457aa57129f55bc2 SHA256 5a6e48105fea75ccccc66a038318f398c42761495d738786dc8a6d43179aa16a RMD160 7dbf02c6e0bbfda1550fc7ba0ebc4fdd866e2d3c MD5 2f548f61bd37f628077e552ae1537be2
+EBUILD stray-0.ebuild 34 SHA1 6834113b3fed0c3833d3b7a42f7ead07c13209e8 SHA256 b68ae58845b2f3d15dad3eae2f02aaa2cfdbb14140c7d4a537a6bf4417fb0b30 RMD160 7bf5c52f5c2acf42d66961af3de9c97e4d2b1207 MD5 75fa0dc852d3c76e4741c650465bfa6c
+MISC ChangeLog 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+AUX foo.patch 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+END
+
+mkdir "cat/unused-distfile" || exit 7
+mkdir "cat/unused-distfile/files" || exit 8
+echo foo >cat/unused-distfile/ChangeLog || exit 10
+echo foo >cat/unused-distfile/files/foo.patch || exit 11
+cat >cat/unused-distfile/unused-distfile-0.ebuild <<END || exit 9
+SLOT="0"
+SRC_URI="monkey.tar.bz2"
+END
+cat >cat/unused-distfile/Manifest <<END || exit 12
+DIST monkey.tar.bz2 7 SHA1 744a9a056f145b86339221bb457aa57129f55bc2 SHA256 5a6e48105fea75ccccc66a038318f398c42761495d738786dc8a6d43179aa16a RMD160 7dbf02c6e0bbfda1550fc7ba0ebc4fdd866e2d3c MD5 2f548f61bd37f628077e552ae1537be2
+DIST donkey.tar.bz2 7 SHA1 726a4b06f832dc6d671285b492a81cebd7e98cb6 SHA256 45814cf76274a6bfdf2993b1d275a29faf1e1f8fa9fff6cf8c4f4c893ede2258 RMD160 73ee0ca7277576f1e316fd7097ebd3f02bcacf83 MD5 f5fa31b4e964cc2a86140bc2a2e11a13
+EBUILD unused-distfile-0.ebuild 34 SHA1 6834113b3fed0c3833d3b7a42f7ead07c13209e8 SHA256 b68ae58845b2f3d15dad3eae2f02aaa2cfdbb14140c7d4a537a6bf4417fb0b30 RMD160 7bf5c52f5c2acf42d66961af3de9c97e4d2b1207 MD5 75fa0dc852d3c76e4741c650465bfa6c
+MISC ChangeLog 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+AUX foo.patch 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+END
+
+mkdir "cat/undigested-distfile" || exit 7
+mkdir "cat/undigested-distfile/files" || exit 8
+echo foo >cat/undigested-distfile/ChangeLog || exit 10
+echo foo >cat/undigested-distfile/files/foo.patch || exit 11
+cat >cat/undigested-distfile/undigested-distfile-0.ebuild <<END || exit 9
+SLOT="0"
+SRC_URI="monkey.tar.bz2"
+END
+cat >cat/undigested-distfile/Manifest <<END || exit 12
+EBUILD undigested-distfile-0.ebuild 34 SHA1 6834113b3fed0c3833d3b7a42f7ead07c13209e8 SHA256 b68ae58845b2f3d15dad3eae2f02aaa2cfdbb14140c7d4a537a6bf4417fb0b30 RMD160 7bf5c52f5c2acf42d66961af3de9c97e4d2b1207 MD5 75fa0dc852d3c76e4741c650465bfa6c
+MISC ChangeLog 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+AUX foo.patch 4 SHA1 f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 SHA256 b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c RMD160 ec0af898b7b1ab23ccf8c5036cb97e9ab23442ab MD5 d3b07384d113edec49eaa6238ad5ff00
+END
+
diff --git a/paludis/repositories/e/qa/qa_checks.cc b/paludis/repositories/e/qa/qa_checks.cc
index 0f87f42..6cd561f 100644
--- a/paludis/repositories/e/qa/qa_checks.cc
+++ b/paludis/repositories/e/qa/qa_checks.cc
@@ -22,7 +22,7 @@
#include <paludis/util/instantiation_policy-impl.hh>
#include <paludis/repositories/e/qa/stray_files.hh>
-#include <paludis/repositories/e/qa/gpg.hh>
+#include <paludis/repositories/e/qa/manifest.hh>
#include <paludis/repositories/e/qa/ebuild_count.hh>
#include <paludis/repositories/e/qa/changelog.hh>
#include <paludis/repositories/e/qa/misc_files.hh>
@@ -116,8 +116,8 @@ QAChecks::QAChecks() :
_imp->category_dir_checks_group->add_check("stray_category_dir_files",
tr1::bind(stray_files_check, _2, _4, _1, is_stray_at_category_dir, "stray_category_dir_files"));
- _imp->package_dir_checks_group->add_check("gpg",
- tr1::bind(gpg_check, _2, _1, "gpg"));
+ _imp->package_dir_checks_group->add_check("manifest",
+ tr1::bind(manifest_check, _2, _1, _4, _5, "manifest"));
_imp->package_dir_checks_group->add_check("ebuild_count",
tr1::bind(ebuild_count_check, _2, _1, _4, _5, "ebuild_count"));