aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-04-28 19:15:59 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-04-28 19:15:59 +0000
commita7b852f0bd6798cff22d2ade85a764e9af8944bf (patch)
tree42f4125284a24fc638ea50ad7b192aa6d99e586c
parent74e6eacacc89b3f62e3953cd74092b51d5d40cd1 (diff)
downloadpaludis-a7b852f0bd6798cff22d2ade85a764e9af8944bf.tar.gz
paludis-a7b852f0bd6798cff22d2ade85a764e9af8944bf.tar.xz
Provide a way of querying the contents of a package. Add --owner and --contents actions
-rw-r--r--doc/doc_main.doxygen5
-rw-r--r--paludis/contents.cc58
-rw-r--r--paludis/contents.hh168
-rw-r--r--paludis/fake_repository.cc9
-rw-r--r--paludis/fake_repository.hh4
-rw-r--r--paludis/files.m41
-rw-r--r--paludis/package_database.cc14
-rw-r--r--paludis/package_database.hh6
-rw-r--r--paludis/portage_repository.cc7
-rw-r--r--paludis/portage_repository.hh4
-rw-r--r--paludis/repository.hh28
-rw-r--r--paludis/vdb_repository.cc87
-rw-r--r--paludis/vdb_repository.hh4
-rw-r--r--src/Makefile.am2
-rw-r--r--src/colour.hh12
-rw-r--r--src/command_line.cc7
-rw-r--r--src/command_line.hh17
-rw-r--r--src/contents.cc144
-rw-r--r--src/contents.hh30
-rw-r--r--src/owner.cc130
-rw-r--r--src/owner.hh30
-rw-r--r--src/paludis.cc20
22 files changed, 784 insertions, 3 deletions
diff --git a/doc/doc_main.doxygen b/doc/doc_main.doxygen
index 9509034..e224c2c 100644
--- a/doc/doc_main.doxygen
+++ b/doc/doc_main.doxygen
@@ -57,6 +57,11 @@
* \ingroup grplibpaludis
*/
+/** \defgroup grpcontents Contents
+ *
+ * \ingroup grplibpaludis
+ */
+
// ----- grpconfigfile Subgroups -----
/** \defgroup grpkvconfigfile Key/Value configuration file
diff --git a/paludis/contents.cc b/paludis/contents.cc
new file mode 100644
index 0000000..ad9acfa
--- /dev/null
+++ b/paludis/contents.cc
@@ -0,0 +1,58 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * 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 "contents.hh"
+
+/** \file
+ * Implementation for Contents classes.
+ *
+ * \ingroup grpcontents
+ */
+
+using namespace paludis;
+
+ContentsEntry::~ContentsEntry()
+{
+}
+
+ContentsFileEntry::ContentsFileEntry(const std::string & name) :
+ ContentsEntry(name)
+{
+}
+
+ContentsDirEntry::ContentsDirEntry(const std::string & name) :
+ ContentsEntry(name)
+{
+}
+
+ContentsMiscEntry::ContentsMiscEntry(const std::string & name) :
+ ContentsEntry(name)
+{
+}
+
+ContentsSymEntry::ContentsSymEntry(const std::string & name, const std::string & target) :
+ ContentsEntry(name),
+ _target(target)
+{
+}
+
+Contents::Contents()
+{
+}
+
diff --git a/paludis/contents.hh b/paludis/contents.hh
new file mode 100644
index 0000000..2cc7414
--- /dev/null
+++ b/paludis/contents.hh
@@ -0,0 +1,168 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * 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_CONTENTS_HH
+#define PALUDIS_GUARD_PALUDIS_CONTENTS_HH 1
+
+#include <paludis/util/visitor.hh>
+#include <paludis/util/counted_ptr.hh>
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <string>
+
+/** \file
+ * Declarations for the Contents classes.
+ *
+ * \ingroup grpcontents
+ */
+
+namespace paludis
+{
+ struct ContentsEntry;
+ struct ContentsFileEntry;
+ struct ContentsDirEntry;
+ struct ContentsSymEntry;
+ struct ContentsMiscEntry;
+
+ typedef VisitorTypes<ContentsFileEntry *, ContentsDirEntry *,
+ ContentsSymEntry *, ContentsMiscEntry *> ContentsVisitorTypes;
+
+ /**
+ * Base class for a contents entry.
+ *
+ * \ingroup grpcontents
+ */
+ class ContentsEntry :
+ private InstantiationPolicy<ContentsEntry, instantiation_method::NonCopyableTag>,
+ public InternalCounted<ContentsEntry>,
+ public virtual VisitableInterface<ContentsVisitorTypes>
+ {
+ private:
+ std::string _name;
+
+ protected:
+ ContentsEntry(const std::string & name) :
+ _name(name)
+ {
+ }
+
+ public:
+ virtual ~ContentsEntry();
+
+ std::string name() const
+ {
+ return _name;
+ }
+ };
+
+ /**
+ * A file contents entry.
+ *
+ * \ingroup grpcontents
+ */
+ class ContentsFileEntry :
+ public ContentsEntry,
+ public Visitable<ContentsFileEntry, ContentsVisitorTypes>
+ {
+ public:
+ ContentsFileEntry(const std::string & name);
+ };
+
+ /**
+ * A directory contents entry.
+ *
+ * \ingroup grpcontents
+ */
+ class ContentsDirEntry :
+ public ContentsEntry,
+ public Visitable<ContentsDirEntry, ContentsVisitorTypes>
+ {
+ public:
+ ContentsDirEntry(const std::string & name);
+ };
+
+ /**
+ * A misc contents entry.
+ *
+ * \ingroup grpcontents
+ */
+ class ContentsMiscEntry :
+ public ContentsEntry,
+ public Visitable<ContentsMiscEntry, ContentsVisitorTypes>
+ {
+ public:
+ ContentsMiscEntry(const std::string & name);
+ };
+
+ /**
+ * A sym contents entry.
+ *
+ * \ingroup grpcontents
+ */
+ class ContentsSymEntry :
+ public ContentsEntry,
+ public Visitable<ContentsSymEntry, ContentsVisitorTypes>
+ {
+ private:
+ std::string _target;
+
+ public:
+ ContentsSymEntry(const std::string & name, const std::string & target);
+
+ std::string target() const
+ {
+ return _target;
+ }
+ };
+
+ /**
+ * A package's contents.
+ *
+ * \ingroup grpcontents
+ */
+ class Contents :
+ private InstantiationPolicy<Contents, instantiation_method::NonCopyableTag>,
+ public InternalCounted<Contents>
+ {
+ private:
+ std::list<ContentsEntry::ConstPointer> _c;
+
+ public:
+ Contents();
+
+ void add(ContentsEntry::ConstPointer c)
+ {
+ _c.push_back(c);
+ }
+
+ typedef std::list<ContentsEntry::ConstPointer>::const_iterator Iterator;
+
+ Iterator begin() const
+ {
+ return _c.begin();
+ }
+
+ Iterator end() const
+ {
+ return _c.end();
+ }
+ };
+}
+
+#endif
diff --git a/paludis/fake_repository.cc b/paludis/fake_repository.cc
index eb593eb..3038f68 100644
--- a/paludis/fake_repository.cc
+++ b/paludis/fake_repository.cc
@@ -172,6 +172,15 @@ FakeRepository::do_version_metadata(
return _imp->metadata.find(stringify(c) + "/" + stringify(p) + "-" + stringify(v))->second;
}
+Contents::ConstPointer
+FakeRepository::do_contents(
+ const CategoryNamePart & c, const PackageNamePart & p, const VersionSpec & v) const
+{
+ if (! has_version(c, p, v))
+ throw InternalError(PALUDIS_HERE, "no version");
+ return Contents::Pointer(new Contents);
+}
+
bool
FakeRepository::do_query_repository_masks(const CategoryNamePart &,
const PackageNamePart &, const VersionSpec &) const
diff --git a/paludis/fake_repository.hh b/paludis/fake_repository.hh
index a816dfc..1e8dece 100644
--- a/paludis/fake_repository.hh
+++ b/paludis/fake_repository.hh
@@ -61,6 +61,10 @@ namespace paludis
const CategoryNamePart &, const PackageNamePart &,
const VersionSpec &) const;
+ virtual Contents::ConstPointer do_contents(
+ const CategoryNamePart &, const PackageNamePart &,
+ const VersionSpec &) const;
+
virtual bool do_query_repository_masks(const CategoryNamePart &,
const PackageNamePart &, const VersionSpec &) const;
diff --git a/paludis/files.m4 b/paludis/files.m4
index 5f11b0c..7dfd788 100644
--- a/paludis/files.m4
+++ b/paludis/files.m4
@@ -10,6 +10,7 @@ dnl on this file at present...
add(`about', `hh', `test')
add(`config_file', `hh', `cc', `test', `testscript')
+add(`contents', `hh', `cc')
add(`default_config', `hh', `cc')
add(`default_environment', `hh', `cc')
add(`dep_atom', `hh', `cc', `test')
diff --git a/paludis/package_database.cc b/paludis/package_database.cc
index 99f844b..6504614 100644
--- a/paludis/package_database.cc
+++ b/paludis/package_database.cc
@@ -131,6 +131,20 @@ PackageDatabase::fetch_metadata(const PackageDatabaseEntry & e) const
e.get<pde_name>().get<qpn_package>(), e.get<pde_version>());
}
+Contents::ConstPointer
+PackageDatabase::fetch_contents(const PackageDatabaseEntry & e) const
+{
+ const Repository::ConstPointer rr(fetch_repository(e.get<pde_repository>()));
+ if (! rr->has_category_named(e.get<pde_name>().get<qpn_category>()))
+ throw NoSuchPackageError(stringify(e.get<pde_name>()));
+ if (! rr->has_package_named(e.get<pde_name>()))
+ throw NoSuchPackageError(stringify(e.get<pde_name>()));
+ if (! rr->has_version(e.get<pde_name>(), e.get<pde_version>()))
+ throw NoSuchVersionError(stringify(e.get<pde_name>()), e.get<pde_version>());
+ return rr->contents(e.get<pde_name>().get<qpn_category>(),
+ e.get<pde_name>().get<qpn_package>(), e.get<pde_version>());
+}
+
Repository::ConstPointer
PackageDatabase::fetch_repository(const RepositoryName & n) const
{
diff --git a/paludis/package_database.hh b/paludis/package_database.hh
index a106893..b10d0ef 100644
--- a/paludis/package_database.hh
+++ b/paludis/package_database.hh
@@ -35,6 +35,7 @@
#include <paludis/version_metadata.hh>
#include <paludis/version_spec.hh>
#include <paludis/package_database_entry.hh>
+#include <paludis/contents.hh>
#include <ostream>
#include <algorithm>
@@ -288,6 +289,11 @@ namespace paludis
VersionMetadata::ConstPointer fetch_metadata(const PackageDatabaseEntry &) const;
/**
+ * Fetch the contents for a particular item.
+ */
+ Contents::ConstPointer fetch_contents(const PackageDatabaseEntry &) const;
+
+ /**
* Fetch a named repository.
*/
Repository::ConstPointer fetch_repository(const RepositoryName &) const;
diff --git a/paludis/portage_repository.cc b/paludis/portage_repository.cc
index 6b5d29b..9dc2df9 100644
--- a/paludis/portage_repository.cc
+++ b/paludis/portage_repository.cc
@@ -863,6 +863,13 @@ PortageRepository::do_version_metadata(
return result;
}
+Contents::ConstPointer
+PortageRepository::do_contents(
+ const CategoryNamePart &, const PackageNamePart &, const VersionSpec &) const
+{
+ return Contents::Pointer(new Contents);
+}
+
bool
PortageRepository::do_query_repository_masks(const CategoryNamePart & c,
const PackageNamePart & p, const VersionSpec & v) const
diff --git a/paludis/portage_repository.hh b/paludis/portage_repository.hh
index 8ee88da..e42390e 100644
--- a/paludis/portage_repository.hh
+++ b/paludis/portage_repository.hh
@@ -129,6 +129,10 @@ namespace paludis
const CategoryNamePart &, const PackageNamePart &,
const VersionSpec &) const;
+ virtual Contents::ConstPointer do_contents(
+ const CategoryNamePart &, const PackageNamePart &,
+ const VersionSpec &) const;
+
virtual bool do_query_repository_masks(const CategoryNamePart &,
const PackageNamePart &, const VersionSpec &) const;
diff --git a/paludis/repository.hh b/paludis/repository.hh
index 197e066..b808d7d 100644
--- a/paludis/repository.hh
+++ b/paludis/repository.hh
@@ -29,6 +29,7 @@
#include <paludis/version_metadata.hh>
#include <paludis/version_spec.hh>
#include <paludis/package_database_entry.hh>
+#include <paludis/contents.hh>
#include <map>
#include <string>
@@ -112,6 +113,13 @@ namespace paludis
const VersionSpec &) const = 0;
/**
+ * Override in descendents: fetch the contents.
+ */
+ virtual Contents::ConstPointer do_contents(
+ const CategoryNamePart &, const PackageNamePart &,
+ const VersionSpec &) const = 0;
+
+ /**
* Override in descendents: check for a version.
*/
virtual bool do_has_version(const CategoryNamePart &,
@@ -319,6 +327,26 @@ namespace paludis
}
/**
+ * Fetch contents.
+ */
+ Contents::ConstPointer contents(
+ const CategoryNamePart & c, const PackageNamePart & p,
+ const VersionSpec & v) const
+ {
+ return do_contents(c, p, v);
+ }
+
+ /**
+ * Fetch contents (override for QualifiedPackageName).
+ */
+ Contents::ConstPointer contents(
+ const QualifiedPackageName & q,
+ const VersionSpec & v) const
+ {
+ return do_contents(q.get<qpn_category>(), q.get<qpn_package>(), v);
+ }
+
+ /**
* Query repository masks.
*/
bool query_repository_masks(const CategoryNamePart & c, const PackageNamePart & p,
diff --git a/paludis/vdb_repository.cc b/paludis/vdb_repository.cc
index b7ad45b..556e4c8 100644
--- a/paludis/vdb_repository.cc
+++ b/paludis/vdb_repository.cc
@@ -459,6 +459,9 @@ VDBRepository::do_version_metadata(
Context context("When fetching metadata for " + stringify(c) + "/" + stringify(p) +
"-" + stringify(v));
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
std::pair<std::vector<VDBEntry>::iterator, std::vector<VDBEntry>::iterator>
r(std::equal_range(_imp->entries.begin(), _imp->entries.end(), std::make_pair(
QualifiedPackageName(c, p), v), VDBEntry::CompareVersion()));
@@ -478,6 +481,90 @@ VDBRepository::do_version_metadata(
}
}
+Contents::ConstPointer
+VDBRepository::do_contents(
+ const CategoryNamePart & c, const PackageNamePart & p, const VersionSpec & v) const
+{
+ Context context("When fetching contents for " + stringify(c) + "/" + stringify(p) +
+ "-" + stringify(v));
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ std::pair<std::vector<VDBEntry>::iterator, std::vector<VDBEntry>::iterator>
+ r(std::equal_range(_imp->entries.begin(), _imp->entries.end(), std::make_pair(
+ QualifiedPackageName(c, p), v), VDBEntry::CompareVersion()));
+
+ if (r.first == r.second)
+ {
+ Log::get_instance()->message(ll_warning, "version lookup failed for request for '" +
+ stringify(c) + "/" + stringify(p) + "-" + stringify(v) + "' in repository '" +
+ stringify(name()) + "'");
+ return Contents::ConstPointer(new Contents);
+ }
+
+ Contents::Pointer result(new Contents);
+
+ FSEntry f(_imp->location / stringify(c) / (stringify(p) + "-" + stringify(v)));
+ if (! (f / "CONTENTS").is_regular_file())
+ {
+ Log::get_instance()->message(ll_warning, "CONTENTS lookup failed for request for '" +
+ stringify(c + p) + "-" + stringify(v) + "' in vdb '" +
+ stringify(_imp->location) + "'");
+ return result;
+ }
+
+ std::ifstream ff(stringify(f / "CONTENTS").c_str());
+ if (! ff)
+ throw InternalError(PALUDIS_HERE, "TODO reading " + stringify(_imp->location) + " name " +
+ stringify(c + p) + " version " + stringify(v) + " CONTENTS"); /// \todo
+
+ std::string line;
+ unsigned line_number(0);
+ Tokeniser<delim_kind::AnyOfTag, delim_mode::DelimiterTag> t(" \t\n");
+ while (std::getline(ff, line))
+ {
+ ++line_number;
+
+ std::vector<std::string> tokens;
+ t.tokenise(line, std::back_inserter(tokens));
+ if (tokens.empty())
+ continue;
+
+ if (tokens.size() < 2)
+ {
+ Log::get_instance()->message(ll_warning, "CONTENTS for '" +
+ stringify(c + p) + "-" + stringify(v) + "' in vdb '" +
+ stringify(_imp->location) + "' has broken line " +
+ stringify(line_number) + ", skipping");
+ continue;
+ }
+
+ if ("obj" == tokens.at(0))
+ result->add(ContentsEntry::Pointer(new ContentsFileEntry(tokens.at(1))));
+ else if ("dir" == tokens.at(0))
+ result->add(ContentsEntry::Pointer(new ContentsDirEntry(tokens.at(1))));
+ else if ("misc" == tokens.at(0))
+ result->add(ContentsEntry::Pointer(new ContentsMiscEntry(tokens.at(1))));
+ else if ("sym" == tokens.at(0))
+ {
+ if (tokens.size() < 4)
+ {
+ Log::get_instance()->message(ll_warning, "CONTENTS for '" +
+ stringify(c + p) + "-" + stringify(v) + "' in vdb '" +
+ stringify(_imp->location) + "' has broken sym line " +
+ stringify(line_number) + ", skipping");
+ continue;
+ }
+
+ result->add(ContentsEntry::Pointer(new ContentsSymEntry(
+ tokens.at(1), tokens.at(3))));
+ }
+ }
+
+ return result;
+}
+
bool
VDBRepository::do_query_repository_masks(const CategoryNamePart &,
const PackageNamePart &, const VersionSpec &) const
diff --git a/paludis/vdb_repository.hh b/paludis/vdb_repository.hh
index 8110494..3989eb1 100644
--- a/paludis/vdb_repository.hh
+++ b/paludis/vdb_repository.hh
@@ -108,6 +108,10 @@ namespace paludis
const CategoryNamePart &, const PackageNamePart &,
const VersionSpec &) const;
+ virtual Contents::ConstPointer do_contents(
+ const CategoryNamePart &, const PackageNamePart &,
+ const VersionSpec &) const;
+
virtual bool do_query_repository_masks(const CategoryNamePart &,
const PackageNamePart &, const VersionSpec &) const;
diff --git a/src/Makefile.am b/src/Makefile.am
index 164d2d4..33b16a5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,6 +17,8 @@ paludis_SOURCES = \
query.hh query.cc \
sync.hh sync.cc \
licence.hh licence.cc \
+ contents.hh contents.cc \
+ owner.hh owner.cc \
paludis.cc
paludis_LDADD = \
diff --git a/src/colour.hh b/src/colour.hh
index 615201d..545335b 100644
--- a/src/colour.hh
+++ b/src/colour.hh
@@ -26,6 +26,7 @@
enum Colour
{
+ cl_none = 0,
cl_red = 31,
cl_green = 32,
cl_yellow = 33,
@@ -45,7 +46,12 @@ enum Colour
cl_masked = cl_flag_off,
cl_heading = cl_bold_green,
cl_updatemode = cl_yellow,
- cl_tag = cl_yellow
+ cl_tag = cl_yellow,
+
+ cl_file = cl_none,
+ cl_dir = cl_blue,
+ cl_sym = cl_pink,
+ cl_misc = cl_red
};
bool use_colour() PALUDIS_ATTRIBUTE((pure));
@@ -55,10 +61,12 @@ std::string colour(Colour colour, const T_ & s)
{
if (CommandLine::get_instance()->a_no_color.specified() || ! use_colour())
return paludis::stringify(s);
- else
+ else if (cl_none != colour)
return "\033[" + paludis::stringify(static_cast<unsigned>(colour) / 100) + ";"
+ paludis::stringify(static_cast<unsigned>(colour) % 100) + "m" + paludis::stringify(s)
+ "\033[0;0m";
+ else
+ return paludis::stringify(s);
}
template <typename T_>
diff --git a/src/command_line.cc b/src/command_line.cc
index cbefdfc..b9e8c00 100644
--- a/src/command_line.cc
+++ b/src/command_line.cc
@@ -33,6 +33,8 @@ CommandLine::CommandLine() :
a_list_sync_protocols(&action_args, "list-sync-protocols", '\0', "List available sync protocols"),
a_list_repository_formats(&action_args, "list-repository-formats", '\0', "List available repository formats"),
a_list_dep_tag_categories(&action_args, "list-dep-tag-categories", '\0', "List known dep tag categories"),
+ a_contents(&action_args, "contents", 'k', "Display contents of a package"),
+ a_owner(&action_args, "owner", 'o', "Display the owner of a file"),
a_has_version(&action_args, "has-version", '\0', "Check whether the specified atom is installed"),
a_best_version(&action_args, "best-version", '\0', "Display the best version of the specified atom"),
a_version(&action_args, "version", 'V', "Display program version"),
@@ -71,7 +73,10 @@ CommandLine::CommandLine() :
a_dl_drop_all(&dl_args, "dl-drop-all", '0', "Drop all dependencies"),
a_dl_ignore_installed(&dl_args, "dl-ignore-installed", 'e', "Ignore installed packages"),
a_dl_no_recursive_deps(&dl_args, "dl-no-recursive-deps", '\0', "Don't check runtime dependencies for installed packages"),
- a_dl_max_stack_depth(&dl_args, "dl-max-stack-depth", '\0', "Maximum stack depth (default 100)")
+ a_dl_max_stack_depth(&dl_args, "dl-max-stack-depth", '\0', "Maximum stack depth (default 100)"),
+
+ owner_args(this, "Owner options"),
+ a_full_match(&owner_args, "full-match", '\0', "Match whole filename")
{
a_dl_max_stack_depth.set_argument(100);
}
diff --git a/src/command_line.hh b/src/command_line.hh
index d1e4840..4f7b5ea 100644
--- a/src/command_line.hh
+++ b/src/command_line.hh
@@ -80,6 +80,12 @@ class CommandLine :
/// --list-dep-tag-categories
paludis::args::SwitchArg a_list_dep_tag_categories;
+ /// --contents
+ paludis::args::SwitchArg a_contents;
+
+ /// --owner
+ paludis::args::SwitchArg a_owner;
+
/// --has-version
paludis::args::SwitchArg a_has_version;
@@ -179,6 +185,17 @@ class CommandLine :
paludis::args::IntegerArg a_dl_max_stack_depth;
/// }
+
+ /// \name Owner arguments
+ /// {
+
+ /// Owner arguments.
+ paludis::args::ArgsGroup owner_args;
+
+ /// --full-match
+ paludis::args::SwitchArg a_full_match;
+
+ /// }
};
/**
diff --git a/src/contents.cc b/src/contents.cc
new file mode 100644
index 0000000..ed95466
--- /dev/null
+++ b/src/contents.cc
@@ -0,0 +1,144 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * 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 "contents.hh"
+#include "colour.hh"
+#include <paludis/paludis.hh>
+#include <iostream>
+#include <algorithm>
+
+namespace p = paludis;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+namespace
+{
+ struct ContentsDisplayer :
+ p::ContentsVisitorTypes::ConstVisitor
+ {
+ void visit(const p::ContentsFileEntry * const e)
+ {
+ cout << " " << colour(cl_file, e->name()) << endl;
+ }
+
+ void visit(const p::ContentsDirEntry * const e)
+ {
+ cout << " " << colour(cl_dir, e->name()) << endl;
+ }
+
+ void visit(const p::ContentsSymEntry * const e)
+ {
+ cout << " " << colour(cl_sym, e->name()) << " -> " << e->target() << endl;
+ }
+
+ void visit(const p::ContentsMiscEntry * const e)
+ {
+ cout << " " << colour(cl_misc, e->name()) << endl;
+ }
+ };
+}
+
+void
+do_one_contents_entry(
+ const p::Environment * const env,
+ const p::PackageDatabaseEntry & e)
+{
+ cout << "* " << colour(cl_package_name, e) << endl;
+
+ p::Contents::ConstPointer contents(env->package_database()->fetch_contents(e));
+ ContentsDisplayer d;
+ std::for_each(contents->begin(), contents->end(), accept_visitor(&d));
+
+ cout << endl;
+}
+
+void
+do_one_contents(
+ const p::Environment * const env,
+ const std::string & q)
+{
+ p::Context local_context("When handling query '" + q + "':");
+
+ /* we might have a dep atom, but we might just have a simple package name
+ * without a category. either should work. */
+ p::PackageDepAtom::Pointer atom(std::string::npos == q.find('/') ?
+ new p::PackageDepAtom(env->package_database()->fetch_unique_qualified_package_name(
+ p::PackageNamePart(q))) :
+ new p::PackageDepAtom(q));
+
+ p::PackageDatabaseEntryCollection::ConstPointer
+ entries(env->package_database()->query(atom, p::is_installed_only));
+
+ if (entries->empty())
+ throw p::NoSuchPackageError(q);
+
+ for (p::PackageDatabaseEntryCollection::Iterator i(entries->begin()),
+ i_end(entries->end()) ; i != i_end ; ++i)
+ do_one_contents_entry(env, *i);
+}
+
+int
+do_contents()
+{
+ int return_code(0);
+
+ p::Context context("When performing contents action from command line:");
+ p::Environment * const env(p::DefaultEnvironment::get_instance());
+
+ CommandLine::ParametersIterator q(CommandLine::get_instance()->begin_parameters()),
+ q_end(CommandLine::get_instance()->end_parameters());
+ for ( ; q != q_end ; ++q)
+ {
+ try
+ {
+ do_one_contents(env, *q);
+ }
+ catch (const p::AmbiguousPackageNameError & e)
+ {
+ cout << endl;
+ cerr << "Query error:" << endl;
+ cerr << " * " << e.backtrace("\n * ");
+ cerr << "Ambiguous package name '" << e.name() << "'. Did you mean:" << endl;
+ for (p::AmbiguousPackageNameError::OptionsIterator o(e.begin_options()),
+ o_end(e.end_options()) ; o != o_end ; ++o)
+ cerr << " * " << colour(cl_package_name, *o) << endl;
+ cerr << endl;
+ }
+ catch (const p::NameError & e)
+ {
+ return_code |= 1;
+ cout << endl;
+ cerr << "Query error:" << endl;
+ cerr << " * " << e.backtrace("\n * ") << e.message() << endl;
+ cerr << endl;
+ }
+ catch (const p::PackageDatabaseLookupError & e)
+ {
+ return_code |= 1;
+ cout << endl;
+ cerr << "Query error:" << endl;
+ cerr << " * " << e.backtrace("\n * ") << e.message() << endl;
+ cerr << endl;
+ }
+ }
+
+ return return_code;
+}
+
diff --git a/src/contents.hh b/src/contents.hh
new file mode 100644
index 0000000..4cf3b61
--- /dev/null
+++ b/src/contents.hh
@@ -0,0 +1,30 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * 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_SRC_CONTENTS_HH
+#define PALUDIS_GUARD_SRC_CONTENTS_HH 1
+
+/** \file
+ * Declaration for the do_contents function.
+ */
+
+/// Handle --contents.
+int do_contents();
+
+#endif
diff --git a/src/owner.cc b/src/owner.cc
new file mode 100644
index 0000000..d3f1deb
--- /dev/null
+++ b/src/owner.cc
@@ -0,0 +1,130 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * 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 "owner.hh"
+#include "colour.hh"
+#include <paludis/paludis.hh>
+#include <iostream>
+
+namespace p = paludis;
+using std::cout;
+using std::cerr;
+using std::endl;
+
+namespace
+{
+ struct ContentsFinder :
+ p::ContentsVisitorTypes::ConstVisitor
+ {
+ bool found;
+ const std::string query;
+ const bool full;
+
+ ContentsFinder(const std::string & q, bool f) :
+ found(false),
+ query(q),
+ full(f)
+ {
+ }
+
+ void handle(const std::string & e)
+ {
+ if (full)
+ found |= (e == query);
+ else
+ found |= (std::string::npos != e.find(query));
+ }
+
+ void visit(const p::ContentsFileEntry * const e)
+ {
+ handle(e->name());
+ }
+
+ void visit(const p::ContentsDirEntry * const e)
+ {
+ handle(e->name());
+ }
+
+ void visit(const p::ContentsSymEntry * const e)
+ {
+ handle(e->name());
+ }
+
+ void visit(const p::ContentsMiscEntry * const e)
+ {
+ handle(e->name());
+ }
+ };
+}
+
+void
+do_one_owner(
+ const p::Environment * const env,
+ const std::string & query)
+{
+ cout << "* " << colour(cl_package_name, query) << endl;
+
+ for (p::PackageDatabase::RepositoryIterator r(env->package_database()->begin_repositories()),
+ r_end(env->package_database()->end_repositories()) ; r != r_end ; ++r)
+ {
+ if (! (*r)->installed())
+ continue;
+
+ p::CategoryNamePartCollection::ConstPointer cats((*r)->category_names());
+ for (p::CategoryNamePartCollection::Iterator c(cats->begin()),
+ c_end(cats->end()) ; c != c_end ; ++c)
+ {
+ p::QualifiedPackageNameCollection::ConstPointer pkgs((*r)->package_names(*c));
+ for (p::QualifiedPackageNameCollection::Iterator p(pkgs->begin()),
+ p_end(pkgs->end()) ; p != p_end ; ++p)
+ {
+ p::VersionSpecCollection::ConstPointer vers((*r)->version_specs(*p));
+ for (p::VersionSpecCollection::Iterator v(vers->begin()),
+ v_end(vers->end()) ; v != v_end ; ++v)
+ {
+ p::PackageDatabaseEntry e(*p, *v, (*r)->name());
+ p::Contents::ConstPointer contents(env->package_database()->fetch_contents(e));
+ ContentsFinder d(query, CommandLine::get_instance()->a_full_match.specified());
+ std::for_each(contents->begin(), contents->end(), accept_visitor(&d));
+ if (d.found)
+ cout << " " << e << endl;
+ }
+ }
+ }
+ }
+
+ cout << endl;
+}
+
+
+int
+do_owner()
+{
+ int return_code(0);
+ p::Context context("When performing owner action from command line:");
+ p::Environment * const env(p::DefaultEnvironment::get_instance());
+
+ CommandLine::ParametersIterator q(CommandLine::get_instance()->begin_parameters()),
+ q_end(CommandLine::get_instance()->end_parameters());
+ for ( ; q != q_end ; ++q)
+ do_one_owner(env, *q);
+
+ return return_code;
+}
+
diff --git a/src/owner.hh b/src/owner.hh
new file mode 100644
index 0000000..672b652
--- /dev/null
+++ b/src/owner.hh
@@ -0,0 +1,30 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * 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_SRC_OWNER_HH
+#define PALUDIS_GUARD_SRC_OWNER_HH 1
+
+/** \file
+ * Declaration for the do_owner function.
+ */
+
+/// Handle --owner.
+int do_owner();
+
+#endif
diff --git a/src/paludis.cc b/src/paludis.cc
index eacf1f8..a33ece7 100644
--- a/src/paludis.cc
+++ b/src/paludis.cc
@@ -21,6 +21,8 @@
#include "src/install.hh"
#include "src/uninstall.hh"
#include "src/list.hh"
+#include "src/contents.hh"
+#include "src/owner.hh"
#include "src/query.hh"
#include "src/applets.hh"
#include "src/sync.hh"
@@ -92,6 +94,8 @@ main(int argc, char *argv[])
CommandLine::get_instance()->a_list_sync_protocols.specified() +
CommandLine::get_instance()->a_list_repository_formats.specified() +
CommandLine::get_instance()->a_list_dep_tag_categories.specified() +
+ CommandLine::get_instance()->a_contents.specified() +
+ CommandLine::get_instance()->a_owner.specified() +
CommandLine::get_instance()->a_has_version.specified() +
CommandLine::get_instance()->a_best_version.specified()))
{
@@ -208,6 +212,22 @@ main(int argc, char *argv[])
return do_list_packages();
}
+ if (CommandLine::get_instance()->a_contents.specified())
+ {
+ if (CommandLine::get_instance()->empty())
+ throw DoHelp("contents action requires at least one parameter");
+
+ return do_contents();
+ }
+
+ if (CommandLine::get_instance()->a_owner.specified())
+ {
+ if (CommandLine::get_instance()->empty())
+ throw DoHelp("owner action requires at least one parameter");
+
+ return do_owner();
+ }
+
if (CommandLine::get_instance()->a_has_version.specified())
{
if (1 != std::distance(CommandLine::get_instance()->begin_parameters(),