aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-07-03 18:26:01 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2006-07-03 18:26:01 +0000
commit67ef8b8e171b716438b3955532e5851b98a83b13 (patch)
tree25aee1051f1a78899865a76a5ab155ef7ce790c0
parent2227a1484566d437bff8914b99e80c18d380aef5 (diff)
downloadpaludis-67ef8b8e171b716438b3955532e5851b98a83b13.tar.gz
paludis-67ef8b8e171b716438b3955532e5851b98a83b13.tar.xz
Add support for --environment-variable on the commandline
-rw-r--r--ebuild/Makefile.am1
-rw-r--r--ebuild/builtin_variable.bash24
-rwxr-xr-xebuild/ebuild.bash18
-rw-r--r--paludis/ebuild.cc37
-rw-r--r--paludis/ebuild.hh37
-rw-r--r--paludis/fake_repository.cc3
-rw-r--r--paludis/nothing_repository.cc3
-rw-r--r--paludis/portage_repository.cc35
-rw-r--r--paludis/portage_repository.hh5
-rw-r--r--paludis/repository.cc5
-rw-r--r--paludis/repository.hh41
-rw-r--r--paludis/vdb_repository.cc79
-rw-r--r--paludis/vdb_repository.hh5
-rw-r--r--src/applets.cc37
-rw-r--r--src/applets.hh3
-rw-r--r--src/command_line.cc2
-rw-r--r--src/command_line.hh3
-rw-r--r--src/paludis.cc10
18 files changed, 335 insertions, 13 deletions
diff --git a/ebuild/Makefile.am b/ebuild/Makefile.am
index a756995..e94c874 100644
--- a/ebuild/Makefile.am
+++ b/ebuild/Makefile.am
@@ -13,6 +13,7 @@ libexecprog_SCRIPTS = \
builtin_strip.bash \
builtin_tidyup.bash \
builtin_unmerge.bash \
+ builtin_variable.bash \
ebuild.bash \
echo_functions.bash \
kernel_functions.bash \
diff --git a/ebuild/builtin_variable.bash b/ebuild/builtin_variable.bash
new file mode 100644
index 0000000..3ffa7d6
--- /dev/null
+++ b/ebuild/builtin_variable.bash
@@ -0,0 +1,24 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# 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 as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# 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
+
+ebuild_f_variable()
+{
+ echo "${!PALUDIS_VARIABLE}"
+}
+
diff --git a/ebuild/ebuild.bash b/ebuild/ebuild.bash
index 0accc54..8e3eed8 100755
--- a/ebuild/ebuild.bash
+++ b/ebuild/ebuild.bash
@@ -187,7 +187,7 @@ ebuild_main()
for action in $@ ; do
case ${action} in
- metadata|init|fetch|merge|unmerge|tidyup|strip)
+ metadata|variable|init|fetch|merge|unmerge|tidyup|strip)
ebuild_load_module builtin_${action}
;;
@@ -207,14 +207,16 @@ ebuild_main()
esac
done
- if [[ $1 == metadata ]] ; then
- for f in cut tr date ; do
- eval "export ebuild_real_${f}=\"$(which $f )\""
- eval "${f}() { ebuild_notice qa 'global scope ${f}' ; $(which $f ) \"\$@\" ; }"
- done
+ if [[ $1 == metadata ]] || [[ $1 == variable ]] ; then
perform_hook ebuild_${action}_pre
- PATH="" ebuild_load_ebuild "${ebuild}"
- ebuild_f_metadata || die "${1} failed"
+ if [[ $1 != variable ]] || [[ -n "${ebuild}" ]] ; then
+ for f in cut tr date ; do
+ eval "export ebuild_real_${f}=\"$(which $f )\""
+ eval "${f}() { ebuild_notice qa 'global scope ${f}' ; $(which $f ) \"\$@\" ; }"
+ done
+ PATH="" ebuild_load_ebuild "${ebuild}"
+ fi
+ ebuild_f_${1} || die "${1} failed"
perform_hook ebuild_${action}_post
else
ebuild_load_ebuild "${ebuild}"
diff --git a/paludis/ebuild.cc b/paludis/ebuild.cc
index f231233..09bd155 100644
--- a/paludis/ebuild.cc
+++ b/paludis/ebuild.cc
@@ -19,6 +19,7 @@
#include <paludis/ebuild.hh>
#include <paludis/util/system.hh>
+#include <paludis/util/strip.hh>
#include <paludis/util/pstream.hh>
#include <paludis/util/log.hh>
#include <paludis/environment.hh>
@@ -203,6 +204,42 @@ EbuildMetadataCommand::do_run_command(const std::string & cmd)
}
}
+EbuildVariableCommand::EbuildVariableCommand(const EbuildCommandParams & p,
+ const std::string & var) :
+ EbuildCommand(p),
+ _var(var)
+{
+}
+
+std::string
+EbuildVariableCommand::commands() const
+{
+ return "variable";
+}
+
+bool
+EbuildVariableCommand::failure()
+{
+ return EbuildCommand::failure();
+}
+
+MakeEnvCommand
+EbuildVariableCommand::extend_command(const MakeEnvCommand & cmd)
+{
+ return cmd("PALUDIS_VARIABLE", _var);
+}
+
+bool
+EbuildVariableCommand::do_run_command(const std::string & cmd)
+{
+ PStream prog(cmd);
+ _result = strip_trailing_string(
+ std::string((std::istreambuf_iterator<char>(prog)),
+ std::istreambuf_iterator<char>()), "\n");
+
+ return (0 == prog.exit_status());
+}
+
std::string
EbuildFetchCommand::commands() const
{
diff --git a/paludis/ebuild.hh b/paludis/ebuild.hh
index 6a5326a..584de8a 100644
--- a/paludis/ebuild.hh
+++ b/paludis/ebuild.hh
@@ -203,6 +203,43 @@ namespace paludis
};
/**
+ * An EbuildVariableCommand is used to fetch the value of an environment
+ * variable for a particular ebuild in a PortageRepository.
+ *
+ * \ingroup grpebuildinterface
+ */
+ class EbuildVariableCommand :
+ public EbuildCommand
+ {
+ private:
+ std::string _result;
+ const std::string _var;
+
+ protected:
+ virtual std::string commands() const;
+
+ virtual MakeEnvCommand extend_command(const MakeEnvCommand &);
+
+ virtual bool do_run_command(const std::string &);
+
+ virtual bool failure();
+
+ public:
+ /**
+ * Constructor.
+ */
+ EbuildVariableCommand(const EbuildCommandParams &, const std::string &);
+
+ /**
+ * Fetch our result.
+ */
+ std::string result() const
+ {
+ return _result;
+ }
+ };
+
+ /**
* Keys for EbuildFetchCommandParams.
*
* \see EbuildFetchCommandParams
diff --git a/paludis/fake_repository.cc b/paludis/fake_repository.cc
index 4c5268c..38f5b85 100644
--- a/paludis/fake_repository.cc
+++ b/paludis/fake_repository.cc
@@ -76,7 +76,8 @@ FakeRepository::FakeRepository(const RepositoryName & name) :
param<repo_syncable>(static_cast<SyncableInterface *>(0)),
param<repo_uninstallable>(static_cast<UninstallableInterface *>(0)),
param<repo_use>(this),
- param<repo_world>(static_cast<WorldInterface *>(0))
+ param<repo_world>(static_cast<WorldInterface *>(0)),
+ param<repo_environment_variable>(static_cast<EnvironmentVariableInterface *>(0))
))),
Repository::MaskInterface(),
Repository::UseInterface(),
diff --git a/paludis/nothing_repository.cc b/paludis/nothing_repository.cc
index 78e33bd..6ccca9d 100644
--- a/paludis/nothing_repository.cc
+++ b/paludis/nothing_repository.cc
@@ -93,7 +93,8 @@ NothingRepository::NothingRepository(const NothingRepositoryParams & p) try :
param<repo_syncable>(this),
param<repo_uninstallable>(static_cast<UninstallableInterface *>(0)),
param<repo_use>(static_cast<UseInterface *>(0)),
- param<repo_world>(static_cast<WorldInterface *>(0))
+ param<repo_world>(static_cast<WorldInterface *>(0)),
+ param<repo_environment_variable>(static_cast<EnvironmentVariableInterface *>(0))
))),
PrivateImplementationPattern<NothingRepository>(new Implementation<NothingRepository>(p))
{
diff --git a/paludis/portage_repository.cc b/paludis/portage_repository.cc
index 0671c64..792d084 100644
--- a/paludis/portage_repository.cc
+++ b/paludis/portage_repository.cc
@@ -553,7 +553,8 @@ PortageRepository::PortageRepository(const PortageRepositoryParams & p) :
param<repo_syncable>(this),
param<repo_uninstallable>(static_cast<UninstallableInterface *>(0)),
param<repo_use>(this),
- param<repo_world>(static_cast<WorldInterface *>(0))
+ param<repo_world>(static_cast<WorldInterface *>(0)),
+ param<repo_environment_variable>(this)
))),
PrivateImplementationPattern<PortageRepository>(new Implementation<PortageRepository>(p))
{
@@ -2029,3 +2030,35 @@ PortageRepository::update_news() const
}
}
+std::string
+PortageRepository::get_environment_variable(
+ const PackageDatabaseEntry & for_package,
+ const std::string & var) const
+{
+ Context context("When fetching environment variable '" + var + "' from repository '"
+ + stringify(name()) + "':");
+
+ _imp->need_profiles();
+
+ QualifiedPackageName q(for_package.get<pde_name>());
+ EbuildVariableCommand cmd(EbuildCommandParams::create((
+ param<ecpk_environment>(_imp->env),
+ param<ecpk_db_entry>(&for_package),
+ param<ecpk_ebuild_dir>(_imp->location / stringify(q.get<qpn_category>()) /
+ stringify(q.get<qpn_package>())),
+ param<ecpk_files_dir>(_imp->location / stringify(q.get<qpn_category>()) /
+ stringify(q.get<qpn_package>()) / "files"),
+ param<ecpk_eclassdirs>(_imp->eclassdirs),
+ param<ecpk_portdir>(_imp->location),
+ param<ecpk_distdir>(_imp->distdir),
+ param<ecpk_buildroot>(_imp->buildroot)
+ )),
+ var);
+
+ if (! cmd())
+ throw EnvironmentVariableActionError("Couldn't get environment variable '" +
+ stringify(var) + "' for package '" + stringify(for_package) + "'");
+
+ return cmd.result();
+}
+
diff --git a/paludis/portage_repository.hh b/paludis/portage_repository.hh
index ba40789..8401a2d 100644
--- a/paludis/portage_repository.hh
+++ b/paludis/portage_repository.hh
@@ -110,6 +110,7 @@ namespace paludis
public Repository::SyncableInterface,
public Repository::NewsInterface,
public Repository::SetsInterface,
+ public Repository::EnvironmentVariableInterface,
private PrivateImplementationPattern<PortageRepository>
{
private:
@@ -203,6 +204,10 @@ namespace paludis
virtual void update_news() const;
+ virtual std::string get_environment_variable(
+ const PackageDatabaseEntry & for_package,
+ const std::string & var) const;
+
typedef CountedPtr<PortageRepository, count_policy::InternalCountTag> Pointer;
typedef CountedPtr<const PortageRepository, count_policy::InternalCountTag> ConstPointer;
};
diff --git a/paludis/repository.cc b/paludis/repository.cc
index ec9dc66..8831de1 100644
--- a/paludis/repository.cc
+++ b/paludis/repository.cc
@@ -60,6 +60,11 @@ PackageInstallActionError::PackageInstallActionError(const std::string & msg) th
{
}
+EnvironmentVariableActionError::EnvironmentVariableActionError(const std::string & msg) throw () :
+ PackageActionError("Environment variable query error: " + msg)
+{
+}
+
PackageFetchActionError::PackageFetchActionError(const std::string & msg) throw () :
PackageActionError("Fetch error: " + msg)
{
diff --git a/paludis/repository.hh b/paludis/repository.hh
index c5bd874..fb0b366 100644
--- a/paludis/repository.hh
+++ b/paludis/repository.hh
@@ -124,6 +124,7 @@ namespace paludis
repo_uninstallable,
repo_use,
repo_world,
+ repo_environment_variable,
last_repo
};
@@ -152,6 +153,7 @@ namespace paludis
class UninstallableInterface;
class UseInterface;
class WorldInterface;
+ class EnvironmentVariableInterface;
protected:
/**
@@ -171,7 +173,8 @@ namespace paludis
SmartRecordKey<repo_syncable, SyncableInterface *>,
SmartRecordKey<repo_uninstallable, UninstallableInterface *>,
SmartRecordKey<repo_use, UseInterface *>,
- SmartRecordKey<repo_world, WorldInterface *>
+ SmartRecordKey<repo_world, WorldInterface *>,
+ SmartRecordKey<repo_environment_variable, EnvironmentVariableInterface *>
{
};
@@ -719,6 +722,25 @@ namespace paludis
};
/**
+ * Interface for environment variable querying for repositories.
+ *
+ * \see Repository
+ * \ingroup grprepository
+ */
+ class Repository::EnvironmentVariableInterface
+ {
+ public:
+ /**
+ * Query an environment variable
+ */
+ virtual std::string get_environment_variable(
+ const PackageDatabaseEntry & for_package,
+ const std::string & var) const = 0;
+
+ virtual ~EnvironmentVariableInterface() { }
+ };
+
+ /**
* Thrown if a repository of the specified type does not exist.
*
* \ingroup grpexceptions
@@ -793,6 +815,23 @@ namespace paludis
PackageUninstallActionError(const std::string & msg) throw ();
};
+ /**
+ * Thrown if an environment variable query fails.
+ *
+ * \ingroup grprepository
+ * \ingroup grpexceptions
+ */
+ class EnvironmentVariableActionError :
+ public PackageActionError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ EnvironmentVariableActionError(const std::string & msg) throw ();
+ };
+
+
class PackageDatabase;
/**
diff --git a/paludis/vdb_repository.cc b/paludis/vdb_repository.cc
index 6930455..6fea778 100644
--- a/paludis/vdb_repository.cc
+++ b/paludis/vdb_repository.cc
@@ -368,7 +368,8 @@ VDBRepository::VDBRepository(const VDBRepositoryParams & p) :
param<repo_syncable>(static_cast<SyncableInterface *>(0)),
param<repo_uninstallable>(this),
param<repo_use>(this),
- param<repo_world>(this)
+ param<repo_world>(this),
+ param<repo_environment_variable>(this)
))),
PrivateImplementationPattern<VDBRepository>(new Implementation<VDBRepository>(p))
{
@@ -938,3 +939,79 @@ VDBRepository::remove_from_world(const QualifiedPackageName & n) const
std::copy(world_lines.begin(), world_lines.end(),
std::ostream_iterator<std::string>(world_file, "\n"));
}
+
+std::string
+VDBRepository::get_environment_variable(
+ const PackageDatabaseEntry & for_package,
+ const std::string & var) const
+{
+ Context context("When fetching environment variable '" + var + "' for '" +
+ stringify(for_package) + "':");
+
+ FSEntry vdb_dir(_imp->location / stringify(for_package.get<pde_name>().get<qpn_category>())
+ / (stringify(for_package.get<pde_name>().get<qpn_package>()) + "-" +
+ stringify(for_package.get<pde_version>())));
+
+ if (! vdb_dir.is_directory())
+ throw EnvironmentVariableActionError("Could not find VDB entry for '"
+ + stringify(for_package) + "'");
+
+ if ((vdb_dir / var).is_regular_file())
+ {
+ std::ifstream f(stringify(vdb_dir / var).c_str());
+ if (! f)
+ throw EnvironmentVariableActionError("Could not read '" +
+ stringify(vdb_dir / var) + "'");
+ return strip_trailing_string(
+ std::string((std::istreambuf_iterator<char>(f)),
+ std::istreambuf_iterator<char>()), "\n");
+ }
+ else if ((vdb_dir / "environment.bz2").is_regular_file())
+ {
+ /* Figure out the format of environment.bz2. If VDB_FORMAT is "paludis-1",
+ * or if there's no VDB_FORMAT and there're no lines with () and no =,
+ * it's an env dump. Otherwise it's a source file. */
+ bool is_source_file(false);
+
+ if ((vdb_dir / "VDB_FORMAT").is_regular_file())
+ {
+ std::ifstream f(stringify(vdb_dir / "VDB_FORMAT").c_str());
+ if (! f)
+ throw EnvironmentVariableActionError("Could not read '" +
+ stringify(vdb_dir / "VDB_FORMAT") + "'");
+ is_source_file = ("paludis-1" != strip_trailing_string(std::string(
+ (std::istreambuf_iterator<char>(f)),
+ std::istreambuf_iterator<char>()), "\n"));
+ }
+ else if (0 == run_command("bunzip2 < " + stringify(vdb_dir / "environment.bz2") +
+ " | grep -q '^[^=]\\+()'"))
+ is_source_file = true;
+
+ if (is_source_file)
+ {
+ PStream p("bash -c '( bunzip2 < " + stringify(vdb_dir / "environment.bz2" ) +
+ " ; echo echo \\$" + var + " ) | bash 2>/dev/null'");
+ std::string result(strip_trailing_string(std::string(
+ (std::istreambuf_iterator<char>(p)),
+ std::istreambuf_iterator<char>()), "\n"));
+ if (0 != p.exit_status())
+ throw EnvironmentVariableActionError("Could not load environment.bz2");
+ return result;
+ }
+ else
+ {
+ PStream p("bunzip2 < " + stringify(vdb_dir / "environment.bz2" ));
+ KeyValueConfigFile k(&p);
+
+ if (0 != p.exit_status())
+ throw EnvironmentVariableActionError("Could not get variable '" + var +
+ "' from environment.bz2 for '" + stringify(for_package) + "'");
+
+ return k.get(var);
+ }
+ }
+ else
+ throw EnvironmentVariableActionError("Could not get variable '" + var + "' for '"
+ + stringify(for_package) + "'");
+}
+
diff --git a/paludis/vdb_repository.hh b/paludis/vdb_repository.hh
index 93404c4..a35f201 100644
--- a/paludis/vdb_repository.hh
+++ b/paludis/vdb_repository.hh
@@ -90,6 +90,7 @@ namespace paludis
public Repository::UninstallableInterface,
public Repository::SetsInterface,
public Repository::WorldInterface,
+ public Repository::EnvironmentVariableInterface,
public PrivateImplementationPattern<VDBRepository>
{
protected:
@@ -168,6 +169,10 @@ namespace paludis
virtual void remove_from_world(const QualifiedPackageName &) const;
+ virtual std::string get_environment_variable(
+ const PackageDatabaseEntry & for_package,
+ const std::string & var) const;
+
typedef CountedPtr<VDBRepository, count_policy::InternalCountTag> Pointer;
typedef CountedPtr<const VDBRepository, count_policy::InternalCountTag> ConstPointer;
};
diff --git a/src/applets.cc b/src/applets.cc
index 05d39a7..dc5109e 100644
--- a/src/applets.cc
+++ b/src/applets.cc
@@ -75,6 +75,43 @@ int do_best_version()
return return_code;
}
+int do_environment_variable()
+{
+ int return_code(0);
+
+ p::Context context("When performing environment-variable action from command line:");
+ p::Environment * const env(p::DefaultEnvironment::get_instance());
+
+ std::string atom_str(*CommandLine::get_instance()->begin_parameters());
+ std::string var_str(* p::next(CommandLine::get_instance()->begin_parameters()));
+ p::PackageDepAtom::Pointer atom(new p::PackageDepAtom(atom_str));
+
+ p::PackageDatabaseEntryCollection::ConstPointer entries(env->package_database()->query(
+ atom, p::is_installed_only));
+
+ if (entries->empty())
+ entries = env->package_database()->query(atom, p::is_uninstalled_only);
+
+ if (entries->empty())
+ throw p::NoSuchPackageError(atom_str);
+
+ p::Repository::ConstPointer repo(env->package_database()->fetch_repository(
+ entries->begin()->get<p::pde_repository>()));
+ p::Repository::EnvironmentVariableInterface * env_if(
+ repo->get_interface<p::repo_environment_variable>());
+
+ if (! env_if)
+ {
+ std::cerr << "Repository '" << repo->name() <<
+ "' cannot be queried for environment variables" << std::endl;
+ return_code |= 1;
+ }
+ else
+ std::cout << env_if->get_environment_variable(*entries->begin(), var_str) << std::endl;
+
+ return return_code;
+}
+
int do_list_repository_formats()
{
int return_code(1);
diff --git a/src/applets.hh b/src/applets.hh
index 7474c0f..fc7e21b 100644
--- a/src/applets.hh
+++ b/src/applets.hh
@@ -32,6 +32,9 @@ int do_has_version();
/// Handle --best-version.
int do_best_version();
+/// Handle --environment-variable.
+int do_environment_variable();
+
/// Handle --list-repository-formats
int do_list_repository_formats();
diff --git a/src/command_line.cc b/src/command_line.cc
index 7a68895..87072a9 100644
--- a/src/command_line.cc
+++ b/src/command_line.cc
@@ -38,6 +38,8 @@ CommandLine::CommandLine() :
action_args_internal(this, "More actions (mostly for internal / script use)"),
a_has_version(&action_args_internal, "has-version", '\0', "Check whether the specified atom is installed"),
a_best_version(&action_args_internal, "best-version", '\0', "Display the best version of the specified atom"),
+ a_environment_variable(&action_args_internal, "environment-variable", '\0', "Display the value of an environment "
+ "variable for a particular package"),
a_list_sync_protocols(&action_args_internal, "list-sync-protocols", '\0', "List available sync protocols"),
a_list_repository_formats(&action_args_internal, "list-repository-formats", '\0', "List available repository formats"),
a_list_dep_tag_categories(&action_args_internal, "list-dep-tag-categories", '\0', "List known dep tag categories"),
diff --git a/src/command_line.hh b/src/command_line.hh
index fad52ea..2d9315e 100644
--- a/src/command_line.hh
+++ b/src/command_line.hh
@@ -92,6 +92,9 @@ class CommandLine :
/// --best-version
paludis::args::SwitchArg a_best_version;
+ /// --environment-variable
+ paludis::args::SwitchArg a_environment_variable;
+
/// --list-sync-protocols
paludis::args::SwitchArg a_list_sync_protocols;
diff --git a/src/paludis.cc b/src/paludis.cc
index 0b91eda..2daf286 100644
--- a/src/paludis.cc
+++ b/src/paludis.cc
@@ -101,6 +101,7 @@ main(int argc, char *argv[])
CommandLine::get_instance()->a_owner.specified() +
CommandLine::get_instance()->a_has_version.specified() +
CommandLine::get_instance()->a_update_news.specified() +
+ CommandLine::get_instance()->a_environment_variable.specified() +
CommandLine::get_instance()->a_best_version.specified()))
{
if ((1 == std::distance(CommandLine::get_instance()->begin_parameters(),
@@ -258,6 +259,15 @@ main(int argc, char *argv[])
return do_best_version();
}
+ if (CommandLine::get_instance()->a_environment_variable.specified())
+ {
+ if (2 != std::distance(CommandLine::get_instance()->begin_parameters(),
+ CommandLine::get_instance()->end_parameters()))
+ throw DoHelp("environment-variable action takes exactly two parameters (depatom var)");
+
+ return do_environment_variable();
+ }
+
if (CommandLine::get_instance()->a_update_news.specified())
{
if (! CommandLine::get_instance()->empty())