aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2008-10-14 20:57:27 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2008-10-15 18:09:11 +0100
commit290f399cc8c7c5c407b083c9b4f9b0ea954a725e (patch)
treeb78d286ceb88be6fa9a735d5a1045590c028e99a
parent918a0b2a9063416885081bb52a1164bf6b7a40ea (diff)
downloadpaludis-290f399cc8c7c5c407b083c9b4f9b0ea954a725e.tar.gz
paludis-290f399cc8c7c5c407b083c9b4f9b0ea954a725e.tar.xz
Add ::/, ::/?, ::/??, ::repo?, ::repo?? deps
Fixes: ticket:665
-rw-r--r--doc/api/cplusplus/examples/example_dep_spec.cc20
-rw-r--r--doc/configuration/specs.html.part23
-rw-r--r--paludis/dep_list.cc24
-rw-r--r--paludis/dep_spec-fwd.hh3
-rw-r--r--paludis/dep_spec.cc162
-rw-r--r--paludis/dep_spec.hh108
-rw-r--r--paludis/find_unused_packages_task.cc5
-rw-r--r--paludis/generator.cc41
-rw-r--r--paludis/install_task.cc3
-rw-r--r--paludis/match_package.cc59
-rw-r--r--paludis/range_rewriter.cc45
-rw-r--r--paludis/report_task.cc3
-rw-r--r--paludis/repositories/cran/package_dep_spec.cc16
-rw-r--r--paludis/user_dep_spec.cc62
-rw-r--r--paludis/user_dep_spec_TEST.cc48
-rw-r--r--paludis/util/make_shared_ptr-fwd.hh11
-rw-r--r--paludis/util/make_shared_ptr.hh22
-rw-r--r--ruby/dep_spec.cc34
-rw-r--r--ruby/dep_spec_TEST.rb18
-rw-r--r--src/clients/adjutrix/keywords_graph.cc5
-rw-r--r--src/output/console_query_task.cc12
21 files changed, 604 insertions, 120 deletions
diff --git a/doc/api/cplusplus/examples/example_dep_spec.cc b/doc/api/cplusplus/examples/example_dep_spec.cc
index 393f43a..1b180dc 100644
--- a/doc/api/cplusplus/examples/example_dep_spec.cc
+++ b/doc/api/cplusplus/examples/example_dep_spec.cc
@@ -104,10 +104,26 @@ int main(int argc, char * argv[])
cout << " " << left << setw(24) << "Slot:" << " " << *spec.slot_requirement_ptr() << endl;
if (spec.in_repository_ptr())
- cout << " " << left << setw(24) << "In repository:" << " " << *spec.in_repository_ptr() << endl;
+ cout << " " << left << setw(24) << "In repository:" << " " <<
+ *spec.in_repository_ptr() << endl;
if (spec.from_repository_ptr())
- cout << " " << left << setw(24) << "From repository:" << " " << *spec.from_repository_ptr() << endl;
+ cout << " " << left << setw(24) << "From repository:" << " " <<
+ *spec.from_repository_ptr() << endl;
+
+ if (spec.installed_at_path_ptr())
+ cout << " " << left << setw(24) << "Installed at path:" << " " <<
+ *spec.installed_at_path_ptr() << endl;
+
+ if (spec.installable_to_path_ptr())
+ cout << " " << left << setw(24) << "Installable to path:" << " " <<
+ spec.installable_to_path_ptr()->path() << ", " <<
+ spec.installable_to_path_ptr()->include_masked() << endl;
+
+ if (spec.installable_to_repository_ptr())
+ cout << " " << left << setw(24) << "Installable to repository:" << " " <<
+ spec.installable_to_repository_ptr()->repository() << ", " <<
+ spec.installable_to_repository_ptr()->include_masked() << endl;
if (spec.additional_requirements_ptr() && ! spec.additional_requirements_ptr()->empty())
{
diff --git a/doc/configuration/specs.html.part b/doc/configuration/specs.html.part
index fa87c63..96debd5 100644
--- a/doc/configuration/specs.html.part
+++ b/doc/configuration/specs.html.part
@@ -25,11 +25,8 @@ the following order:</p>
<ul>
<li><code>:slot</code>: Match only in that slot.</li>
- <li><code>::fromrepository-&gt;inrepository</code>: Match only from (originally, so <code>::foo-&gt;</code> will
- match things that were installed from the <code>foo</code> repository) and in (now, so <code>::-&gt;installed</code>
- matches things that are now in the <code>installed</code> repository). At most one of the two names can be
- blank.</li>
- <li><code>::repository</code>: like <code>::-&gt;repository</code>.</li>
+ <li><code>::repo-&gt;repo</code>: Repository requirements, described below.</li>
+ <li><code>::something</code>: like <code>::-&gt;something</code>, for all legal values of something.</li>
<li><code>[use]</code> and <code>[-use]</code>: Match only if the named USE flag is enabled / disabled for this
package. May be specified multiple times with different USE flag names.</li>
<li><code>[=1.23]</code>: Match a particular version. Any operator described below
@@ -37,6 +34,22 @@ the following order:</p>
dependency or <code>[&gt;=1.2&amp;&lt;2]</code> for an and dependency.</li>
</ul>
+<p>Repository requirements are in the form <code>to</code>, <code>from-&gt;</code> or <code>::from-&gt;to</code>. The
+<code>from</code> may only be a repository name, and matches packages <em>originally</em> from that repository (so
+<code>*/*::myrepo-&gt;</code> finds installed packages that originated in <code>myrepo</code>. Valid forms for
+<code>to</code> are as follows:</p>
+
+<ul>
+ <li><code>repo</code>: currently in this repository. Note that an installed package is no longer 'in' the repository
+ whence it came; use a from specification for that.</li>
+ <li><code>repo?</code>: could be installed to <code>repo</code>.</li>
+ <li><code>repo??</code>: could be installed to <code>repo</code>, ignoring masks.</li>
+ <li><code>/path</code>: installed at root <code>/path</code> (typically <code>/</code>).</li>
+ <li><code>/path?</code>: could be installed to some installed repository with root path <code>/path</code>.</li>
+ <li><code>/path??</code>: could be installed to some installed repository with root path <code>/path</code>,
+ ignoring masks.</li>
+</ul>
+
<h2>Operators</h2>
<p>The following operators are recognised:</p>
diff --git a/paludis/dep_list.cc b/paludis/dep_list.cc
index ea8a764..ac5d5c2 100644
--- a/paludis/dep_list.cc
+++ b/paludis/dep_list.cc
@@ -887,8 +887,12 @@ DepList::AddVisitor::visit_leaf(const BlockDepSpec & a)
/* ignore if it's a virtual/blah (not <virtual/blah-1) block and it's blocking
* ourself */
if (! (a.blocked_spec()->version_requirements_ptr() || a.blocked_spec()->slot_requirement_ptr()
- || a.blocked_spec()->additional_requirements_ptr() || a.blocked_spec()->in_repository_ptr()
- || a.blocked_spec()->from_repository_ptr())
+ || a.blocked_spec()->additional_requirements_ptr()
+ || a.blocked_spec()->from_repository_ptr()
+ || a.blocked_spec()->in_repository_ptr()
+ || a.blocked_spec()->installed_at_path_ptr()
+ || a.blocked_spec()->installable_to_repository_ptr()
+ || a.blocked_spec()->installable_to_path_ptr())
&& d->_imp->current_package_id())
{
if ((*aa)->name() == d->_imp->current_package_id()->name())
@@ -928,8 +932,12 @@ DepList::AddVisitor::visit_leaf(const BlockDepSpec & a)
/* ignore if it's a virtual/blah (not <virtual/blah-1) block and it's blocking
* ourself */
if (! (a.blocked_spec()->version_requirements_ptr() || a.blocked_spec()->slot_requirement_ptr()
- || a.blocked_spec()->additional_requirements_ptr() || a.blocked_spec()->in_repository_ptr()
- || a.blocked_spec()->from_repository_ptr())
+ || a.blocked_spec()->additional_requirements_ptr()
+ || a.blocked_spec()->in_repository_ptr()
+ || a.blocked_spec()->from_repository_ptr()
+ || a.blocked_spec()->installed_at_path_ptr()
+ || a.blocked_spec()->installable_to_repository_ptr()
+ || a.blocked_spec()->installable_to_path_ptr())
&& d->_imp->current_package_id())
{
if ((*r)->package_id->name() == d->_imp->current_package_id()->name())
@@ -954,8 +962,12 @@ DepList::AddVisitor::visit_leaf(const BlockDepSpec & a)
/* ignore if it's a virtual/blah (not <virtual/blah-1) block and it's blocking
* ourself */
if (! (a.blocked_spec()->version_requirements_ptr() || a.blocked_spec()->slot_requirement_ptr()
- || a.blocked_spec()->additional_requirements_ptr() || a.blocked_spec()->in_repository_ptr()
- || a.blocked_spec()->from_repository_ptr())
+ || a.blocked_spec()->additional_requirements_ptr()
+ || a.blocked_spec()->in_repository_ptr()
+ || a.blocked_spec()->from_repository_ptr()
+ || a.blocked_spec()->installed_at_path_ptr()
+ || a.blocked_spec()->installable_to_repository_ptr()
+ || a.blocked_spec()->installable_to_path_ptr())
&& d->_imp->current_package_id())
{
if (r->package_id->name() == d->_imp->current_package_id()->name())
diff --git a/paludis/dep_spec-fwd.hh b/paludis/dep_spec-fwd.hh
index 1458544..712c1ae 100644
--- a/paludis/dep_spec-fwd.hh
+++ b/paludis/dep_spec-fwd.hh
@@ -73,6 +73,9 @@ namespace paludis
class AdditionalPackageDepSpecRequirement;
+ struct InstallableToRepository;
+ struct InstallableToPath;
+
/**
* An AdditionalPackageDepSpecRequirement can be written to an ostream.
*
diff --git a/paludis/dep_spec.cc b/paludis/dep_spec.cc
index 7d6f872..ae6c527 100644
--- a/paludis/dep_spec.cc
+++ b/paludis/dep_spec.cc
@@ -36,6 +36,7 @@
#include <paludis/util/options.hh>
#include <paludis/util/make_shared_ptr.hh>
#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/fs_entry.hh>
#include <paludis/metadata_key.hh>
#include <tr1/functional>
#include <algorithm>
@@ -646,15 +647,33 @@ PackageDepSpec::slot_requirement_ptr() const
}
std::tr1::shared_ptr<const RepositoryName>
+PackageDepSpec::in_repository_ptr() const
+{
+ return _imp->data->in_repository_ptr();
+}
+
+std::tr1::shared_ptr<const InstallableToRepository>
+PackageDepSpec::installable_to_repository_ptr() const
+{
+ return _imp->data->installable_to_repository_ptr();
+}
+
+std::tr1::shared_ptr<const RepositoryName>
PackageDepSpec::from_repository_ptr() const
{
return _imp->data->from_repository_ptr();
}
-std::tr1::shared_ptr<const RepositoryName>
-PackageDepSpec::in_repository_ptr() const
+std::tr1::shared_ptr<const FSEntry>
+PackageDepSpec::installed_at_path_ptr() const
{
- return _imp->data->in_repository_ptr();
+ return _imp->data->installed_at_path_ptr();
+}
+
+std::tr1::shared_ptr<const InstallableToPath>
+PackageDepSpec::installable_to_path_ptr() const
+{
+ return _imp->data->installable_to_path_ptr();
}
std::tr1::shared_ptr<const AdditionalPackageDepSpecRequirements>
@@ -688,11 +707,20 @@ PackageDepSpec::without_additional_requirements() const
if (slot_requirement_ptr())
result.slot_requirement(slot_requirement_ptr());
+ if (in_repository_ptr())
+ result.in_repository(*in_repository_ptr());
+
if (from_repository_ptr())
result.from_repository(*from_repository_ptr());
- if (in_repository_ptr())
- result.in_repository(*in_repository_ptr());
+ if (installed_at_path_ptr())
+ result.installed_at_path(*installed_at_path_ptr());
+
+ if (installable_to_path_ptr())
+ result.installable_to_path(*installable_to_path_ptr());
+
+ if (installable_to_repository_ptr())
+ result.installable_to_repository(*installable_to_repository_ptr());
if (annotations_key())
result.annotations(annotations_key());
@@ -757,8 +785,11 @@ namespace
std::tr1::shared_ptr<VersionRequirements> version_requirements;
VersionRequirementsMode version_requirements_mode_v;
std::tr1::shared_ptr<const SlotRequirement> slot;
- std::tr1::shared_ptr<const RepositoryName> from_repository;
std::tr1::shared_ptr<const RepositoryName> in_repository;
+ std::tr1::shared_ptr<const RepositoryName> from_repository;
+ std::tr1::shared_ptr<const InstallableToRepository> installable_to_repository;
+ std::tr1::shared_ptr<const FSEntry> installed_at_path;
+ std::tr1::shared_ptr<const InstallableToPath> installable_to_path;
std::tr1::shared_ptr<AdditionalPackageDepSpecRequirements> additional_requirements;
std::tr1::shared_ptr<const MetadataSectionKey> annotations;
@@ -776,8 +807,11 @@ namespace
version_requirements(other.version_requirements_ptr() ? new VersionRequirements : 0),
version_requirements_mode_v(other.version_requirements_mode()),
slot(other.slot_requirement_ptr()),
- from_repository(other.from_repository_ptr()),
in_repository(other.in_repository_ptr()),
+ from_repository(other.from_repository_ptr()),
+ installable_to_repository(other.installable_to_repository_ptr()),
+ installed_at_path(other.installed_at_path_ptr()),
+ installable_to_path(other.installable_to_path_ptr()),
additional_requirements(other.additional_requirements_ptr() ? new AdditionalPackageDepSpecRequirements : 0),
annotations(other.annotations_key())
{
@@ -798,8 +832,11 @@ namespace
version_requirements(other.version_requirements),
version_requirements_mode_v(other.version_requirements_mode_v),
slot(other.slot),
- from_repository(other.from_repository),
in_repository(other.in_repository),
+ from_repository(other.from_repository),
+ installable_to_repository(other.installable_to_repository),
+ installed_at_path(other.installed_at_path),
+ installable_to_path(other.installable_to_path),
additional_requirements(other.additional_requirements),
annotations(other.annotations)
{
@@ -856,12 +893,57 @@ namespace
if (slot_requirement_ptr())
s << stringify(*slot_requirement_ptr());
- if (in_repository_ptr() && from_repository_ptr())
- s << "::" << *from_repository_ptr() << "->" << *in_repository_ptr();
- else if (in_repository_ptr())
- s << "::" << *in_repository_ptr();
- else if (from_repository_ptr())
- s << "::" << *from_repository_ptr() << "->";
+ std::string left, right;
+ bool need_arrow(false);
+
+ if (from_repository_ptr())
+ left = stringify(*from_repository_ptr());
+
+ if (in_repository_ptr())
+ right = stringify(*in_repository_ptr());
+
+ if (installed_at_path_ptr())
+ {
+ if (! right.empty())
+ {
+ need_arrow = true;
+ right.append("->");
+ }
+ right.append(stringify(*installed_at_path_ptr()));
+ }
+
+ if (installable_to_repository_ptr())
+ {
+ if (! right.empty())
+ {
+ need_arrow = true;
+ right.append("->");
+ }
+ if (installable_to_repository_ptr()->include_masked())
+ right.append(stringify(installable_to_repository_ptr()->repository()) + "??");
+ else
+ right.append(stringify(installable_to_repository_ptr()->repository()) + "?");
+ }
+
+ if (installable_to_path_ptr())
+ {
+ if (! right.empty())
+ {
+ need_arrow = true;
+ right.append("->");
+ }
+ if (installable_to_path_ptr()->include_masked())
+ right.append(stringify(installable_to_path_ptr()->path()) + "??");
+ else
+ right.append(stringify(installable_to_path_ptr()->path()) + "?");
+ }
+
+ if (need_arrow || ((! left.empty()) && (! right.empty())))
+ s << "::" << left << "->" << right;
+ else if (! right.empty())
+ s << "::" << right;
+ else if (! left.empty())
+ s << "::" << left << "->";
if (version_requirements_ptr())
{
@@ -953,14 +1035,29 @@ namespace
return slot;
}
+ virtual std::tr1::shared_ptr<const RepositoryName> in_repository_ptr() const
+ {
+ return in_repository;
+ }
+
+ virtual std::tr1::shared_ptr<const InstallableToRepository> installable_to_repository_ptr() const
+ {
+ return installable_to_repository;
+ }
+
virtual std::tr1::shared_ptr<const RepositoryName> from_repository_ptr() const
{
return from_repository;
}
- virtual std::tr1::shared_ptr<const RepositoryName> in_repository_ptr() const
+ virtual std::tr1::shared_ptr<const FSEntry> installed_at_path_ptr() const
{
- return in_repository;
+ return installed_at_path;
+ }
+
+ virtual std::tr1::shared_ptr<const InstallableToPath> installable_to_path_ptr() const
+ {
+ return installable_to_path;
}
virtual std::tr1::shared_ptr<const AdditionalPackageDepSpecRequirements> additional_requirements_ptr() const
@@ -1033,17 +1130,38 @@ PartiallyMadePackageDepSpec::slot_requirement(const std::tr1::shared_ptr<const S
}
PartiallyMadePackageDepSpec &
-PartiallyMadePackageDepSpec::from_repository(const RepositoryName & repo)
+PartiallyMadePackageDepSpec::in_repository(const RepositoryName & s)
+{
+ _imp->data->in_repository.reset(new RepositoryName(s));
+ return *this;
+}
+
+PartiallyMadePackageDepSpec &
+PartiallyMadePackageDepSpec::from_repository(const RepositoryName & s)
{
- _imp->data->from_repository.reset(new RepositoryName(repo));
- return *this;
+ _imp->data->from_repository.reset(new RepositoryName(s));
+ return *this;
}
PartiallyMadePackageDepSpec &
-PartiallyMadePackageDepSpec::in_repository(const RepositoryName & repo)
+PartiallyMadePackageDepSpec::installable_to_repository(const InstallableToRepository & s)
{
- _imp->data->in_repository.reset(new RepositoryName(repo));
- return *this;
+ _imp->data->installable_to_repository.reset(new InstallableToRepository(s));
+ return *this;
+}
+
+PartiallyMadePackageDepSpec &
+PartiallyMadePackageDepSpec::installed_at_path(const FSEntry & s)
+{
+ _imp->data->installed_at_path.reset(new FSEntry(s));
+ return *this;
+}
+
+PartiallyMadePackageDepSpec &
+PartiallyMadePackageDepSpec::installable_to_path(const InstallableToPath & s)
+{
+ _imp->data->installable_to_path.reset(new InstallableToPath(s));
+ return *this;
}
PartiallyMadePackageDepSpec &
diff --git a/paludis/dep_spec.hh b/paludis/dep_spec.hh
index 0b5cb82..28969a0 100644
--- a/paludis/dep_spec.hh
+++ b/paludis/dep_spec.hh
@@ -25,6 +25,8 @@
#include <paludis/util/instantiation_policy.hh>
#include <paludis/util/private_implementation_pattern.hh>
#include <paludis/util/wrapped_forward_iterator-fwd.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/named_value.hh>
#include <paludis/dep_label.hh>
#include <paludis/dep_spec-fwd.hh>
@@ -314,6 +316,37 @@ namespace paludis
virtual const std::string as_raw_string() const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
};
+ namespace n
+ {
+ struct include_masked;
+ struct path;
+ struct repository;
+ }
+
+ /**
+ * Data for PackageDepSpec.installable_to_repository_ptr() etc.
+ *
+ * \ingroup g_dep_spec
+ * \since 0.32
+ */
+ struct InstallableToRepository
+ {
+ NamedValue<n::include_masked, bool> include_masked;
+ NamedValue<n::repository, RepositoryName> repository;
+ };
+
+ /**
+ * Data for PackageDepSpec.installable_to_path_ptr() etc.
+ *
+ * \ingroup g_dep_spec
+ * \since 0.32
+ */
+ struct InstallableToPath
+ {
+ NamedValue<n::include_masked, bool> include_masked;
+ NamedValue<n::path, FSEntry> path;
+ };
+
/**
* A PartiallyMadePackageDepSpec is returned by make_package_dep_spec()
* and is used to incrementally build a PackageDepSpec.
@@ -346,16 +379,37 @@ namespace paludis
PartiallyMadePackageDepSpec & slot_requirement(const std::tr1::shared_ptr<const SlotRequirement> &);
/**
- * Set our in-repository requirements, return ourself.
+ * Set our in-repository requirement, return ourself.
*/
PartiallyMadePackageDepSpec & in_repository(const RepositoryName &);
/**
- * Set our from-repository requirements, return ourself.
+ * Set our from-repository requirement, return ourself.
*/
PartiallyMadePackageDepSpec & from_repository(const RepositoryName &);
/**
+ * Set our installable-to-repository requirement, return ourself.
+ *
+ * \since 0.32
+ */
+ PartiallyMadePackageDepSpec & installable_to_repository(const InstallableToRepository &);
+
+ /**
+ * Set our installed-at-path requirement, return ourself.
+ *
+ * \since 0.32
+ */
+ PartiallyMadePackageDepSpec & installed_at_path(const FSEntry &);
+
+ /**
+ * Set our installable-to-path requirement, return ourself.
+ *
+ * \since 0.32
+ */
+ PartiallyMadePackageDepSpec & installable_to_path(const InstallableToPath &);
+
+ /**
* Set our package name part requirements, return ourself.
*/
PartiallyMadePackageDepSpec & package_name_part(const PackageNamePart &);
@@ -484,16 +538,37 @@ namespace paludis
std::tr1::shared_ptr<const SlotRequirement> slot_requirement_ptr() const;
/**
- * Fetch the in-repo name (may be a zero pointer).
+ * Fetch the in-repository requirement (may be a zero pointer).
*/
std::tr1::shared_ptr<const RepositoryName> in_repository_ptr() const;
/**
- * Fetch the from-repo name (may be a zero pointer).
+ * Fetch the installable-to-repository requirement (may be a zero pointer).
+ *
+ * \since 0.32
+ */
+ std::tr1::shared_ptr<const InstallableToRepository> installable_to_repository_ptr() const;
+
+ /**
+ * Fetch the from-repository requirement (may be a zero pointer).
*/
std::tr1::shared_ptr<const RepositoryName> from_repository_ptr() const;
/**
+ * Fetch the installed-at-path requirement (may be a zero pointer).
+ *
+ * \since 0.32
+ */
+ std::tr1::shared_ptr<const FSEntry> installed_at_path_ptr() const;
+
+ /**
+ * Fetch the installable-to-path requirement (may be a zero pointer).
+ *
+ * \since 0.32
+ */
+ std::tr1::shared_ptr<const InstallableToPath> installable_to_path_ptr() const;
+
+ /**
* Fetch any additional requirements (may be a zero pointer).
*/
std::tr1::shared_ptr<const AdditionalPackageDepSpecRequirements> additional_requirements_ptr() const;
@@ -573,16 +648,37 @@ namespace paludis
virtual std::tr1::shared_ptr<const SlotRequirement> slot_requirement_ptr() const = 0;
/**
- * Fetch the in-repo name (may be a zero pointer).
+ * Fetch the from-repository requirement (may be a zero pointer).
*/
virtual std::tr1::shared_ptr<const RepositoryName> in_repository_ptr() const = 0;
/**
- * Fetch the from-repo name (may be a zero pointer).
+ * Fetch the installable-to-repository requirement (may be a zero pointer).
+ *
+ * \since 0.32
+ */
+ virtual std::tr1::shared_ptr<const InstallableToRepository> installable_to_repository_ptr() const = 0;
+
+ /**
+ * Fetch the from-repository requirement (may be a zero pointer).
*/
virtual std::tr1::shared_ptr<const RepositoryName> from_repository_ptr() const = 0;
/**
+ * Fetch the installed-at-path requirement (may be a zero pointer).
+ *
+ * \since 0.32
+ */
+ virtual std::tr1::shared_ptr<const FSEntry> installed_at_path_ptr() const = 0;
+
+ /**
+ * Fetch the installable-to-path requirement (may be a zero pointer).
+ *
+ * \since 0.32
+ */
+ virtual std::tr1::shared_ptr<const InstallableToPath> installable_to_path_ptr() const = 0;
+
+ /**
* Fetch the additional requirements (may be a zero pointer).
*/
virtual std::tr1::shared_ptr<const AdditionalPackageDepSpecRequirements> additional_requirements_ptr() const = 0;
diff --git a/paludis/find_unused_packages_task.cc b/paludis/find_unused_packages_task.cc
index 34f3bda..9c91594 100644
--- a/paludis/find_unused_packages_task.cc
+++ b/paludis/find_unused_packages_task.cc
@@ -45,9 +45,8 @@ FindUnusedPackagesTask::execute(const QualifiedPackageName & package)
{
std::tr1::shared_ptr<PackageIDSequence> result(new PackageIDSequence);
std::tr1::shared_ptr<const PackageIDSequence> packages((*_env)[selection::AllVersionsGroupedBySlot(
- generator::Matches(make_package_dep_spec()
- .package(package)
- .in_repository(_repo->name()))
+ generator::InRepository(_repo->name()) &
+ generator::Package(package)
)]);
SlotName old_slot("I_am_a_slot");
diff --git a/paludis/generator.cc b/paludis/generator.cc
index ed6210f..e168ab5 100644
--- a/paludis/generator.cc
+++ b/paludis/generator.cc
@@ -287,12 +287,47 @@ namespace
virtual std::tr1::shared_ptr<const RepositoryNameSet> repositories(
const Environment * const env) const
{
- if (! spec.in_repository_ptr())
+ if ((! spec.in_repository_ptr()) && (! spec.installed_at_path_ptr()))
return AllGeneratorHandlerBase::repositories(env);
std::tr1::shared_ptr<RepositoryNameSet> result(new RepositoryNameSet);
- if (env->package_database()->has_repository_named(*spec.in_repository_ptr()))
- result->insert(*spec.in_repository_ptr());
+
+ if (spec.in_repository_ptr())
+ {
+ if (env->package_database()->has_repository_named(*spec.in_repository_ptr()))
+ {
+ if (spec.installed_at_path_ptr())
+ {
+ std::tr1::shared_ptr<const Repository> repo(env->package_database()->fetch_repository(
+ *spec.in_repository_ptr()));
+ if (! repo->installed_root_key())
+ return result;
+ if (repo->installed_root_key()->value() != *spec.installed_at_path_ptr())
+ return result;
+ }
+
+ result->insert(*spec.in_repository_ptr());
+ }
+ }
+ else
+ {
+ if (spec.installed_at_path_ptr())
+ {
+ for (PackageDatabase::RepositoryConstIterator i(env->package_database()->begin_repositories()),
+ i_end(env->package_database()->end_repositories()) ; i != i_end ; ++i)
+ {
+ if (! (*i)->installed_root_key())
+ continue;
+
+ if ((*i)->installed_root_key()->value() != *spec.installed_at_path_ptr())
+ continue;
+
+ result->insert((*i)->name());
+ }
+ }
+ else
+ return AllGeneratorHandlerBase::repositories(env);
+ }
return result;
}
diff --git a/paludis/install_task.cc b/paludis/install_task.cc
index 97ec3e5..f9b05fc 100644
--- a/paludis/install_task.cc
+++ b/paludis/install_task.cc
@@ -757,7 +757,8 @@ InstallTask::_one(const DepList::Iterator dep, const int x, const int y, const i
generator::Matches(make_package_dep_spec()
.package(dep->package_id->name())
.slot_requirement(make_shared_ptr(new UserSlotExactRequirement(dep->package_id->slot())))
- .in_repository(dep->destination->name())) |
+ .in_repository(dep->destination->name())
+ ) |
filter::SupportsAction<UninstallAction>())];
// don't clean the thing we just installed
diff --git a/paludis/match_package.cc b/paludis/match_package.cc
index b00b34e..22a3037 100644
--- a/paludis/match_package.cc
+++ b/paludis/match_package.cc
@@ -28,6 +28,10 @@
#include <paludis/metadata_key.hh>
#include <paludis/util/visitor-impl.hh>
#include <paludis/util/set.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/action.hh>
+#include <paludis/repository.hh>
+#include <paludis/metadata_key.hh>
#include <tr1/functional>
#include <algorithm>
@@ -123,6 +127,61 @@ paludis::match_package(
return false;
}
+ if (spec.installed_at_path_ptr())
+ {
+ if (! entry.repository()->installed_root_key())
+ return false;
+ if (entry.repository()->installed_root_key()->value() != *spec.installed_at_path_ptr())
+ return false;
+ if (! entry.supports_action(SupportsActionTest<InstalledAction>()))
+ return false;
+ }
+
+ if (spec.installable_to_repository_ptr())
+ {
+ if (! entry.supports_action(SupportsActionTest<InstallAction>()))
+ return false;
+ if (! spec.installable_to_repository_ptr()->include_masked())
+ if (entry.masked())
+ return false;
+
+ const std::tr1::shared_ptr<const Repository> dest(env.package_database()->fetch_repository(
+ spec.installable_to_repository_ptr()->repository()));
+ if (! dest->destination_interface())
+ return false;
+ if (! dest->destination_interface()->is_suitable_destination_for(entry))
+ return false;
+
+ return true;
+ }
+
+ if (spec.installable_to_path_ptr())
+ {
+ if (! entry.supports_action(SupportsActionTest<InstallAction>()))
+ return false;
+ if (! spec.installable_to_path_ptr()->include_masked())
+ if (entry.masked())
+ return false;
+
+ for (PackageDatabase::RepositoryConstIterator d(env.package_database()->begin_repositories()),
+ d_end(env.package_database()->end_repositories()) ;
+ d != d_end ; ++d)
+ {
+ if (! (*d)->destination_interface())
+ continue;
+ if (! (*d)->installed_root_key())
+ continue;
+ if ((*d)->installed_root_key()->value() != spec.installable_to_path_ptr()->path())
+ continue;
+ if (! (*d)->destination_interface()->is_suitable_destination_for(entry))
+ continue;
+
+ return true;
+ }
+
+ return false;
+ }
+
if (spec.slot_requirement_ptr())
{
SlotRequirementChecker v(entry.slot());
diff --git a/paludis/range_rewriter.cc b/paludis/range_rewriter.cc
index 88309f9..b14c48f 100644
--- a/paludis/range_rewriter.cc
+++ b/paludis/range_rewriter.cc
@@ -122,16 +122,6 @@ namespace
return std::tr1::shared_ptr<const SlotRequirement>();
}
- virtual std::tr1::shared_ptr<const RepositoryName> from_repository_ptr() const
- {
- return std::tr1::shared_ptr<const RepositoryName>();
- }
-
- virtual std::tr1::shared_ptr<const RepositoryName> in_repository_ptr() const
- {
- return std::tr1::shared_ptr<const RepositoryName>();
- }
-
virtual std::tr1::shared_ptr<const MetadataSectionKey> annotations_key() const
{
return std::tr1::shared_ptr<const MetadataSectionKey>();
@@ -168,6 +158,31 @@ namespace
{
return make_shared_ptr(new RangeRewrittenPackageDepSpecData(*this));
}
+
+ virtual std::tr1::shared_ptr<const RepositoryName> in_repository_ptr() const
+ {
+ return make_null_shared_ptr();
+ }
+
+ virtual std::tr1::shared_ptr<const InstallableToRepository> installable_to_repository_ptr() const
+ {
+ return make_null_shared_ptr();
+ }
+
+ virtual std::tr1::shared_ptr<const RepositoryName> from_repository_ptr() const
+ {
+ return make_null_shared_ptr();
+ }
+
+ virtual std::tr1::shared_ptr<const FSEntry> installed_at_path_ptr() const
+ {
+ return make_null_shared_ptr();
+ }
+
+ virtual std::tr1::shared_ptr<const InstallableToPath> installable_to_path_ptr() const
+ {
+ return make_null_shared_ptr();
+ }
};
}
@@ -227,8 +242,14 @@ RangeRewriter::visit_leaf(const PackageDepSpec & a)
if (_imp->invalid)
return;
- if (a.additional_requirements_ptr() || a.slot_requirement_ptr() || a.in_repository_ptr() || a.package_name_part_ptr()
- || a.category_name_part_ptr() || ! a.version_requirements_ptr() || ! a.package_ptr() || a.from_repository_ptr())
+ if (a.additional_requirements_ptr() || a.slot_requirement_ptr() || a.package_name_part_ptr()
+ || a.category_name_part_ptr() || ! a.version_requirements_ptr() || ! a.package_ptr()
+ || a.in_repository_ptr()
+ || a.from_repository_ptr()
+ || a.installable_to_repository_ptr()
+ || a.installable_to_path_ptr()
+ || a.installed_at_path_ptr()
+ )
{
_imp->invalid = true;
return;
diff --git a/paludis/report_task.cc b/paludis/report_task.cc
index 49dffba..eaba698 100644
--- a/paludis/report_task.cc
+++ b/paludis/report_task.cc
@@ -206,10 +206,11 @@ ReportTask::execute()
{
std::tr1::shared_ptr<const PackageIDSequence> installable(
(*e)[selection::BestVersionOnly(
+ generator::InRepository(RepositoryName(*o)) &
generator::Matches(make_package_dep_spec()
.package((*v)->name())
.version_requirement(VersionRequirement(vo_equal, (*v)->version()))
- .in_repository(RepositoryName(*o))) |
+ ) |
filter::SupportsAction<InstallAction>())]);
if (! installable->empty())
diff --git a/paludis/repositories/cran/package_dep_spec.cc b/paludis/repositories/cran/package_dep_spec.cc
index c146bc5..eb48b72 100644
--- a/paludis/repositories/cran/package_dep_spec.cc
+++ b/paludis/repositories/cran/package_dep_spec.cc
@@ -23,6 +23,7 @@
#include <paludis/util/tokeniser.hh>
#include <paludis/util/sequence.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/make_shared_ptr.hh>
#include <paludis/dep_spec.hh>
#include <paludis/version_operator.hh>
#include <paludis/version_spec.hh>
@@ -133,6 +134,21 @@ namespace
return *this;
}
+
+ virtual std::tr1::shared_ptr<const InstallableToRepository> installable_to_repository_ptr() const
+ {
+ return make_null_shared_ptr();
+ }
+
+ virtual std::tr1::shared_ptr<const FSEntry> installed_at_path_ptr() const
+ {
+ return make_null_shared_ptr();
+ }
+
+ virtual std::tr1::shared_ptr<const InstallableToPath> installable_to_path_ptr() const
+ {
+ return make_null_shared_ptr();
+ }
};
}
diff --git a/paludis/user_dep_spec.cc b/paludis/user_dep_spec.cc
index 130424a..54b26b6 100644
--- a/paludis/user_dep_spec.cc
+++ b/paludis/user_dep_spec.cc
@@ -196,31 +196,73 @@ namespace
}
void
+ parse_rhs(PartiallyMadePackageDepSpec & reqs, const std::string & req)
+ {
+ if (req.empty())
+ throw PackageDepSpecError("Invalid empty :: requirement");
+
+ if ('/' == req.at(0))
+ {
+ if ('?' == req.at(req.length() - 1))
+ {
+ if (req.length() >= 2 && '?' == req.at(req.length() - 2))
+ reqs.installable_to_path(make_named_values<InstallableToPath>(
+ value_for<n::include_masked>(true),
+ value_for<n::path>(FSEntry(req.substr(0, req.length() - 2)))));
+ else
+ reqs.installable_to_path(make_named_values<InstallableToPath>(
+ value_for<n::include_masked>(false),
+ value_for<n::path>(FSEntry(req.substr(0, req.length() - 1)))));
+ }
+ else
+ reqs.installed_at_path(req);
+ }
+ else
+ {
+ if ('?' == req.at(req.length() - 1))
+ {
+ if (req.length() >= 3 && '?' == req.at(req.length() - 2))
+ reqs.installable_to_repository(make_named_values<InstallableToRepository>(
+ value_for<n::include_masked>(true),
+ value_for<n::repository>(RepositoryName(req.substr(0, req.length() - 2)))));
+ else
+ reqs.installable_to_repository(make_named_values<InstallableToRepository>(
+ value_for<n::include_masked>(false),
+ value_for<n::repository>(RepositoryName(req.substr(0, req.length() - 1)))));
+ }
+ else
+ reqs.in_repository(RepositoryName(req));
+ }
+ }
+
+ void
user_remove_trailing_repo_if_exists(std::string & s, PartiallyMadePackageDepSpec & result)
{
std::string::size_type repo_p;
if (std::string::npos == ((repo_p = s.rfind("::"))))
return;
- std::string repo_name(s.substr(repo_p + 2));
+ std::string req(s.substr(repo_p + 2));
s.erase(repo_p);
+ if (req.empty())
+ throw PackageDepSpecError("Need something after ::");
- std::string::size_type arrow_p(repo_name.find("->"));
+ std::string::size_type arrow_p(req.find("->"));
if (std::string::npos == arrow_p)
- result.in_repository(RepositoryName(repo_name));
+ parse_rhs(result, req);
else
{
- std::string from_repository(repo_name.substr(0, arrow_p));
- std::string to_repository(repo_name.substr(arrow_p + 2));
+ std::string left(req.substr(0, arrow_p));
+ std::string right(req.substr(arrow_p + 2));
- if (from_repository.empty() && to_repository.empty())
+ if (left.empty() && right.empty())
throw PackageDepSpecError("::-> requires either a from or a to repository");
- if (! to_repository.empty())
- result.in_repository(RepositoryName(to_repository));
+ if (! right.empty())
+ parse_rhs(result, right);
- if (! from_repository.empty())
- result.from_repository(RepositoryName(from_repository));
+ if (! left.empty())
+ result.from_repository(RepositoryName(left));
}
}
}
diff --git a/paludis/user_dep_spec_TEST.cc b/paludis/user_dep_spec_TEST.cc
index 852438b..3c3650c 100644
--- a/paludis/user_dep_spec_TEST.cc
+++ b/paludis/user_dep_spec_TEST.cc
@@ -59,7 +59,10 @@ namespace
const std::string & slot_requirement,
const std::string & in_repository,
const std::string & from_repository,
- const std::string & additional_requirement
+ const std::string & additional_requirement,
+ const std::string & installed_at_path = "",
+ const std::string & installable_to_path_f = "",
+ const bool installable_to_path_s = false
)
{
TestMessageSuffix s(stringify(spec), true);
@@ -134,6 +137,25 @@ namespace
indirect_iterator(spec.additional_requirements_ptr()->end()), ", "),
additional_requirement);
}
+
+ if (installed_at_path.empty())
+ TEST_CHECK(! spec.installed_at_path_ptr());
+ else
+ {
+ TEST_CHECK(spec.installed_at_path_ptr());
+ TEST_CHECK_STRINGIFY_EQUAL(*spec.installed_at_path_ptr(),
+ installed_at_path);
+ }
+
+ if (installable_to_path_f.empty())
+ TEST_CHECK(! spec.installable_to_path_ptr());
+ else
+ {
+ TEST_CHECK(spec.installable_to_path_ptr());
+ TEST_CHECK_STRINGIFY_EQUAL(spec.installable_to_path_ptr()->path(), installable_to_path_f);
+ TEST_CHECK_EQUAL(spec.installable_to_path_ptr()->include_masked(), installable_to_path_s);
+ }
+
}
};
}
@@ -251,6 +273,30 @@ namespace test_cases
PackageDepSpec d(parse_user_package_dep_spec("cat/pkg::r1->r2",
&env, UserPackageDepSpecOptions() + updso_allow_wildcards));
check_spec(d, "cat/pkg", "", "", "", "", "", "r2", "r1", "");
+
+ PackageDepSpec e(parse_user_package_dep_spec("cat/pkg::/",
+ &env, UserPackageDepSpecOptions() + updso_allow_wildcards));
+ check_spec(e, "cat/pkg", "", "", "", "", "", "", "", "", "/");
+
+ PackageDepSpec f(parse_user_package_dep_spec("cat/pkg::/path",
+ &env, UserPackageDepSpecOptions() + updso_allow_wildcards));
+ check_spec(f, "cat/pkg", "", "", "", "", "", "", "", "", "/path");
+
+ PackageDepSpec g(parse_user_package_dep_spec("cat/pkg::/?",
+ &env, UserPackageDepSpecOptions() + updso_allow_wildcards));
+ check_spec(g, "cat/pkg", "", "", "", "", "", "", "", "", "", "/", false);
+
+ PackageDepSpec h(parse_user_package_dep_spec("cat/pkg::/path?",
+ &env, UserPackageDepSpecOptions() + updso_allow_wildcards));
+ check_spec(h, "cat/pkg", "", "", "", "", "", "", "", "", "", "/path", false);
+
+ PackageDepSpec i(parse_user_package_dep_spec("cat/pkg::/??",
+ &env, UserPackageDepSpecOptions() + updso_allow_wildcards));
+ check_spec(i, "cat/pkg", "", "", "", "", "", "", "", "", "", "/", true);
+
+ PackageDepSpec j(parse_user_package_dep_spec("cat/pkg::/path??",
+ &env, UserPackageDepSpecOptions() + updso_allow_wildcards));
+ check_spec(j, "cat/pkg", "", "", "", "", "", "", "", "", "", "/path", true);
}
} test_user_package_dep_spec_repo;
diff --git a/paludis/util/make_shared_ptr-fwd.hh b/paludis/util/make_shared_ptr-fwd.hh
index 3636930..75fdd8a 100644
--- a/paludis/util/make_shared_ptr-fwd.hh
+++ b/paludis/util/make_shared_ptr-fwd.hh
@@ -44,6 +44,17 @@ namespace paludis
template <typename T_>
std::tr1::shared_ptr<T_>
make_shared_ptr(T_ * const t) PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ struct NullSharedPtr;
+
+ /**
+ * Return an object that can convert itself to an empty
+ * std::tr1::shared_ptr<> of any type.
+ *
+ * \ingroup g_utils
+ * \since 0.32
+ */
+ inline NullSharedPtr make_null_shared_ptr() PALUDIS_ATTRIBUTE((warn_unused_result)) PALUDIS_VISIBLE;
}
#endif
diff --git a/paludis/util/make_shared_ptr.hh b/paludis/util/make_shared_ptr.hh
index ef15f41..a2ca047 100644
--- a/paludis/util/make_shared_ptr.hh
+++ b/paludis/util/make_shared_ptr.hh
@@ -41,6 +41,28 @@ namespace paludis
{
return std::tr1::shared_ptr<T_>(t);
}
+
+ /**
+ * An object that can convert itself into an empty std::tr1::shared_ptr<>
+ * of any type.
+ *
+ * \see make_null_shared_ptr()
+ * \since 0.32
+ * \ingroup g_utils
+ */
+ struct PALUDIS_VISIBLE NullSharedPtr
+ {
+ template <typename T_>
+ inline operator std::tr1::shared_ptr<T_> () const
+ {
+ return std::tr1::shared_ptr<T_>();
+ }
+ };
+
+ inline NullSharedPtr make_null_shared_ptr()
+ {
+ return NullSharedPtr();
+ }
}
#endif
diff --git a/ruby/dep_spec.cc b/ruby/dep_spec.cc
index 25984cc..1440695 100644
--- a/ruby/dep_spec.cc
+++ b/ruby/dep_spec.cc
@@ -714,38 +714,6 @@ namespace
/*
* call-seq:
- * in_repository -> String or Nil
- *
- * Fetch the in-repository name.
- */
- VALUE
- package_dep_spec_in_repository_ptr(VALUE self)
- {
- std::tr1::shared_ptr<WrappedSpecBase> * ptr;
- Data_Get_Struct(self, std::tr1::shared_ptr<WrappedSpecBase>, ptr);
- if (0 == std::tr1::static_pointer_cast<const WrappedSpec<PackageDepSpec> >(*ptr)->spec()->in_repository_ptr())
- return Qnil;
- return rb_str_new2(stringify((*std::tr1::static_pointer_cast<const WrappedSpec<PackageDepSpec> >(*ptr)->spec()->in_repository_ptr())).c_str());
- }
-
- /*
- * call-seq:
- * from_repository -> String or Nil
- *
- * Fetch the from-repository name.
- */
- VALUE
- package_dep_spec_from_repository_ptr(VALUE self)
- {
- std::tr1::shared_ptr<WrappedSpecBase> * ptr;
- Data_Get_Struct(self, std::tr1::shared_ptr<WrappedSpecBase>, ptr);
- if (0 == std::tr1::static_pointer_cast<const WrappedSpec<PackageDepSpec> >(*ptr)->spec()->from_repository_ptr())
- return Qnil;
- return rb_str_new2(stringify((*std::tr1::static_pointer_cast<const WrappedSpec<PackageDepSpec> >(*ptr)->spec()->from_repository_ptr())).c_str());
- }
-
- /*
- * call-seq:
* version_requirements -> Array
*
* Fetch the version requirements. E.g. [ {:operator => '=', :spec => VersionSpec.new('0.1') } ]
@@ -1156,8 +1124,6 @@ namespace
rb_define_method(c_package_dep_spec, "package_name_part", RUBY_FUNC_CAST(&package_dep_spec_package_name_part), 0);
rb_define_method(c_package_dep_spec, "category_name_part", RUBY_FUNC_CAST(&package_dep_spec_category_name_part), 0);
rb_define_method(c_package_dep_spec, "slot_requirement", RUBY_FUNC_CAST(&package_dep_spec_slot_requirement_ptr), 0);
- rb_define_method(c_package_dep_spec, "in_repository", RUBY_FUNC_CAST(&package_dep_spec_in_repository_ptr), 0);
- rb_define_method(c_package_dep_spec, "from_repository", RUBY_FUNC_CAST(&package_dep_spec_from_repository_ptr), 0);
rb_define_method(c_package_dep_spec, "version_requirements", RUBY_FUNC_CAST(&package_dep_spec_version_requirements_ptr), 0);
rb_define_method(c_package_dep_spec, "version_requirements_mode", RUBY_FUNC_CAST(&package_dep_spec_version_requirements_mode), 0);
#ifdef CIARANM_REMOVED_THIS
diff --git a/ruby/dep_spec_TEST.rb b/ruby/dep_spec_TEST.rb
index 8647449..d9329af 100644
--- a/ruby/dep_spec_TEST.rb
+++ b/ruby/dep_spec_TEST.rb
@@ -120,15 +120,15 @@ module Paludis
assert_nil pdb.package
end
- def test_from_repository
- assert_nil pda.from_repository
- assert_nil pdb.from_repository
- end
-
- def test_in_repository
- assert_equal "testrepo", pda.in_repository
- assert_nil pdb.in_repository
- end
+### def test_from_repository
+### assert_nil pda.from_repository
+### assert_nil pdb.from_repository
+### end
+###
+### def test_in_repository
+### assert_equal "testrepo", pda.in_repository
+### assert_nil pdb.in_repository
+### end
def test_package_name_part
assert_nil pda.package_name_part
diff --git a/src/clients/adjutrix/keywords_graph.cc b/src/clients/adjutrix/keywords_graph.cc
index 5727f4b..c3c2b4f 100644
--- a/src/clients/adjutrix/keywords_graph.cc
+++ b/src/clients/adjutrix/keywords_graph.cc
@@ -73,9 +73,8 @@ namespace
FindUnusedPackagesTask task(&e, &repo);
std::tr1::shared_ptr<const PackageIDSequence> packages(e[selection::AllVersionsGroupedBySlot(
- generator::Matches(make_package_dep_spec()
- .package(package)
- .in_repository(repo.name())))]);
+ generator::InRepository(repo.name()) &
+ generator::Matches(make_package_dep_spec().package(package)))]);
std::tr1::shared_ptr<const PackageIDSequence> unused(task.execute(package));
if (packages->empty())
diff --git a/src/output/console_query_task.cc b/src/output/console_query_task.cc
index 892466e..4d1479c 100644
--- a/src/output/console_query_task.cc
+++ b/src/output/console_query_task.cc
@@ -134,7 +134,11 @@ void
ConsoleQueryTask::display_header(const PackageDepSpec & a, const std::tr1::shared_ptr<const PackageID> & e) const
{
if (a.version_requirements_ptr() || a.slot_requirement_ptr() || a.additional_requirements_ptr() ||
- a.in_repository_ptr() || a.from_repository_ptr())
+ a.in_repository_ptr() ||
+ a.from_repository_ptr() ||
+ a.installable_to_repository_ptr() ||
+ a.installable_to_path_ptr() ||
+ a.installed_at_path_ptr())
output_starred_item(render_as_package_name(stringify(a)));
else
output_starred_item(render_as_package_name(stringify(e->name())));
@@ -144,7 +148,11 @@ void
ConsoleQueryTask::display_compact(const PackageDepSpec & a, const std::tr1::shared_ptr<const PackageID> & e) const
{
if (a.version_requirements_ptr() || a.slot_requirement_ptr() || a.additional_requirements_ptr() ||
- a.in_repository_ptr() || a.from_repository_ptr())
+ a.in_repository_ptr() ||
+ a.from_repository_ptr() ||
+ a.installable_to_repository_ptr() ||
+ a.installable_to_path_ptr() ||
+ a.installed_at_path_ptr())
{
std::string pad(std::max<long>(1, 30 - stringify(a).length()), ' ');
output_starred_item_no_endl(render_as_package_name(stringify(a)) + pad);