aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-01-22 00:31:02 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-01-22 00:31:02 +0000
commit66b4acc5c80fb242eac4e5e3358a80614d005865 (patch)
treeed95f8befd4eefb9262c9fd8a58e451d050cdf70
parentd5aa27d7859537369060a1c042fdb478bfc3d2df (diff)
downloadpaludis-66b4acc5c80fb242eac4e5e3358a80614d005865.tar.gz
paludis-66b4acc5c80fb242eac4e5e3358a80614d005865.tar.xz
start accounts
-rw-r--r--configure.ac4
-rw-r--r--paludis/repositories/accounts/Makefile.am96
-rw-r--r--paludis/repositories/accounts/accounts_exceptions.cc29
-rw-r--r--paludis/repositories/accounts/accounts_exceptions.hh39
-rw-r--r--paludis/repositories/accounts/accounts_handler.cc30
-rw-r--r--paludis/repositories/accounts/accounts_handler.hh40
-rw-r--r--paludis/repositories/accounts/accounts_id.cc419
-rw-r--r--paludis/repositories/accounts/accounts_id.hh106
-rw-r--r--paludis/repositories/accounts/accounts_repository.cc464
-rw-r--r--paludis/repositories/accounts/accounts_repository.hh169
-rw-r--r--paludis/repositories/accounts/accounts_repository_TEST.cc60
-rw-r--r--paludis/repositories/accounts/accounts_repository_store.cc278
-rw-r--r--paludis/repositories/accounts/accounts_repository_store.hh96
-rw-r--r--paludis/repositories/accounts/dummy_accounts_handler.cc34
-rw-r--r--paludis/repositories/accounts/dummy_accounts_handler.hh38
-rw-r--r--paludis/repositories/accounts/installed_accounts_id.cc284
-rw-r--r--paludis/repositories/accounts/installed_accounts_id.hh103
-rw-r--r--paludis/repositories/accounts/passwd_accounts_handler.cc200
-rw-r--r--paludis/repositories/accounts/passwd_accounts_handler.hh38
-rw-r--r--paludis/repositories/accounts/registration.cc64
-rw-r--r--paludis/repositories/e/e_repository.cc6
-rw-r--r--paludis/repositories/e/exheres_layout.cc14
-rw-r--r--paludis/repositories/e/exheres_layout.hh5
-rw-r--r--paludis/repositories/e/layout.hh6
-rw-r--r--paludis/repositories/e/traditional_layout.cc9
-rw-r--r--paludis/repositories/e/traditional_layout.hh5
26 files changed, 2629 insertions, 7 deletions
diff --git a/configure.ac b/configure.ac
index 678d61f..6bf10ba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1253,7 +1253,7 @@ AC_SUBST([VIM_INSTALL_DIR])
dnl }}}
dnl {{{ repositories
-ALL_REPOSITORIES="cran e fake gems unavailable unpackaged unwritten virtuals"
+ALL_REPOSITORIES="accounts cran e fake gems unavailable unpackaged unwritten virtuals"
DEFAULT_REPOSITORIES="e fake unavailable unpackaged unwritten virtuals"
AC_MSG_CHECKING([which repositories to build...])
AC_ARG_WITH([repositories],
@@ -1262,6 +1262,7 @@ AC_ARG_WITH([repositories],
all All available repositories
default Equivalent to e,fake,unavailable,unpackaged,unwritten,virtuals
+ accounts Account management (requires distribution support)
cran The Comprehensive R Archive Network (unusable)
e Ebuild, Ebin, Exheres, VDB etc
fake A fake repository for test cases and adjutrix
@@ -1524,6 +1525,7 @@ AC_OUTPUT(
paludis/environments/test/Makefile
paludis/fetchers/Makefile
paludis/repositories/Makefile
+ paludis/repositories/accounts/Makefile
paludis/repositories/cran/Makefile
paludis/repositories/cran/cran/Makefile
paludis/repositories/e/Makefile
diff --git a/paludis/repositories/accounts/Makefile.am b/paludis/repositories/accounts/Makefile.am
new file mode 100644
index 0000000..35dd4ac
--- /dev/null
+++ b/paludis/repositories/accounts/Makefile.am
@@ -0,0 +1,96 @@
+SUBDIRS = .
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda *.loT *.epicfail
+DISTCLEANFILES =
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CXXFLAGS = -I$(top_srcdir) -I$(top_builddir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
+DEFS= \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+paludis_repositories_libdir = $(libdir)/paludis/repositories
+paludis_repositories_lib_LTLIBRARIES = libpaludisaccountsrepository_@PALUDIS_PC_SLOT@.la
+
+paludis_repositories_accounts_includedir = $(includedir)/paludis-$(PALUDIS_PC_SLOT)/paludis/repositories/accounts/
+libpaludisaccountsrepository_@PALUDIS_PC_SLOT@_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+
+paludis_repositories_accounts_include_HEADERS = \
+ accounts_exceptions.hh \
+ accounts_handler.hh \
+ accounts_repository.hh \
+ accounts_repository_store.hh \
+ dummy_accounts_handler.hh \
+ passwd_accounts_handler.hh \
+ accounts_id.hh \
+ installed_accounts_id.hh
+
+libpaludisaccountsrepository_@PALUDIS_PC_SLOT@_la_SOURCES = \
+ accounts_exceptions.cc \
+ accounts_handler.cc \
+ accounts_repository.cc \
+ accounts_repository_store.cc \
+ accounts_id.cc \
+ installed_accounts_id.cc \
+ dummy_accounts_handler.cc \
+ passwd_accounts_handler.cc \
+ registration.cc \
+ $(paludis_repositories_accounts_include_HEADERS)
+
+libpaludisaccountsrepository_@PALUDIS_PC_SLOT@_la_LIBADD = \
+ $(top_builddir)/paludis/libpaludis_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/util/libpaludisutil_@PALUDIS_PC_SLOT@.la \
+ $(DYNAMIC_LD_LIBS)
+
+accounts_repository_TEST_SOURCES = accounts_repository_TEST.cc
+
+accounts_repository_TEST_LDADD = \
+ libpaludisaccountsrepository_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/util/libpaludisutil_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/paludis/libpaludis_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/test/libtest.a \
+ $(DYNAMIC_LD_LIBS)
+
+accounts_repository_TEST_CXXFLAGS = $(AM_CXXFLAGS) @PALUDIS_CXXFLAGS_NO_DEBUGGING@
+
+EXTRA_DIST = \
+ accounts_repository_TEST.cc
+
+check_SCRIPTS =
+
+TESTS_ENVIRONMENT = env \
+ TEST_OUTPUT_WRAPPER="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/outputwrapper`" \
+ PALUDIS_OUTPUTWRAPPER_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/`" \
+ PALUDIS_EBUILD_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_srcdir)/paludis/repositories/e/ebuild/`" \
+ PALUDIS_EAPIS_DIR="$(top_srcdir)/paludis/repositories/e/eapis/" \
+ PALUDIS_DISTRIBUTIONS_DIR="$(top_srcdir)/paludis/distributions/" \
+ PALUDIS_DISTRIBUTION="gentoo" \
+ PALUDIS_FETCHERS_DIR="$(top_srcdir)/paludis/fetchers/" \
+ PALUDIS_OPTIONS="" \
+ PALUDIS_SKIP_CONFIG="yes" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ PALUDIS_REPOSITORY_SO_DIR="$(top_builddir)/paludis/repositories" \
+ PALUDIS_NO_CHOWN="yes" \
+ bash $(top_srcdir)/test/run_test.sh
+
+TESTS = \
+ accounts_repository_TEST
+
+check_PROGRAMS = $(TESTS)
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+distcheck-deps-local : $(DISTCHECK_DEPS)
+
+distcheck-deps : distcheck-deps-subdirs
+
+distcheck-deps-subdirs :
+ for s in $(SUBDIRS) . ; do if test x$$s = x. ; then $(MAKE) distcheck-deps-local || exit 1 ; \
+ else $(MAKE) -C $$s distcheck-deps || exit 1 ; fi ; done
+
+
diff --git a/paludis/repositories/accounts/accounts_exceptions.cc b/paludis/repositories/accounts/accounts_exceptions.cc
new file mode 100644
index 0000000..39f4ba3
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_exceptions.cc
@@ -0,0 +1,29 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repositories/accounts/accounts_exceptions.hh>
+
+using namespace paludis;
+using namespace paludis::accounts_repository;
+
+AccountsRepositoryConfigurationError::AccountsRepositoryConfigurationError(const std::string & s) throw () :
+ ConfigurationError("AccountsRepository configuration error: " + s)
+{
+}
+
diff --git a/paludis/repositories/accounts/accounts_exceptions.hh b/paludis/repositories/accounts/accounts_exceptions.hh
new file mode 100644
index 0000000..68dca53
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_exceptions.hh
@@ -0,0 +1,39 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_ACCOUNTS_EXCEPTIONS_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_ACCOUNTS_EXCEPTIONS_HH 1
+
+#include <paludis/util/exception.hh>
+#include <paludis/util/attributes.hh>
+
+namespace paludis
+{
+ namespace accounts_repository
+ {
+ class PALUDIS_VISIBLE AccountsRepositoryConfigurationError :
+ public ConfigurationError
+ {
+ public:
+ AccountsRepositoryConfigurationError(const std::string &) throw ();
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/accounts/accounts_handler.cc b/paludis/repositories/accounts/accounts_handler.cc
new file mode 100644
index 0000000..7206907
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_handler.cc
@@ -0,0 +1,30 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repositories/accounts/accounts_handler.hh>
+#include <paludis/util/simple_visitor_cast.hh>
+#include <paludis/action.hh>
+
+using namespace paludis;
+using namespace paludis::accounts_repository;
+
+AccountsHandler::~AccountsHandler()
+{
+}
+
diff --git a/paludis/repositories/accounts/accounts_handler.hh b/paludis/repositories/accounts/accounts_handler.hh
new file mode 100644
index 0000000..85eee6a
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_handler.hh
@@ -0,0 +1,40 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_ACCOUNTS_HANDLER_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_ACCOUNTS_HANDLER_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <paludis/repository-fwd.hh>
+
+namespace paludis
+{
+ namespace accounts_repository
+ {
+ class AccountsHandler
+ {
+ public:
+ virtual ~AccountsHandler() = 0;
+
+ virtual void merge(const MergeParams &) = 0;
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/accounts/accounts_id.cc b/paludis/repositories/accounts/accounts_id.cc
new file mode 100644
index 0000000..7d7c9e2
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_id.cc
@@ -0,0 +1,419 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repositories/accounts/accounts_id.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/config_file.hh>
+#include <paludis/util/options.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/hashes.hh>
+#include <paludis/util/simple_visitor_cast.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/mutex.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/name.hh>
+#include <paludis/version_spec.hh>
+#include <paludis/literal_metadata_key.hh>
+#include <paludis/repository.hh>
+#include <paludis/action.hh>
+
+using namespace paludis;
+using namespace paludis::accounts_repository;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<AccountsUserID>
+ {
+ const Environment * const env;
+
+ const QualifiedPackageName name;
+ const VersionSpec version;
+ const SlotName slot;
+ const std::tr1::shared_ptr<const Repository> repository;
+
+ const std::tr1::shared_ptr<const LiteralMetadataValueKey<FSEntry> > fs_location_key;
+ const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > > from_repositories_key;
+
+ mutable Mutex mutex;
+ mutable bool has_file_keys;
+ mutable bool has_metadata_keys;
+ mutable std::tr1::shared_ptr<const LiteralMetadataValueKey<std::string> > username_key;
+ mutable std::tr1::shared_ptr<const LiteralMetadataValueKey<std::string> > gecos_key;
+ mutable std::tr1::shared_ptr<const LiteralMetadataValueKey<std::string> > preferred_uid_key;
+ mutable std::tr1::shared_ptr<const LiteralMetadataValueKey<std::string> > default_group_key;
+ mutable std::tr1::shared_ptr<const LiteralMetadataStringSetKey> extra_groups_key;
+ mutable std::tr1::shared_ptr<const LiteralMetadataValueKey<std::string> > home_key;
+ mutable std::tr1::shared_ptr<const LiteralMetadataValueKey<std::string> > shell_key;
+
+ Implementation(const Environment * const e,
+ const QualifiedPackageName & q, const std::tr1::shared_ptr<const Repository> & r,
+ const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > > & f,
+ const FSEntry & l) :
+ env(e),
+ name(q),
+ version("0"),
+ slot("0"),
+ repository(r),
+ fs_location_key(new LiteralMetadataValueKey<FSEntry>("location", "Location", mkt_internal, l)),
+ from_repositories_key(f),
+ has_file_keys(false),
+ has_metadata_keys(false)
+ {
+ }
+ };
+}
+
+AccountsUserID::AccountsUserID(const Environment * const e,
+ const QualifiedPackageName & q, const std::tr1::shared_ptr<const Repository> & r,
+ const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > > & f, const FSEntry & l) :
+ PrivateImplementationPattern<AccountsUserID>(new Implementation<AccountsUserID>(e, q, r, f, l)),
+ _imp(PrivateImplementationPattern<AccountsUserID>::_imp)
+{
+}
+
+AccountsUserID::~AccountsUserID()
+{
+}
+
+void
+AccountsUserID::_add_metadata_keys() const
+{
+ Lock lock(_imp->mutex);
+
+ if (_imp->has_metadata_keys)
+ return;
+
+ add_metadata_key(_imp->fs_location_key);
+ add_metadata_key(_imp->from_repositories_key);
+
+ if (_imp->username_key)
+ add_metadata_key(_imp->username_key);
+ if (_imp->gecos_key)
+ add_metadata_key(_imp->gecos_key);
+ if (_imp->preferred_uid_key)
+ add_metadata_key(_imp->preferred_uid_key);
+ if (_imp->default_group_key)
+ add_metadata_key(_imp->default_group_key);
+ if (_imp->extra_groups_key)
+ add_metadata_key(_imp->extra_groups_key);
+ if (_imp->shell_key)
+ add_metadata_key(_imp->shell_key);
+ if (_imp->home_key)
+ add_metadata_key(_imp->home_key);
+
+ _imp->has_metadata_keys = true;
+}
+
+void
+AccountsUserID::_need_file_keys() const
+{
+ if (_imp->has_file_keys)
+ return;
+
+ Lock lock(_imp->mutex);
+
+ KeyValueConfigFile k(_imp->fs_location_key->value(), KeyValueConfigFileOptions(),
+ &KeyValueConfigFile::no_defaults, &KeyValueConfigFile::no_transformation);
+
+ /* also need to change the handlers if any of the raw names are changed */
+
+ _imp->username_key.reset(new LiteralMetadataValueKey<std::string>("username", "Username",
+ mkt_significant, stringify(name().package())));
+
+ if (! k.get("gecos").empty())
+ _imp->gecos_key.reset(new LiteralMetadataValueKey<std::string>("gecos", "Description",
+ mkt_significant, k.get("gecos")));
+
+ if (! k.get("preferred_uid").empty())
+ _imp->preferred_uid_key.reset(new LiteralMetadataValueKey<std::string>("preferred_uid", "Preferred UID",
+ mkt_normal, k.get("preferred_uid")));
+
+ if (! k.get("shell").empty())
+ _imp->shell_key.reset(new LiteralMetadataValueKey<std::string>("shell", "Shell",
+ mkt_normal, k.get("shell")));
+
+ if (! k.get("home").empty())
+ _imp->home_key.reset(new LiteralMetadataValueKey<std::string>("home", "Home Directory",
+ mkt_normal, k.get("home")));
+
+ if (! k.get("default_group").empty())
+ _imp->default_group_key.reset(new LiteralMetadataValueKey<std::string>("default_group", "Default Group",
+ mkt_normal, k.get("default_group")));
+
+ if (! k.get("extra_groups").empty())
+ {
+ std::tr1::shared_ptr<Set<std::string> > groups_s(new Set<std::string>);
+ tokenise_whitespace(k.get("extra_groups"), groups_s->inserter());
+ _imp->extra_groups_key.reset(new LiteralMetadataStringSetKey("extra_groups", "Extra Groups",
+ mkt_normal, groups_s));
+ }
+
+ _imp->has_file_keys = true;
+}
+
+void
+AccountsUserID::need_keys_added() const
+{
+ if (! _imp->has_file_keys)
+ _need_file_keys();
+
+ if (! _imp->has_metadata_keys)
+ _add_metadata_keys();
+}
+
+void
+AccountsUserID::clear_metadata_keys() const
+{
+ Lock lock(_imp->mutex);
+ _imp->has_metadata_keys = false;
+ PackageID::clear_metadata_keys();
+}
+
+void
+AccountsUserID::need_masks_added() const
+{
+}
+
+const QualifiedPackageName
+AccountsUserID::name() const
+{
+ return _imp->name;
+}
+
+const VersionSpec
+AccountsUserID::version() const
+{
+ return _imp->version;
+}
+
+const SlotName
+AccountsUserID::slot() const
+{
+ return _imp->slot;
+}
+
+const std::tr1::shared_ptr<const Repository>
+AccountsUserID::repository() const
+{
+ return _imp->repository;
+}
+
+const std::string
+AccountsUserID::canonical_form(const PackageIDCanonicalForm f) const
+{
+ switch (f)
+ {
+ case idcf_full:
+ return stringify(name()) + "-" + stringify(version()) + ":" + stringify(slot()) + "::" + stringify(repository()->name());
+
+ case idcf_no_version:
+ return stringify(name()) + ":" + stringify(slot()) + "::" + stringify(repository()->name());
+
+ case idcf_version:
+ return stringify(version());
+
+ case last_idcf:
+ break;
+ }
+
+ throw InternalError(PALUDIS_HERE, "Bad PackageIDCanonicalForm");
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const PackageID> > >
+AccountsUserID::virtual_for_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataCollectionKey<KeywordNameSet> >
+AccountsUserID::keywords_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<ProvideSpecTree> >
+AccountsUserID::provide_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataCollectionKey<PackageIDSequence> >
+AccountsUserID::contains_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const PackageID> > >
+AccountsUserID::contained_in_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+AccountsUserID::build_dependencies_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+AccountsUserID::run_dependencies_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+AccountsUserID::post_dependencies_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+AccountsUserID::suggested_dependencies_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<FetchableURISpecTree> >
+AccountsUserID::fetches_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<SimpleURISpecTree> >
+AccountsUserID::homepage_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::string> >
+AccountsUserID::short_description_key() const
+{
+ _need_file_keys();
+ return _imp->gecos_key;
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::string> >
+AccountsUserID::long_description_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const Contents> > >
+AccountsUserID::contents_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataTimeKey>
+AccountsUserID::installed_time_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > >
+AccountsUserID::from_repositories_key() const
+{
+ return _imp->from_repositories_key;
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<FSEntry> >
+AccountsUserID::fs_location_key() const
+{
+ return _imp->fs_location_key;
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<bool> >
+AccountsUserID::transient_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const Choices> > >
+AccountsUserID::choices_key() const
+{
+ return make_null_shared_ptr();
+}
+
+std::tr1::shared_ptr<const Set<std::string> >
+AccountsUserID::breaks_portage() const
+{
+ return make_shared_ptr(new Set<std::string>);
+}
+
+bool
+AccountsUserID::arbitrary_less_than_comparison(const PackageID & other) const
+{
+ if (slot() < other.slot())
+ return true;
+
+ return false;
+}
+
+std::size_t
+AccountsUserID::extra_hash_value() const
+{
+ return Hash<SlotName>()(slot());
+}
+
+bool
+AccountsUserID::supports_action(const SupportsActionTestBase & test) const
+{
+ return simple_visitor_cast<const SupportsActionTest<InstallAction> >(test);
+}
+
+void
+AccountsUserID::perform_action(Action & action) const
+{
+ const InstallAction * const install_action(simple_visitor_cast<const InstallAction>(action));
+ if (! install_action)
+ throw UnsupportedActionError(*this, action);
+
+ if (! (*install_action->options.destination()).destination_interface())
+ throw InstallActionError("Can't install '" + stringify(*this)
+ + "' to destination '" + stringify(install_action->options.destination()->name())
+ + "' because destination does not provide destination_interface");
+
+ switch (install_action->options.want_phase()("merge"))
+ {
+ case wp_yes:
+ {
+ (*install_action->options.destination()).destination_interface()->merge(
+ make_named_values<MergeParams>(
+ value_for<n::environment_file>(FSEntry("/dev/null")),
+ value_for<n::image_dir>(fs_location_key()->value()),
+ value_for<n::options>(MergerOptions() + mo_rewrite_symlinks + mo_allow_empty_dirs),
+ value_for<n::package_id>(shared_from_this()),
+ value_for<n::used_this_for_config_protect>(install_action->options.used_this_for_config_protect())
+ ));
+ }
+ break;
+
+ case wp_skip:
+ break;
+
+ case wp_abort:
+ throw InstallActionError("Told to abort install");
+
+ case last_wp:
+ throw InternalError(PALUDIS_HERE, "bad WantPhase");
+ }
+}
+
diff --git a/paludis/repositories/accounts/accounts_id.hh b/paludis/repositories/accounts/accounts_id.hh
new file mode 100644
index 0000000..a3fc52c
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_id.hh
@@ -0,0 +1,106 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_ACCOUNTS_ID_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_ACCOUNTS_ID_HH 1
+
+#include <paludis/package_id.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace paludis
+{
+ namespace accounts_repository
+ {
+ class AccountsRepository;
+
+ class AccountsUserID :
+ public PackageID,
+ private PrivateImplementationPattern<AccountsUserID>,
+ public std::tr1::enable_shared_from_this<AccountsUserID>
+ {
+ private:
+ PrivateImplementationPattern<AccountsUserID>::ImpPtr & _imp;
+
+ void _add_metadata_keys() const;
+ void _need_file_keys() const;
+
+ protected:
+ virtual void clear_metadata_keys() const;
+ virtual void need_keys_added() const;
+ virtual void need_masks_added() const;
+
+ public:
+ AccountsUserID(const Environment * const,
+ const QualifiedPackageName &, const std::tr1::shared_ptr<const Repository> &,
+ const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > > &,
+ const FSEntry &);
+ ~AccountsUserID();
+
+ virtual const std::string canonical_form(const PackageIDCanonicalForm) const;
+
+ virtual const QualifiedPackageName name() const;
+ virtual const VersionSpec version() const;
+ virtual const SlotName slot() const;
+ virtual const std::tr1::shared_ptr<const Repository> repository() const;
+
+ ///\name Specific metadata keys
+ ///\{
+
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const PackageID> > > virtual_for_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataCollectionKey<KeywordNameSet> > keywords_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataSpecTreeKey<ProvideSpecTree> > provide_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataCollectionKey<PackageIDSequence> > contains_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const PackageID> > > contained_in_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > build_dependencies_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > run_dependencies_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > post_dependencies_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > suggested_dependencies_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataSpecTreeKey<FetchableURISpecTree> > fetches_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataSpecTreeKey<SimpleURISpecTree> > homepage_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<std::string> > short_description_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<std::string> > long_description_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const Contents> > > contents_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataTimeKey> installed_time_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > > from_repositories_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<FSEntry> > fs_location_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<bool> > transient_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const Choices> > > choices_key() const;
+
+ ///\}
+
+ ///\name Actions
+ ///\{
+
+ virtual bool supports_action(const SupportsActionTestBase &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual void perform_action(Action &) const;
+
+ ///\}
+
+ virtual std::tr1::shared_ptr<const Set<std::string> > breaks_portage() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool arbitrary_less_than_comparison(const PackageID &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::size_t extra_hash_value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/accounts/accounts_repository.cc b/paludis/repositories/accounts/accounts_repository.cc
new file mode 100644
index 0000000..dee923f
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_repository.cc
@@ -0,0 +1,464 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repositories/accounts/accounts_repository.hh>
+#include <paludis/repositories/accounts/accounts_exceptions.hh>
+#include <paludis/repositories/accounts/accounts_repository_store.hh>
+#include <paludis/repositories/accounts/dummy_accounts_handler.hh>
+#include <paludis/repositories/accounts/passwd_accounts_handler.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/active_object_ptr.hh>
+#include <paludis/util/deferred_construction_ptr.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/dep_tag.hh>
+#include <paludis/literal_metadata_key.hh>
+#include <paludis/action.hh>
+#include <paludis/package_id.hh>
+#include <paludis/environment.hh>
+
+using namespace paludis;
+using namespace paludis::accounts_repository;
+
+namespace
+{
+ std::tr1::shared_ptr<AccountsHandler> make_handler(const std::string & handler)
+ {
+ if (handler == "dummy")
+ return make_shared_ptr(new DummyAccountsHandler);
+ else if (handler == "passwd")
+ return make_shared_ptr(new PasswdAccountsHandler);
+ else
+ throw AccountsRepositoryConfigurationError("Unknown accounts handler '" + handler + "'");
+ }
+
+ std::tr1::shared_ptr<AccountsRepositoryStore>
+ make_store(const AccountsRepository * const repo, const AccountsRepositoryParams & p)
+ {
+ return make_shared_ptr(new AccountsRepositoryStore(p.environment(), repo, false));
+ }
+
+ std::tr1::shared_ptr<AccountsRepositoryStore>
+ make_installed_store(const AccountsRepository * const repo, const InstalledAccountsRepositoryParams & p)
+ {
+ return make_shared_ptr(new AccountsRepositoryStore(p.environment(), repo, true));
+ }
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<AccountsRepository>
+ {
+ const std::tr1::shared_ptr<const AccountsRepositoryParams> params_if_not_installed;
+ const std::tr1::shared_ptr<const InstalledAccountsRepositoryParams> params_if_installed;
+ const std::tr1::shared_ptr<AccountsHandler> handler_if_installed;
+
+ const std::tr1::shared_ptr<LiteralMetadataValueKey<std::string> > format_key;
+ const std::tr1::shared_ptr<LiteralMetadataValueKey<std::string> > handler_key;
+ const std::tr1::shared_ptr<LiteralMetadataValueKey<FSEntry> > installed_root_key;
+
+ const ActiveObjectPtr<DeferredConstructionPtr<std::tr1::shared_ptr<AccountsRepositoryStore> > > store;
+
+ Implementation(AccountsRepository * const repo, const AccountsRepositoryParams & p) :
+ params_if_not_installed(new AccountsRepositoryParams(p)),
+ format_key(new LiteralMetadataValueKey<std::string> ("format", "format", mkt_significant, "accounts")),
+ store(DeferredConstructionPtr<std::tr1::shared_ptr<AccountsRepositoryStore> > (
+ std::tr1::bind(&make_store, repo, std::tr1::cref(*params_if_not_installed))))
+ {
+ }
+
+ Implementation(AccountsRepository * const repo, const InstalledAccountsRepositoryParams & p) :
+ params_if_installed(new InstalledAccountsRepositoryParams(p)),
+ handler_if_installed(make_handler(p.handler())),
+ format_key(new LiteralMetadataValueKey<std::string> ("format", "format", mkt_significant, "installed-accounts")),
+ handler_key(new LiteralMetadataValueKey<std::string> ("handler", "handler", mkt_normal, p.handler())),
+ installed_root_key(new LiteralMetadataValueKey<FSEntry>("root", "root", mkt_normal, p.root())),
+ store(DeferredConstructionPtr<std::tr1::shared_ptr<AccountsRepositoryStore> > (
+ std::tr1::bind(&make_installed_store, repo, std::tr1::cref(*params_if_installed))))
+ {
+ }
+ };
+}
+
+AccountsRepository::AccountsRepository(const AccountsRepositoryParams & p) :
+ PrivateImplementationPattern<AccountsRepository>(new Implementation<AccountsRepository>(this, p)),
+ Repository(
+ p.environment(),
+ p.name(),
+ make_named_values<RepositoryCapabilities>(
+ value_for<n::destination_interface>(static_cast<RepositoryDestinationInterface *>(0)),
+ value_for<n::e_interface>(static_cast<RepositoryEInterface *>(0)),
+ value_for<n::environment_variable_interface>(static_cast<RepositoryEnvironmentVariableInterface *>(0)),
+ value_for<n::hook_interface>(static_cast<RepositoryHookInterface *>(0)),
+ value_for<n::make_virtuals_interface>(static_cast<RepositoryMakeVirtualsInterface *>(0)),
+ value_for<n::manifest_interface>(static_cast<RepositoryManifestInterface *>(0)),
+ value_for<n::mirrors_interface>(static_cast<RepositoryMirrorsInterface *>(0)),
+ value_for<n::provides_interface>(static_cast<RepositoryProvidesInterface *>(0)),
+ value_for<n::qa_interface>(static_cast<RepositoryQAInterface *>(0)),
+ value_for<n::sets_interface>(this),
+ value_for<n::syncable_interface>(static_cast<RepositorySyncableInterface *>(0)),
+ value_for<n::virtuals_interface>(static_cast<RepositoryVirtualsInterface *>(0))
+ )),
+ _imp(PrivateImplementationPattern<AccountsRepository>::_imp)
+{
+ _add_metadata_keys();
+}
+
+AccountsRepository::AccountsRepository(const InstalledAccountsRepositoryParams & p) :
+ PrivateImplementationPattern<AccountsRepository>(new Implementation<AccountsRepository>(this, p)),
+ Repository(
+ p.environment(),
+ p.name(),
+ make_named_values<RepositoryCapabilities>(
+ value_for<n::destination_interface>(this),
+ value_for<n::e_interface>(static_cast<RepositoryEInterface *>(0)),
+ value_for<n::environment_variable_interface>(static_cast<RepositoryEnvironmentVariableInterface *>(0)),
+ value_for<n::hook_interface>(static_cast<RepositoryHookInterface *>(0)),
+ value_for<n::make_virtuals_interface>(static_cast<RepositoryMakeVirtualsInterface *>(0)),
+ value_for<n::manifest_interface>(static_cast<RepositoryManifestInterface *>(0)),
+ value_for<n::mirrors_interface>(static_cast<RepositoryMirrorsInterface *>(0)),
+ value_for<n::provides_interface>(static_cast<RepositoryProvidesInterface *>(0)),
+ value_for<n::qa_interface>(static_cast<RepositoryQAInterface *>(0)),
+ value_for<n::sets_interface>(this),
+ value_for<n::syncable_interface>(static_cast<RepositorySyncableInterface *>(0)),
+ value_for<n::virtuals_interface>(static_cast<RepositoryVirtualsInterface *>(0))
+ )),
+ _imp(PrivateImplementationPattern<AccountsRepository>::_imp)
+{
+ _add_metadata_keys();
+}
+
+void
+AccountsRepository::need_keys_added() const
+{
+}
+
+void
+AccountsRepository::_add_metadata_keys()
+{
+ clear_metadata_keys();
+ add_metadata_key(_imp->format_key);
+
+ if (_imp->handler_key)
+ add_metadata_key(_imp->handler_key);
+}
+
+AccountsRepository::~AccountsRepository()
+{
+}
+
+std::tr1::shared_ptr<Repository>
+AccountsRepository::repository_factory_create(
+ Environment * const env,
+ const std::tr1::function<std::string (const std::string &)> & f)
+{
+ Context context("When making accounts repository from repo_file '" + f("repo_file") + "':");
+
+ std::string name_str(f("name"));
+ if (name_str.empty())
+ name_str = "accounts";
+
+ return std::tr1::shared_ptr<AccountsRepository>(new AccountsRepository(
+ make_named_values<AccountsRepositoryParams>(
+ value_for<n::environment>(env),
+ value_for<n::name>(RepositoryName(name_str))
+ )));
+}
+
+std::tr1::shared_ptr<Repository>
+AccountsRepository::repository_factory_installed_create(
+ Environment * const env,
+ const std::tr1::function<std::string (const std::string &)> & f)
+{
+ Context context("When making accounts repository from repo_file '" + f("repo_file") + "':");
+
+ std::string name_str(f("name"));
+ if (name_str.empty())
+ name_str = "installed-accounts";
+
+ std::string handler(f("handler"));
+ if (handler.empty())
+ throw AccountsRepositoryConfigurationError("Key 'handler' not specified or empty");
+
+ std::string root_str(f("root"));
+ if (root_str.empty())
+ root_str = "/";
+
+ if (root_str != "/")
+ throw AccountsRepositoryConfigurationError("Values other than '/' for 'root' not yet supported");
+
+ return std::tr1::shared_ptr<AccountsRepository>(new AccountsRepository(
+ make_named_values<InstalledAccountsRepositoryParams>(
+ value_for<n::environment>(env),
+ value_for<n::handler>(handler),
+ value_for<n::name>(RepositoryName(name_str)),
+ value_for<n::root>(FSEntry(root_str))
+ )));
+}
+
+RepositoryName
+AccountsRepository::repository_factory_name(
+ const Environment * const,
+ const std::tr1::function<std::string (const std::string &)> & f)
+{
+ if (f("name").empty())
+ return RepositoryName("accounts");
+ else
+ return RepositoryName(f("name"));
+}
+
+RepositoryName
+AccountsRepository::repository_factory_installed_name(
+ const Environment * const,
+ const std::tr1::function<std::string (const std::string &)> & f)
+{
+ if (f("name").empty())
+ return RepositoryName("installed-accounts");
+ else
+ return RepositoryName(f("name"));
+}
+
+std::tr1::shared_ptr<const RepositoryNameSet>
+AccountsRepository::repository_factory_dependencies(
+ const Environment * const,
+ const std::tr1::function<std::string (const std::string &)> &)
+{
+ return make_shared_ptr(new RepositoryNameSet);
+}
+
+std::tr1::shared_ptr<const RepositoryNameSet>
+AccountsRepository::repository_factory_installed_dependencies(
+ const Environment * const,
+ const std::tr1::function<std::string (const std::string &)> &)
+{
+ return make_shared_ptr(new RepositoryNameSet);
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::string> >
+AccountsRepository::format_key() const
+{
+ return _imp->format_key;
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<FSEntry> >
+AccountsRepository::location_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<FSEntry> >
+AccountsRepository::installed_root_key() const
+{
+ return _imp->installed_root_key;
+}
+
+void
+AccountsRepository::invalidate()
+{
+ if (_imp->params_if_not_installed)
+ _imp.reset(new Implementation<AccountsRepository>(this, *_imp->params_if_not_installed));
+ else
+ _imp.reset(new Implementation<AccountsRepository>(this, *_imp->params_if_installed));
+ _add_metadata_keys();
+}
+
+void
+AccountsRepository::invalidate_masks()
+{
+}
+
+void
+AccountsRepository::regenerate_cache() const
+{
+}
+
+bool
+AccountsRepository::has_category_named(const CategoryNamePart & c) const
+{
+ return _imp->store->has_category_named(c);
+}
+
+bool
+AccountsRepository::has_package_named(const QualifiedPackageName & q) const
+{
+ return _imp->store->has_package_named(q);
+}
+
+std::tr1::shared_ptr<const CategoryNamePartSet>
+AccountsRepository::category_names() const
+{
+ return _imp->store->category_names();
+}
+
+std::tr1::shared_ptr<const CategoryNamePartSet>
+AccountsRepository::unimportant_category_names() const
+{
+ return _imp->store->unimportant_category_names();
+}
+
+std::tr1::shared_ptr<const CategoryNamePartSet>
+AccountsRepository::category_names_containing_package(const PackageNamePart & p) const
+{
+ return Repository::category_names_containing_package(p);
+}
+
+std::tr1::shared_ptr<const QualifiedPackageNameSet>
+AccountsRepository::package_names(const CategoryNamePart & c) const
+{
+ return _imp->store->package_names(c);
+}
+
+std::tr1::shared_ptr<const PackageIDSequence>
+AccountsRepository::package_ids(const QualifiedPackageName & p) const
+{
+ return _imp->store->package_ids(p);
+}
+
+namespace
+{
+ struct SupportsActionQuery
+ {
+ bool visit(const SupportsActionTest<InstalledAction> &) const
+ {
+ return false;
+ }
+
+ bool visit(const SupportsActionTest<InstallAction> &) const
+ {
+ return true;
+ }
+
+ bool visit(const SupportsActionTest<FetchAction> &) const
+ {
+ return false;
+ }
+
+ bool visit(const SupportsActionTest<PretendFetchAction> &) const
+ {
+ return false;
+ }
+
+ bool visit(const SupportsActionTest<ConfigAction> &) const
+ {
+ return false;
+ }
+
+ bool visit(const SupportsActionTest<PretendAction> &) const
+ {
+ return false;
+ }
+
+ bool visit(const SupportsActionTest<InfoAction> &) const
+ {
+ return false;
+ }
+
+ bool visit(const SupportsActionTest<UninstallAction> &) const
+ {
+ return false;
+ }
+ };
+}
+
+bool
+AccountsRepository::some_ids_might_support_action(const SupportsActionTestBase & a) const
+{
+ SupportsActionQuery q;
+ return a.accept_returning<bool>(q);
+}
+
+bool
+AccountsRepository::is_suitable_destination_for(const PackageID & id) const
+{
+ std::string f(id.repository()->format_key() ? id.repository()->format_key()->value() : "");
+ return _imp->handler_if_installed && f == "accounts";
+}
+
+bool
+AccountsRepository::is_default_destination() const
+{
+ return _imp->handler_if_installed &&
+ _imp->params_if_installed->environment()->root() == installed_root_key()->value();
+}
+
+bool
+AccountsRepository::want_pre_post_phases() const
+{
+ return true;
+}
+
+void
+AccountsRepository::merge(const MergeParams & m)
+{
+ if (! _imp->handler_if_installed)
+ throw InstallActionError("Can't merge to here");
+
+ _imp->handler_if_installed->merge(m);
+}
+
+const std::tr1::shared_ptr<const SetSpecTree>
+AccountsRepository::package_set(const SetName & s) const
+{
+ using namespace std::tr1::placeholders;
+
+ Context context("When fetching package set '" + stringify(s) + "' from '" +
+ stringify(name()) + "':");
+
+ if ("everything" == s.data() && _imp->params_if_installed)
+ {
+ std::tr1::shared_ptr<SetSpecTree> result(new SetSpecTree(make_shared_ptr(new AllDepSpec)));
+ std::tr1::shared_ptr<GeneralSetDepTag> tag(new GeneralSetDepTag(s, stringify(name())));
+
+ std::tr1::shared_ptr<const CategoryNamePartSet> cats(category_names());
+ for (CategoryNamePartSet::ConstIterator c(cats->begin()), c_end(cats->end()) ;
+ c != c_end ; ++c)
+ {
+ std::tr1::shared_ptr<const QualifiedPackageNameSet> pkgs(package_names(*c));
+ for (QualifiedPackageNameSet::ConstIterator e(pkgs->begin()), e_end(pkgs->end()) ;
+ e != e_end ; ++e)
+ {
+ std::tr1::shared_ptr<PackageDepSpec> spec(new PackageDepSpec(make_package_dep_spec().package(QualifiedPackageName(*e))));
+ spec->set_tag(tag);
+ result->root()->append(spec);
+ }
+ }
+
+ return result;
+ }
+ else
+ return make_null_shared_ptr();
+}
+
+std::tr1::shared_ptr<const SetNameSet>
+AccountsRepository::sets_list() const
+{
+ Context context("While generating the list of sets:");
+
+ std::tr1::shared_ptr<SetNameSet> result(new SetNameSet);
+ if (_imp->params_if_installed)
+ result->insert(SetName("everything"));
+ return result;
+}
+
+
+template class PrivateImplementationPattern<AccountsRepository>;
+
diff --git a/paludis/repositories/accounts/accounts_repository.hh b/paludis/repositories/accounts/accounts_repository.hh
new file mode 100644
index 0000000..a25153c
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_repository.hh
@@ -0,0 +1,169 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_ACCOUNTS_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_ACCOUNTS_REPOSITORY_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <paludis/util/named_value.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/repository.hh>
+
+namespace paludis
+{
+ namespace n
+ {
+ struct environment;
+ struct handler;
+ struct installed;
+ struct name;
+ struct root;
+ }
+
+ namespace accounts_repository
+ {
+ struct AccountsRepositoryParams
+ {
+ NamedValue<n::environment, Environment *> environment;
+ NamedValue<n::name, RepositoryName> name;
+ };
+
+ struct InstalledAccountsRepositoryParams
+ {
+ NamedValue<n::environment, Environment *> environment;
+ NamedValue<n::handler, std::string> handler;
+ NamedValue<n::name, RepositoryName> name;
+ NamedValue<n::root, FSEntry> root;
+ };
+
+ class PALUDIS_VISIBLE AccountsRepository :
+ private PrivateImplementationPattern<AccountsRepository>,
+ public Repository,
+ public RepositoryDestinationInterface,
+ public RepositorySetsInterface,
+ public std::tr1::enable_shared_from_this<AccountsRepository>
+ {
+ private:
+ PrivateImplementationPattern<AccountsRepository>::ImpPtr & _imp;
+
+ void _add_metadata_keys();
+
+ protected:
+ virtual void need_keys_added() const;
+
+ public:
+ AccountsRepository(const AccountsRepositoryParams &);
+ AccountsRepository(const InstalledAccountsRepositoryParams &);
+
+ ~AccountsRepository();
+
+ ///\name RepositoryFactory functions
+ ///\{
+
+ static RepositoryName repository_factory_name(
+ const Environment * const env,
+ const std::tr1::function<std::string (const std::string &)> &);
+
+ static std::tr1::shared_ptr<Repository> repository_factory_create(
+ Environment * const env,
+ const std::tr1::function<std::string (const std::string &)> &);
+
+ static std::tr1::shared_ptr<const RepositoryNameSet> repository_factory_dependencies(
+ const Environment * const env,
+ const std::tr1::function<std::string (const std::string &)> &);
+
+ ///\}
+
+ ///\name RepositoryFactory functions for Installed
+ ///\{
+
+ static RepositoryName repository_factory_installed_name(
+ const Environment * const env,
+ const std::tr1::function<std::string (const std::string &)> &);
+
+ static std::tr1::shared_ptr<Repository> repository_factory_installed_create(
+ Environment * const env,
+ const std::tr1::function<std::string (const std::string &)> &);
+
+ static std::tr1::shared_ptr<const RepositoryNameSet> repository_factory_installed_dependencies(
+ const Environment * const env,
+ const std::tr1::function<std::string (const std::string &)> &);
+
+ ///\}
+
+ ///\name Specific metadata keys
+ ///\{
+
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<std::string> > format_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<FSEntry> > location_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<FSEntry> > installed_root_key() const;
+
+ ///\}
+
+ ///\name Repository content queries
+ ///\{
+
+ virtual bool has_category_named(const CategoryNamePart & c) const;
+ virtual bool has_package_named(const QualifiedPackageName & q) const;
+ virtual std::tr1::shared_ptr<const CategoryNamePartSet> category_names() const;
+ virtual std::tr1::shared_ptr<const CategoryNamePartSet> unimportant_category_names() const;
+ virtual std::tr1::shared_ptr<const CategoryNamePartSet> category_names_containing_package(
+ const PackageNamePart & p) const;
+ virtual std::tr1::shared_ptr<const QualifiedPackageNameSet> package_names(
+ const CategoryNamePart & c) const;
+ virtual std::tr1::shared_ptr<const PackageIDSequence> package_ids(const QualifiedPackageName & p) const;
+ virtual bool some_ids_might_support_action(const SupportsActionTestBase &) const;
+
+ ///\}
+
+ ///\name Repository behaviour methods
+ ///\{
+
+ virtual void invalidate();
+ virtual void invalidate_masks();
+ virtual void regenerate_cache() const;
+
+ ///\}
+
+ ///\name Destination functions
+ ///\{
+
+ virtual bool is_suitable_destination_for(const PackageID &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual bool is_default_destination() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual bool want_pre_post_phases() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual void merge(const MergeParams &);
+
+ ///\}
+
+ ///\name Set queries
+ ///\{
+
+ virtual const std::tr1::shared_ptr<const SetSpecTree> package_set(const SetName & s) const;
+ virtual std::tr1::shared_ptr<const SetNameSet> sets_list() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ ///\}
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/accounts/accounts_repository_TEST.cc b/paludis/repositories/accounts/accounts_repository_TEST.cc
new file mode 100644
index 0000000..b8bf04e
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_repository_TEST.cc
@@ -0,0 +1,60 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repositories/accounts/accounts_repository.hh>
+#include <paludis/environments/test/test_environment.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/generator.hh>
+#include <paludis/selection.hh>
+#include <paludis/filtered_generator.hh>
+#include <paludis/filter.hh>
+#include <paludis/package_id.hh>
+#include <paludis/package_database.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+#include <tr1/memory>
+
+using namespace paludis;
+using namespace paludis::accounts_repository;
+using namespace test;
+
+namespace test_cases
+{
+ struct AccountsRepositoryCreationTest : TestCase
+ {
+ AccountsRepositoryCreationTest() : TestCase("creation") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ std::tr1::shared_ptr<AccountsRepository> repo(new AccountsRepository(
+ make_named_values<AccountsRepositoryParams>(
+ value_for<n::environment>(&env),
+ value_for<n::name>(RepositoryName("accounts"))
+ )));
+ env.package_database()->add_repository(1, repo);
+ TEST_CHECK_STRINGIFY_EQUAL(repo->name(), "accounts");
+ }
+ } test_creation;
+}
+
diff --git a/paludis/repositories/accounts/accounts_repository_store.cc b/paludis/repositories/accounts/accounts_repository_store.cc
new file mode 100644
index 0000000..fb98ac5
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_repository_store.cc
@@ -0,0 +1,278 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repositories/accounts/accounts_repository_store.hh>
+#include <paludis/repositories/accounts/accounts_repository.hh>
+#include <paludis/repositories/accounts/accounts_id.hh>
+#include <paludis/repositories/accounts/installed_accounts_id.hh>
+#include <paludis/repositories/accounts/accounts_exceptions.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/hashes.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/simple_visitor_cast.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/options.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/name.hh>
+#include <paludis/package_database.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/environment.hh>
+#include <paludis/literal_metadata_key.hh>
+#include <tr1/functional>
+#include <tr1/unordered_map>
+#include <algorithm>
+#include <set>
+#include <sys/types.h>
+#include <pwd.h>
+
+using namespace paludis;
+using namespace paludis::accounts_repository;
+
+typedef std::tr1::unordered_map<CategoryNamePart,
+ std::tr1::shared_ptr<QualifiedPackageNameSet>,
+ Hash<CategoryNamePart> > PackageNames;
+
+typedef std::tr1::unordered_map<QualifiedPackageName,
+ std::tr1::shared_ptr<PackageIDSequence>,
+ Hash<QualifiedPackageName> > IDs;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<AccountsRepositoryStore>
+ {
+ const Environment * const env;
+ const AccountsRepository * const repo;
+ const bool installed;
+
+ std::tr1::shared_ptr<CategoryNamePartSet> categories;
+ mutable PackageNames package_names;
+ mutable IDs ids;
+
+ Implementation(const Environment * const e, const AccountsRepository * const r, const bool i) :
+ env(e),
+ repo(r),
+ installed(i),
+ categories(new CategoryNamePartSet)
+ {
+ categories->insert(CategoryNamePart("user"));
+ categories->insert(CategoryNamePart("group"));
+ }
+ };
+}
+
+AccountsRepositoryStore::AccountsRepositoryStore(
+ const Environment * const env,
+ const AccountsRepository * const repo,
+ const bool installed) :
+ PrivateImplementationPattern<AccountsRepositoryStore>(new Implementation<AccountsRepositoryStore>(
+ env, repo, installed))
+{
+ _load(repo->shared_from_this());
+}
+
+AccountsRepositoryStore::~AccountsRepositoryStore()
+{
+}
+
+void
+AccountsRepositoryStore::_load(const std::tr1::shared_ptr<const Repository> & repo)
+{
+ Context context("When loading data for AccountsRepository:");
+
+ for (PackageDatabase::RepositoryConstIterator r(_imp->env->package_database()->begin_repositories()),
+ r_end(_imp->env->package_database()->end_repositories()) ;
+ r != r_end ; ++r)
+ {
+ Context r_context("When loading data for repository '" + stringify((*r)->name()) + ":");
+
+ Repository::MetadataConstIterator k_iter((*r)->find_metadata("accounts_repository_data_location"));
+ if (k_iter == (*r)->end_metadata())
+ {
+ Log::get_instance()->message("accounts.no_key_from_repository", ll_debug, lc_context) <<
+ "Repository " << (*r)->name() << " defines no accounts_repository_data_location key";
+ continue;
+ }
+
+ const MetadataValueKey<FSEntry> * k(simple_visitor_cast<const MetadataValueKey<FSEntry> >(**k_iter));
+ if (! k)
+ {
+ Log::get_instance()->message("accounts.bad_key_from_repository", ll_warning, lc_context) <<
+ "Repository " << (*r)->name() << " defines an accounts_repository_data_location key, but it is not an FSEntry key";
+ continue;
+ }
+
+ FSEntry dir(k->value());
+ if (! dir.is_directory_or_symlink_to_directory())
+ {
+ Log::get_instance()->message("accounts.empty_key_from_repository", ll_warning, lc_context) <<
+ "Repository " << (*r)->name() << " has accounts_repository_data_location " << dir << ", but this is not a directory";
+ continue;
+ }
+
+ std::tr1::shared_ptr<Set<std::string> > r_set(new Set<std::string>);
+ r_set->insert(stringify((*r)->name()));
+ std::tr1::shared_ptr<LiteralMetadataStringSetKey> r_key(new LiteralMetadataStringSetKey("defined_by", "Defined by repository", mkt_internal, r_set));
+ _load_one(repo, r_key, dir);
+ }
+}
+
+void
+AccountsRepositoryStore::_load_one(
+ const std::tr1::shared_ptr<const Repository> & repo,
+ const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > > & from_repo,
+ const FSEntry & dir)
+{
+ Context context("When loading accounts from directory '" + stringify(dir) + "':");
+
+ if ((dir / "users").is_directory_or_symlink_to_directory())
+ _load_one_users(repo, from_repo, dir / "users");
+ else
+ Log::get_instance()->message("accounts.no_users", ll_debug, lc_context) <<
+ "Repository " << repo->name() << " has accounts_repository_data_location " << dir << ", but no users subdirectory";
+
+ if ((dir / "groups").is_directory_or_symlink_to_directory())
+ _load_one_groups(repo, dir / "groups");
+ else
+ Log::get_instance()->message("accounts.no_groups", ll_debug, lc_context) <<
+ "Repository " << repo->name() << " has accounts_repository_data_location " << dir << ", but no groups subdirectory";
+
+}
+
+void
+AccountsRepositoryStore::_load_one_users(
+ const std::tr1::shared_ptr<const Repository> & repo,
+ const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > > & from_repo,
+ const FSEntry & dir)
+{
+ for (DirIterator d(dir, DirIteratorOptions()), d_end ; d != d_end ; ++d)
+ if (is_file_with_extension(*d, ".conf", IsFileWithOptions()))
+ _load_one_user(repo, from_repo, *d);
+ else
+ Log::get_instance()->message("accounts.unknown_file", ll_debug, lc_context) <<
+ "Don't know what to do with '" << *d << "'";
+}
+
+void
+AccountsRepositoryStore::_load_one_groups(const std::tr1::shared_ptr<const Repository> & repo, const FSEntry & dir)
+{
+ for (DirIterator d(dir, DirIteratorOptions()), d_end ; d != d_end ; ++d)
+ if (is_file_with_extension(*d, ".conf", IsFileWithOptions()))
+ _load_one_group(repo, *d);
+ else
+ Log::get_instance()->message("accounts.unknown_file", ll_debug, lc_context) <<
+ "Don't know what to do with '" << *d << "'";
+}
+
+void
+AccountsRepositoryStore::_load_one_user(
+ const std::tr1::shared_ptr<const Repository> & repo,
+ const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > > & from_repo,
+ const FSEntry & filename)
+{
+ CategoryNamePart cat("user");
+ PackageNamePart pkg(strip_trailing_string(filename.basename(), ".conf"));
+ QualifiedPackageName qpn(cat + pkg);
+ std::string username(stringify(pkg));
+
+ if (_imp->installed)
+ {
+ if (! getpwnam(username.c_str()))
+ return;
+ }
+ else
+ {
+ if (getpwnam(username.c_str()))
+ return;
+ }
+
+ PackageNames::iterator p(_imp->package_names.find(cat));
+ if (p == _imp->package_names.end())
+ p = _imp->package_names.insert(std::make_pair(cat, make_shared_ptr(new QualifiedPackageNameSet))).first;
+
+ p->second->insert(qpn);
+
+ IDs::iterator q(_imp->ids.find(qpn));
+ if (q == _imp->ids.end())
+ q = _imp->ids.insert(std::make_pair(qpn, make_shared_ptr(new PackageIDSequence))).first;
+ else
+ q->second.reset(new PackageIDSequence);
+
+ if (_imp->installed)
+ q->second->push_back(make_shared_ptr(new InstalledAccountsUserID(_imp->env, qpn, repo)));
+ else
+ q->second->push_back(make_shared_ptr(new AccountsUserID(_imp->env, qpn, repo, from_repo, filename)));
+}
+
+void
+AccountsRepositoryStore::_load_one_group(const std::tr1::shared_ptr<const Repository> &, const FSEntry &)
+{
+}
+
+bool
+AccountsRepositoryStore::has_category_named(const CategoryNamePart & c) const
+{
+ return _imp->categories->end() != _imp->categories->find(c);
+}
+
+bool
+AccountsRepositoryStore::has_package_named(const QualifiedPackageName & q) const
+{
+ return _imp->ids.end() != _imp->ids.find(q);
+}
+
+std::tr1::shared_ptr<const CategoryNamePartSet>
+AccountsRepositoryStore::category_names() const
+{
+ return _imp->categories;
+}
+
+std::tr1::shared_ptr<const CategoryNamePartSet>
+AccountsRepositoryStore::unimportant_category_names() const
+{
+ return _imp->categories;
+}
+
+std::tr1::shared_ptr<const QualifiedPackageNameSet>
+AccountsRepositoryStore::package_names(const CategoryNamePart & c) const
+{
+ PackageNames::iterator p(_imp->package_names.find(c));
+ if (_imp->package_names.end() == p)
+ return make_shared_ptr(new QualifiedPackageNameSet);
+ else
+ return p->second;
+}
+
+std::tr1::shared_ptr<const PackageIDSequence>
+AccountsRepositoryStore::package_ids(const QualifiedPackageName & p) const
+{
+ IDs::iterator i(_imp->ids.find(p));
+ if (_imp->ids.end() == i)
+ return make_shared_ptr(new PackageIDSequence);
+ else
+ return i->second;
+}
+
+template class PrivateImplementationPattern<accounts_repository::AccountsRepositoryStore>;
+
diff --git a/paludis/repositories/accounts/accounts_repository_store.hh b/paludis/repositories/accounts/accounts_repository_store.hh
new file mode 100644
index 0000000..d7f222b
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_repository_store.hh
@@ -0,0 +1,96 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_ACCOUNTS_REPOSITORY_STORE_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_ACCOUNTS_REPOSITORY_STORE_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/fs_entry-fwd.hh>
+#include <paludis/name-fwd.hh>
+#include <paludis/package_id-fwd.hh>
+#include <paludis/environment-fwd.hh>
+#include <paludis/repository-fwd.hh>
+#include <paludis/metadata_key-fwd.hh>
+#include <tr1/memory>
+
+namespace paludis
+{
+ namespace accounts_repository
+ {
+ struct AccountsRepository;
+
+ class PALUDIS_VISIBLE AccountsRepositoryStore :
+ private PrivateImplementationPattern<AccountsRepositoryStore>
+ {
+ private:
+ void _load(const std::tr1::shared_ptr<const Repository> & repo);
+
+ void _load_one(
+ const std::tr1::shared_ptr<const Repository> & repo,
+ const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > > & from_repo,
+ const FSEntry & dir);
+
+ void _load_one_users(
+ const std::tr1::shared_ptr<const Repository> & repo,
+ const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > > & from_repo,
+ const FSEntry & dir);
+
+ void _load_one_groups(const std::tr1::shared_ptr<const Repository> & repo, const FSEntry & dir);
+
+ void _load_one_user(
+ const std::tr1::shared_ptr<const Repository> & repo,
+ const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > > & from_repo,
+ const FSEntry & file);
+
+ void _load_one_group(const std::tr1::shared_ptr<const Repository> & repo, const FSEntry & file);
+
+ public:
+ AccountsRepositoryStore(
+ const Environment * const,
+ const AccountsRepository * const,
+ const bool installed);
+
+ ~AccountsRepositoryStore();
+
+ bool has_category_named(const CategoryNamePart &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ bool has_package_named(const QualifiedPackageName & q) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ std::tr1::shared_ptr<const CategoryNamePartSet> category_names() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ std::tr1::shared_ptr<const CategoryNamePartSet> unimportant_category_names() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ std::tr1::shared_ptr<const QualifiedPackageNameSet> package_names(
+ const CategoryNamePart & c) const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ std::tr1::shared_ptr<const PackageIDSequence> package_ids(
+ const QualifiedPackageName & p) const PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+
+#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE
+ extern template class PrivateImplementationPattern<accounts_repository::AccountsRepositoryStore>;
+#endif
+}
+
+#endif
diff --git a/paludis/repositories/accounts/dummy_accounts_handler.cc b/paludis/repositories/accounts/dummy_accounts_handler.cc
new file mode 100644
index 0000000..d811753
--- /dev/null
+++ b/paludis/repositories/accounts/dummy_accounts_handler.cc
@@ -0,0 +1,34 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repositories/accounts/dummy_accounts_handler.hh>
+#include <paludis/package_id.hh>
+#include <paludis/repository.hh>
+#include <iostream>
+
+using namespace paludis;
+using namespace paludis::accounts_repository;
+
+void
+DummyAccountsHandler::merge(const MergeParams & m)
+{
+ std::cout << ">>> Installing " << *m.package_id() << " using dummy handler" << std::endl;
+ std::cout << ">>> Finished installing " << *m.package_id() << std::endl;
+}
+
diff --git a/paludis/repositories/accounts/dummy_accounts_handler.hh b/paludis/repositories/accounts/dummy_accounts_handler.hh
new file mode 100644
index 0000000..2d450c7
--- /dev/null
+++ b/paludis/repositories/accounts/dummy_accounts_handler.hh
@@ -0,0 +1,38 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_DUMMY_ACCOUNTS_HANDLER_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_DUMMY_ACCOUNTS_HANDLER_HH 1
+
+#include <paludis/repositories/accounts/accounts_handler.hh>
+
+namespace paludis
+{
+ namespace accounts_repository
+ {
+ class DummyAccountsHandler :
+ public AccountsHandler
+ {
+ public:
+ virtual void merge(const MergeParams &);
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/accounts/installed_accounts_id.cc b/paludis/repositories/accounts/installed_accounts_id.cc
new file mode 100644
index 0000000..1750255
--- /dev/null
+++ b/paludis/repositories/accounts/installed_accounts_id.cc
@@ -0,0 +1,284 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repositories/accounts/installed_accounts_id.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/config_file.hh>
+#include <paludis/util/options.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/hashes.hh>
+#include <paludis/util/simple_visitor_cast.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/make_named_values.hh>
+#include <paludis/name.hh>
+#include <paludis/version_spec.hh>
+#include <paludis/literal_metadata_key.hh>
+#include <paludis/repository.hh>
+#include <paludis/action.hh>
+
+using namespace paludis;
+using namespace paludis::accounts_repository;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<InstalledAccountsUserID>
+ {
+ const Environment * const env;
+
+ const QualifiedPackageName name;
+ const VersionSpec version;
+ const SlotName slot;
+ const std::tr1::shared_ptr<const Repository> repository;
+
+ const std::tr1::shared_ptr<const LiteralMetadataValueKey<bool> > transient_key;
+
+ Implementation(const Environment * const e,
+ const QualifiedPackageName & q, const std::tr1::shared_ptr<const Repository> & r) :
+ env(e),
+ name(q),
+ version("0"),
+ slot("0"),
+ repository(r),
+ transient_key(new LiteralMetadataValueKey<bool>("transient", "Transient", mkt_internal, true))
+ {
+ }
+ };
+}
+
+InstalledAccountsUserID::InstalledAccountsUserID(const Environment * const e,
+ const QualifiedPackageName & q, const std::tr1::shared_ptr<const Repository> & r) :
+ PrivateImplementationPattern<InstalledAccountsUserID>(new Implementation<InstalledAccountsUserID>(e, q, r)),
+ _imp(PrivateImplementationPattern<InstalledAccountsUserID>::_imp)
+{
+ add_metadata_key(_imp->transient_key);
+}
+
+InstalledAccountsUserID::~InstalledAccountsUserID()
+{
+}
+
+void
+InstalledAccountsUserID::need_keys_added() const
+{
+}
+
+void
+InstalledAccountsUserID::clear_metadata_keys() const
+{
+}
+
+void
+InstalledAccountsUserID::need_masks_added() const
+{
+}
+
+const QualifiedPackageName
+InstalledAccountsUserID::name() const
+{
+ return _imp->name;
+}
+
+const VersionSpec
+InstalledAccountsUserID::version() const
+{
+ return _imp->version;
+}
+
+const SlotName
+InstalledAccountsUserID::slot() const
+{
+ return _imp->slot;
+}
+
+const std::tr1::shared_ptr<const Repository>
+InstalledAccountsUserID::repository() const
+{
+ return _imp->repository;
+}
+
+const std::string
+InstalledAccountsUserID::canonical_form(const PackageIDCanonicalForm f) const
+{
+ switch (f)
+ {
+ case idcf_full:
+ return stringify(name()) + "-" + stringify(version()) + ":" + stringify(slot()) + "::" + stringify(repository()->name());
+
+ case idcf_no_version:
+ return stringify(name()) + ":" + stringify(slot()) + "::" + stringify(repository()->name());
+
+ case idcf_version:
+ return stringify(version());
+
+ case last_idcf:
+ break;
+ }
+
+ throw InternalError(PALUDIS_HERE, "Bad PackageIDCanonicalForm");
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const PackageID> > >
+InstalledAccountsUserID::virtual_for_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataCollectionKey<KeywordNameSet> >
+InstalledAccountsUserID::keywords_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<ProvideSpecTree> >
+InstalledAccountsUserID::provide_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataCollectionKey<PackageIDSequence> >
+InstalledAccountsUserID::contains_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const PackageID> > >
+InstalledAccountsUserID::contained_in_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+InstalledAccountsUserID::build_dependencies_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+InstalledAccountsUserID::run_dependencies_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+InstalledAccountsUserID::post_dependencies_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+InstalledAccountsUserID::suggested_dependencies_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<FetchableURISpecTree> >
+InstalledAccountsUserID::fetches_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<SimpleURISpecTree> >
+InstalledAccountsUserID::homepage_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::string> >
+InstalledAccountsUserID::short_description_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::string> >
+InstalledAccountsUserID::long_description_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const Contents> > >
+InstalledAccountsUserID::contents_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataTimeKey>
+InstalledAccountsUserID::installed_time_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > >
+InstalledAccountsUserID::from_repositories_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<FSEntry> >
+InstalledAccountsUserID::fs_location_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<bool> >
+InstalledAccountsUserID::transient_key() const
+{
+ return _imp->transient_key;
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const Choices> > >
+InstalledAccountsUserID::choices_key() const
+{
+ return make_null_shared_ptr();
+}
+
+std::tr1::shared_ptr<const Set<std::string> >
+InstalledAccountsUserID::breaks_portage() const
+{
+ return make_shared_ptr(new Set<std::string>);
+}
+
+bool
+InstalledAccountsUserID::arbitrary_less_than_comparison(const PackageID & other) const
+{
+ if (slot() < other.slot())
+ return true;
+
+ return false;
+}
+
+std::size_t
+InstalledAccountsUserID::extra_hash_value() const
+{
+ return Hash<SlotName>()(slot());
+}
+
+bool
+InstalledAccountsUserID::supports_action(const SupportsActionTestBase & test) const
+{
+ return simple_visitor_cast<const SupportsActionTest<InstalledAction> >(test);
+}
+
+void
+InstalledAccountsUserID::perform_action(Action & action) const
+{
+ throw UnsupportedActionError(*this, action);
+}
+
diff --git a/paludis/repositories/accounts/installed_accounts_id.hh b/paludis/repositories/accounts/installed_accounts_id.hh
new file mode 100644
index 0000000..9625d94
--- /dev/null
+++ b/paludis/repositories/accounts/installed_accounts_id.hh
@@ -0,0 +1,103 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_INSTALLED_ACCOUNTS_ID_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_INSTALLED_ACCOUNTS_ID_HH 1
+
+#include <paludis/package_id.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace paludis
+{
+ namespace accounts_repository
+ {
+ class AccountsRepository;
+
+ class InstalledAccountsUserID :
+ public PackageID,
+ private PrivateImplementationPattern<InstalledAccountsUserID>,
+ public std::tr1::enable_shared_from_this<InstalledAccountsUserID>
+ {
+ private:
+ PrivateImplementationPattern<InstalledAccountsUserID>::ImpPtr & _imp;
+
+ void _add_metadata_keys() const;
+
+ protected:
+ virtual void clear_metadata_keys() const;
+ virtual void need_keys_added() const;
+ virtual void need_masks_added() const;
+
+ public:
+ InstalledAccountsUserID(const Environment * const,
+ const QualifiedPackageName &, const std::tr1::shared_ptr<const Repository> &);
+ ~InstalledAccountsUserID();
+
+ virtual const std::string canonical_form(const PackageIDCanonicalForm) const;
+
+ virtual const QualifiedPackageName name() const;
+ virtual const VersionSpec version() const;
+ virtual const SlotName slot() const;
+ virtual const std::tr1::shared_ptr<const Repository> repository() const;
+
+ ///\name Specific metadata keys
+ ///\{
+
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const PackageID> > > virtual_for_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataCollectionKey<KeywordNameSet> > keywords_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataSpecTreeKey<ProvideSpecTree> > provide_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataCollectionKey<PackageIDSequence> > contains_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const PackageID> > > contained_in_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > build_dependencies_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > run_dependencies_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > post_dependencies_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > suggested_dependencies_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataSpecTreeKey<FetchableURISpecTree> > fetches_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataSpecTreeKey<SimpleURISpecTree> > homepage_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<std::string> > short_description_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<std::string> > long_description_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const Contents> > > contents_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataTimeKey> installed_time_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > > from_repositories_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<FSEntry> > fs_location_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<bool> > transient_key() const;
+ virtual const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const Choices> > > choices_key() const;
+
+ ///\}
+
+ ///\name Actions
+ ///\{
+
+ virtual bool supports_action(const SupportsActionTestBase &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual void perform_action(Action &) const;
+
+ ///\}
+
+ virtual std::tr1::shared_ptr<const Set<std::string> > breaks_portage() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool arbitrary_less_than_comparison(const PackageID &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::size_t extra_hash_value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/accounts/passwd_accounts_handler.cc b/paludis/repositories/accounts/passwd_accounts_handler.cc
new file mode 100644
index 0000000..f3d4d09
--- /dev/null
+++ b/paludis/repositories/accounts/passwd_accounts_handler.cc
@@ -0,0 +1,200 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repositories/accounts/passwd_accounts_handler.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/simple_visitor_cast.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/destringify.hh>
+#include <paludis/util/join.hh>
+#include <paludis/action.hh>
+#include <paludis/repository.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/package_id.hh>
+#include <iostream>
+#include <sys/types.h>
+#include <pwd.h>
+
+using namespace paludis;
+using namespace paludis::accounts_repository;
+
+void
+PasswdAccountsHandler::merge(const MergeParams & params)
+{
+ Context context("When installing '" + stringify(*params.package_id()) + "':");
+
+ std::cout << ">>> Installing " << *params.package_id() << " using passwd handler" << std::endl;
+
+ std::string username;
+ do
+ {
+ PackageID::MetadataConstIterator m(params.package_id()->find_metadata("username"));
+ if (params.package_id()->end_metadata() == m)
+ throw InstallActionError("Key 'username' for '" + stringify(*params.package_id()) + "' does not exist");
+
+ const MetadataValueKey<std::string> * k(simple_visitor_cast<const MetadataValueKey<std::string> >(**m));
+ if (! k)
+ throw InstallActionError("Key 'username' for '" + stringify(*params.package_id()) + "' is not a string key");
+
+ username = k->value();
+
+ if (0 != getpwnam(username.c_str()))
+ throw InstallActionError("User '" + username + "' already exists");
+ } while (false);
+
+ std::string gecos;
+ do
+ {
+ PackageID::MetadataConstIterator m(params.package_id()->find_metadata("gecos"));
+ if (params.package_id()->end_metadata() == m)
+ break;
+
+ const MetadataValueKey<std::string> * k(simple_visitor_cast<const MetadataValueKey<std::string> >(**m));
+ if (! k)
+ throw InstallActionError("Key 'gecos' for '" + stringify(*params.package_id()) + "' is not a string key");
+
+ gecos = k->value();
+
+ if (std::string::npos != gecos.find('\''))
+ throw InstallActionError("Value for key 'gecos' for '" + stringify(*params.package_id()) + "' must not contain a quote");
+
+ if (! gecos.empty())
+ gecos = " -c '" + gecos + "'";
+ } while (false);
+
+ std::string preferred_uid;
+ do
+ {
+ PackageID::MetadataConstIterator m(params.package_id()->find_metadata("preferred_uid"));
+ if (params.package_id()->end_metadata() == m)
+ break;
+
+ const MetadataValueKey<std::string> * k(simple_visitor_cast<const MetadataValueKey<std::string> >(**m));
+ if (! k)
+ throw InstallActionError("Key 'preferred_uid' for '" + stringify(*params.package_id()) + "' is not a string key");
+
+ preferred_uid = k->value();
+
+ if (std::string::npos != preferred_uid.find_first_not_of("0123456789"))
+ throw InstallActionError("Value for key 'preferred_uid' for '" + stringify(*params.package_id()) + "' must be a number");
+
+ uid_t uid(destringify<uid_t>(preferred_uid));
+ if (getpwuid(uid))
+ {
+ std::cout << ">>> Preferred UID " << uid << " already in use, not specifying an ID" << std::endl;
+ preferred_uid = "";
+ }
+
+ if (! preferred_uid.empty())
+ preferred_uid = " -u '" + preferred_uid + "'";
+ } while (false);
+
+ std::string primary_group;
+ do
+ {
+ PackageID::MetadataConstIterator m(params.package_id()->find_metadata("primary_group"));
+ if (params.package_id()->end_metadata() == m)
+ break;
+
+ const MetadataValueKey<std::string> * k(simple_visitor_cast<const MetadataValueKey<std::string> >(**m));
+ if (! k)
+ throw InstallActionError("Key 'primary_group' for '" + stringify(*params.package_id()) + "' is not a string key");
+
+ primary_group = k->value();
+
+ if (std::string::npos != primary_group.find('\''))
+ throw InstallActionError("Value for key 'primary_group' for '" + stringify(*params.package_id()) + "' must not contain a quote");
+
+ if (! primary_group.empty())
+ primary_group = " -g '" + primary_group + "'";
+ } while (false);
+
+ std::string extra_groups;
+ do
+ {
+ PackageID::MetadataConstIterator m(params.package_id()->find_metadata("extra_groups"));
+ if (params.package_id()->end_metadata() == m)
+ break;
+
+ const MetadataCollectionKey<Set<std::string> > * k(simple_visitor_cast<const MetadataCollectionKey<Set<std::string> > >(**m));
+ if (! k)
+ throw InstallActionError("Key 'extra_groups' for '" + stringify(*params.package_id()) + "' is not a string set key");
+
+ extra_groups = join(k->value()->begin(), k->value()->end(), ",");
+
+ if (std::string::npos != extra_groups.find('\''))
+ throw InstallActionError("Value for key 'extra_groups' for '" + stringify(*params.package_id()) + "' must not contain a quote");
+
+ if (! extra_groups.empty())
+ extra_groups = " -G '" + extra_groups + "'";
+ } while (false);
+
+ std::string shell;
+ do
+ {
+ PackageID::MetadataConstIterator m(params.package_id()->find_metadata("shell"));
+ if (params.package_id()->end_metadata() == m)
+ break;
+
+ const MetadataValueKey<std::string> * k(simple_visitor_cast<const MetadataValueKey<std::string> >(**m));
+ if (! k)
+ throw InstallActionError("Key 'shell' for '" + stringify(*params.package_id()) + "' is not a string key");
+
+ shell = k->value();
+
+ if (std::string::npos != shell.find('\''))
+ throw InstallActionError("Value for key 'shell' for '" + stringify(*params.package_id()) + "' must not contain a quote");
+
+ if (! shell.empty())
+ shell = " -s '" + shell + "'";
+ } while (false);
+
+ std::string home;
+ do
+ {
+ PackageID::MetadataConstIterator m(params.package_id()->find_metadata("home"));
+ if (params.package_id()->end_metadata() == m)
+ break;
+
+ const MetadataValueKey<std::string> * k(simple_visitor_cast<const MetadataValueKey<std::string> >(**m));
+ if (! k)
+ throw InstallActionError("Key 'home' for '" + stringify(*params.package_id()) + "' is not a string key");
+
+ home = k->value();
+
+ if (std::string::npos != home.find('\''))
+ throw InstallActionError("Value for key 'home' for '" + stringify(*params.package_id()) + "' must not contain a quote");
+
+ if (! home.empty())
+ home = " -d '" + home + "'";
+ } while (false);
+
+ Command cmd("useradd " + username + gecos + primary_group + extra_groups + shell + home);
+ cmd.with_echo_to_stderr();
+ int exit_status(run_command(cmd));
+
+ if (0 != exit_status)
+ throw InstallActionError("Install of '" + stringify(*params.package_id()) + "' failed because useradd returned "
+ + stringify(exit_status));
+
+ std::cout << ">>> Finished installing " << *params.package_id() << std::endl;
+}
+
diff --git a/paludis/repositories/accounts/passwd_accounts_handler.hh b/paludis/repositories/accounts/passwd_accounts_handler.hh
new file mode 100644
index 0000000..4ce9a2b
--- /dev/null
+++ b/paludis/repositories/accounts/passwd_accounts_handler.hh
@@ -0,0 +1,38 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_PASSWD_ACCOUNTS_HANDLER_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_PASSWD_ACCOUNTS_HANDLER_HH 1
+
+#include <paludis/repositories/accounts/accounts_handler.hh>
+
+namespace paludis
+{
+ namespace accounts_repository
+ {
+ class PasswdAccountsHandler :
+ public AccountsHandler
+ {
+ public:
+ virtual void merge(const MergeParams &);
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/accounts/registration.cc b/paludis/repositories/accounts/registration.cc
new file mode 100644
index 0000000..3131145
--- /dev/null
+++ b/paludis/repositories/accounts/registration.cc
@@ -0,0 +1,64 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repository_factory.hh>
+#include <paludis/repositories/accounts/accounts_repository.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/destringify.hh>
+
+using namespace paludis;
+using namespace paludis::accounts_repository;
+
+namespace
+{
+ int generic_importance(const Environment * const, const std::tr1::function<std::string (const std::string &)> & f)
+ {
+ if (! f("importance").empty())
+ return destringify<int>(f("importance"));
+ else
+ return 1;
+ }
+}
+
+extern "C" void paludis_initialise_repository_so(RepositoryFactory * const factory) PALUDIS_VISIBLE;
+
+void paludis_initialise_repository_so(RepositoryFactory * const factory)
+{
+ std::tr1::shared_ptr<Set<std::string> > accounts_formats(new Set<std::string>);
+ accounts_formats->insert("accounts");
+
+ factory->add_repository_format(accounts_formats,
+ &AccountsRepository::repository_factory_name,
+ &generic_importance,
+ &AccountsRepository::repository_factory_create,
+ &AccountsRepository::repository_factory_dependencies
+ );
+
+ std::tr1::shared_ptr<Set<std::string> > installed_accounts_formats(new Set<std::string>);
+ installed_accounts_formats->insert("installed_accounts");
+ installed_accounts_formats->insert("installed-accounts");
+
+ factory->add_repository_format(installed_accounts_formats,
+ &AccountsRepository::repository_factory_installed_name,
+ &generic_importance,
+ &AccountsRepository::repository_factory_installed_create,
+ &AccountsRepository::repository_factory_installed_dependencies
+ );
+}
+
diff --git a/paludis/repositories/e/e_repository.cc b/paludis/repositories/e/e_repository.cc
index 6c4596d..226d5a7 100644
--- a/paludis/repositories/e/e_repository.cc
+++ b/paludis/repositories/e/e_repository.cc
@@ -239,6 +239,7 @@ namespace paludis
std::tr1::shared_ptr<const MetadataValueKey<std::string> > binary_destination_key;
std::tr1::shared_ptr<const MetadataValueKey<std::string> > binary_src_uri_prefix_key;
std::tr1::shared_ptr<const MetadataValueKey<std::string> > binary_keywords;
+ std::tr1::shared_ptr<const MetadataValueKey<FSEntry> > accounts_repository_data_location_key;
};
Implementation<ERepository>::Implementation(ERepository * const r,
@@ -321,7 +322,8 @@ namespace paludis
binary_src_uri_prefix_key(new LiteralMetadataValueKey<std::string> (
"binary_uri_prefix", "binary_uri_prefix", mkt_normal, params.binary_uri_prefix())),
binary_keywords(new LiteralMetadataValueKey<std::string> (
- "binary_keywords", "binary_keywords", mkt_normal, params.binary_keywords()))
+ "binary_keywords", "binary_keywords", mkt_normal, params.binary_keywords())),
+ accounts_repository_data_location_key(layout->accounts_repository_data_location_key())
{
}
@@ -530,6 +532,8 @@ ERepository::_add_metadata_keys() const
add_metadata_key(_imp->binary_destination_key);
add_metadata_key(_imp->binary_src_uri_prefix_key);
add_metadata_key(_imp->binary_keywords);
+ if (_imp->accounts_repository_data_location_key)
+ add_metadata_key(_imp->accounts_repository_data_location_key);
}
bool
diff --git a/paludis/repositories/e/exheres_layout.cc b/paludis/repositories/e/exheres_layout.cc
index 3b48bdb..dd251c7 100644
--- a/paludis/repositories/e/exheres_layout.cc
+++ b/paludis/repositories/e/exheres_layout.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2007, 2008, 2009 Ciaran McCreesh
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -40,7 +40,9 @@
#include <paludis/util/set.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
#include <paludis/util/hashes.hh>
+#include <paludis/util/make_shared_ptr.hh>
#include <paludis/choice.hh>
+#include <paludis/literal_metadata_key.hh>
#include <tr1/functional>
#include <tr1/unordered_map>
#include <functional>
@@ -648,3 +650,13 @@ ExheresLayout::binary_ebuild_location(const QualifiedPackageName & q, const Vers
return package_directory(q) / _imp->entries->binary_ebuild_name(q, v, eapi);
}
+std::tr1::shared_ptr<MetadataValueKey<FSEntry> >
+ExheresLayout::accounts_repository_data_location_key() const
+{
+ if ((_imp->tree_root / "metadata" / "accounts").exists())
+ return make_shared_ptr(new LiteralMetadataValueKey<FSEntry>("accounts_repository_data_location",
+ "AccountsRepository data location", mkt_internal, _imp->tree_root / "metadata" / "accounts"));
+ else
+ return make_null_shared_ptr();
+}
+
diff --git a/paludis/repositories/e/exheres_layout.hh b/paludis/repositories/e/exheres_layout.hh
index e8f9498..12af444 100644
--- a/paludis/repositories/e/exheres_layout.hh
+++ b/paludis/repositories/e/exheres_layout.hh
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2007, 2008, 2009 Ciaran McCreesh
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -127,6 +127,9 @@ namespace paludis
virtual std::tr1::shared_ptr<Map<FSEntry, std::string> > manifest_files(const QualifiedPackageName &) const
PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual std::tr1::shared_ptr<MetadataValueKey<FSEntry> > accounts_repository_data_location_key() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
virtual void invalidate_masks();
};
}
diff --git a/paludis/repositories/e/layout.hh b/paludis/repositories/e/layout.hh
index 5abf771..6595747 100644
--- a/paludis/repositories/e/layout.hh
+++ b/paludis/repositories/e/layout.hh
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2005, 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2005, 2006, 2007, 2008, 2009 Ciaran McCreesh
* Copyright (c) 2006 Danny van Dyk
*
* This file is part of the Paludis package manager. Paludis is free software;
@@ -29,6 +29,7 @@
#include <paludis/util/exception.hh>
#include <paludis/util/map-fwd.hh>
#include <paludis/repositories/e/use_desc.hh>
+#include <paludis/metadata_key-fwd.hh>
#include <tr1/memory>
namespace paludis
@@ -148,6 +149,9 @@ namespace paludis
virtual std::tr1::shared_ptr<Map<FSEntry, std::string> > manifest_files(const QualifiedPackageName &) const
PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+ virtual std::tr1::shared_ptr<MetadataValueKey<FSEntry> > accounts_repository_data_location_key() const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
virtual FSEntry sync_filter_file() const;
virtual void invalidate_masks() = 0;
diff --git a/paludis/repositories/e/traditional_layout.cc b/paludis/repositories/e/traditional_layout.cc
index 43aeb35..15ce2c5 100644
--- a/paludis/repositories/e/traditional_layout.cc
+++ b/paludis/repositories/e/traditional_layout.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2005, 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2005, 2006, 2007, 2008, 2009 Ciaran McCreesh
* Copyright (c) 2006 Danny van Dyk
*
* This file is part of the Paludis package manager. Paludis is free software;
@@ -39,6 +39,7 @@
#include <paludis/util/set.hh>
#include <paludis/util/indirect_iterator-impl.hh>
#include <paludis/util/hashes.hh>
+#include <paludis/util/make_shared_ptr.hh>
#include <paludis/choice.hh>
#include <tr1/functional>
#include <tr1/unordered_map>
@@ -664,3 +665,9 @@ TraditionalLayout::binary_ebuild_location(const QualifiedPackageName & q, const
return package_directory(q) / _imp->entries->binary_ebuild_name(q, v, eapi);
}
+std::tr1::shared_ptr<MetadataValueKey<FSEntry> >
+TraditionalLayout::accounts_repository_data_location_key() const
+{
+ return make_null_shared_ptr();
+}
+
diff --git a/paludis/repositories/e/traditional_layout.hh b/paludis/repositories/e/traditional_layout.hh
index f2bb2df..a7c70b7 100644
--- a/paludis/repositories/e/traditional_layout.hh
+++ b/paludis/repositories/e/traditional_layout.hh
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2005, 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2005, 2006, 2007, 2008, 2009 Ciaran McCreesh
* Copyright (c) 2006 Danny van Dyk
*
* This file is part of the Paludis package manager. Paludis is free software;
@@ -129,6 +129,9 @@ namespace paludis
virtual std::tr1::shared_ptr<Map<FSEntry, std::string> > manifest_files(const QualifiedPackageName &) const
PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual std::tr1::shared_ptr<MetadataValueKey<FSEntry> > accounts_repository_data_location_key() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
virtual FSEntry sync_filter_file() const;
virtual void invalidate_masks();