aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-01-26 16:54:57 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-01-26 16:54:57 +0000
commit3b7c99e52d69416f6f950aba12de939f278ce925 (patch)
treecfb0e5eee3427dcacf8df3e8cb6b048ff8592cf5
parent26e9570a12fcfa86b664ddbc88ace18a82409afb (diff)
parente3edf0be14525a801d0050eca2c7f22354a78afa (diff)
downloadpaludis-3b7c99e52d69416f6f950aba12de939f278ce925.tar.gz
paludis-3b7c99e52d69416f6f950aba12de939f278ce925.tar.xz
Merge branch 'accounts'
-rw-r--r--.gitignore1
-rw-r--r--configure.ac5
-rw-r--r--doc/configuration/Makefile.am99
-rw-r--r--doc/configuration/exndbam.html.part.in19
-rw-r--r--doc/configuration/index.html.part8
-rw-r--r--doc/configuration/installedunpackaged.html.part.in16
-rw-r--r--doc/configuration/repositories/Makefile.am104
-rw-r--r--doc/configuration/repositories/accounts.html.part15
-rw-r--r--doc/configuration/repositories/e.html.part (renamed from doc/configuration/erepository.html.part.in)31
-rw-r--r--doc/configuration/repositories/exndbam.html.part21
-rw-r--r--doc/configuration/repositories/index.html.part (renamed from doc/configuration/repositories.html.part.in)37
-rw-r--r--doc/configuration/repositories/installed_accounts.html.part21
-rw-r--r--doc/configuration/repositories/installed_unpackaged.html.part15
-rw-r--r--doc/configuration/repositories/toplinks.html.part.in138
-rw-r--r--doc/configuration/repositories/unavailable.html.part (renamed from doc/configuration/unavailable.html.part.in)21
-rw-r--r--doc/configuration/repositories/vdb.html.part (renamed from doc/configuration/vdb.html.part.in)14
-rw-r--r--doc/configuration/toplinks.html.part.in8
-rw-r--r--doc/configuration/unwritten.html.part.in36
-rw-r--r--doc/index.html.part.in8
-rw-r--r--paludis/repositories/accounts/Makefile.am98
-rw-r--r--paludis/repositories/accounts/accounts_dep_key.cc140
-rw-r--r--paludis/repositories/accounts/accounts_dep_key.hh56
-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.cc465
-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.cc317
-rw-r--r--paludis/repositories/accounts/accounts_repository_store.hh102
-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.cc288
-rw-r--r--paludis/repositories/accounts/installed_accounts_id.hh104
-rw-r--r--paludis/repositories/accounts/passwd_accounts_handler.cc266
-rw-r--r--paludis/repositories/accounts/passwd_accounts_handler.hh41
-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
46 files changed, 3392 insertions, 220 deletions
diff --git a/.gitignore b/.gitignore
index 2beb39b..a9df65d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -199,6 +199,7 @@ paludis-*.*.*.tar.bz2
/paludis/package_database_TEST
/paludis/paludis.hh
/paludis/range_rewriter_TEST
+/paludis/repositories/accounts/accounts_repository_TEST
/paludis/repositories/cran/cran_dep_parser_TEST
/paludis/repositories/cran/cran_installed_repository_TEST
/paludis/repositories/cran/cran_repository_TEST
diff --git a/configure.ac b/configure.ac
index 678d61f..6b5f416 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
@@ -1504,6 +1505,7 @@ AC_OUTPUT(
doc/api/ruby/Makefile
doc/clients/Makefile
doc/configuration/Makefile
+ doc/configuration/repositories/Makefile
doc/faq/Makefile
doc/overview/Makefile
hooks/Makefile
@@ -1524,6 +1526,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/doc/configuration/Makefile.am b/doc/configuration/Makefile.am
index 5f85e6c..065bd15 100644
--- a/doc/configuration/Makefile.am
+++ b/doc/configuration/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = .
+SUBDIRS = repositories .
CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda *.loT *.epicfail \
header.html.part \
@@ -32,21 +32,7 @@ CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda *.loT *.epicfail \
sets.html \
sets.html.part \
configfiles.html \
- specs.html \
- repositories.html \
- repositories.html.part \
- erepository.html \
- erepository.html.part \
- installedunpackaged.html \
- installedunpackaged.html.part \
- vdb.html \
- vdb.html.part \
- exndbam.html \
- exndbam.html.part \
- unavailable.html \
- unavailable.html.part \
- unwritten.html \
- unwritten.html.part
+ specs.html
MAINTAINERCLEANFILES = Makefile.in
@@ -68,14 +54,7 @@ EXTRA_DIST = \
paludisenvironmentonly.html.part \
configfiles.html.part \
specs.html.part \
- sets.html.part.in \
- repositories.html.part.in \
- erepository.html.part.in \
- installedunpackaged.html.part.in \
- unavailable.html.part.in \
- unwritten.html.part.in \
- vdb.html.part.in \
- exndbam.html.part.in
+ sets.html.part.in
paludisconfigurationhtmldir = $(htmldir)/configuration
@@ -95,14 +74,7 @@ paludisconfigurationhtml_DATA = \
use.html \
configfiles.html \
specs.html \
- sets.html \
- repositories.html \
- erepository.html \
- installedunpackaged.html \
- unavailable.html \
- unwritten.html \
- vdb.html \
- exndbam.html
+ sets.html
if HAVE_HTMLTIDY
@@ -177,42 +149,6 @@ specpath.html.part : $(srcdir)/specpath.html.part.in $(srcdir)/paludisenvironmen
-e 's,###PALUDISENVIRONMENTONLY###,,g' \
< $(srcdir)/specpath.html.part.in > specpath.html.part
-erepository.html.part : $(srcdir)/erepository.html.part.in $(srcdir)/paludisenvironmentonly.html.part
- sed \
- -e '/###PALUDISENVIRONMENTONLY###/r $(srcdir)/paludisenvironmentonly.html.part' \
- -e 's,###PALUDISENVIRONMENTONLY###,,g' \
- < $(srcdir)/erepository.html.part.in > erepository.html.part
-
-unavailable.html.part : $(srcdir)/unavailable.html.part.in $(srcdir)/paludisenvironmentonly.html.part
- sed \
- -e '/###PALUDISENVIRONMENTONLY###/r $(srcdir)/paludisenvironmentonly.html.part' \
- -e 's,###PALUDISENVIRONMENTONLY###,,g' \
- < $(srcdir)/unavailable.html.part.in > unavailable.html.part
-
-unwritten.html.part : $(srcdir)/unwritten.html.part.in $(srcdir)/paludisenvironmentonly.html.part
- sed \
- -e '/###PALUDISENVIRONMENTONLY###/r $(srcdir)/paludisenvironmentonly.html.part' \
- -e 's,###PALUDISENVIRONMENTONLY###,,g' \
- < $(srcdir)/unwritten.html.part.in > unwritten.html.part
-
-installedunpackaged.html.part : $(srcdir)/installedunpackaged.html.part.in $(srcdir)/paludisenvironmentonly.html.part
- sed \
- -e '/###PALUDISENVIRONMENTONLY###/r $(srcdir)/paludisenvironmentonly.html.part' \
- -e 's,###PALUDISENVIRONMENTONLY###,,g' \
- < $(srcdir)/installedunpackaged.html.part.in > installedunpackaged.html.part
-
-vdb.html.part : $(srcdir)/vdb.html.part.in $(srcdir)/paludisenvironmentonly.html.part
- sed \
- -e '/###PALUDISENVIRONMENTONLY###/r $(srcdir)/paludisenvironmentonly.html.part' \
- -e 's,###PALUDISENVIRONMENTONLY###,,g' \
- < $(srcdir)/vdb.html.part.in > vdb.html.part
-
-exndbam.html.part : $(srcdir)/exndbam.html.part.in $(srcdir)/paludisenvironmentonly.html.part
- sed \
- -e '/###PALUDISENVIRONMENTONLY###/r $(srcdir)/paludisenvironmentonly.html.part' \
- -e 's,###PALUDISENVIRONMENTONLY###,,g' \
- < $(srcdir)/exndbam.html.part.in > exndbam.html.part
-
environment.html.part : $(srcdir)/environment.html.part.in $(srcdir)/paludisenvironmentonly.html.part
sed \
-e '/###PALUDISENVIRONMENTONLY###/r $(srcdir)/paludisenvironmentonly.html.part' \
@@ -225,12 +161,6 @@ keywords.html.part : $(srcdir)/keywords.html.part.in $(srcdir)/paludisenvironmen
-e 's,###PALUDISENVIRONMENTONLY###,,g' \
< $(srcdir)/keywords.html.part.in > keywords.html.part
-repositories.html.part : $(srcdir)/repositories.html.part.in $(srcdir)/paludisenvironmentonly.html.part
- sed \
- -e '/###PALUDISENVIRONMENTONLY###/r $(srcdir)/paludisenvironmentonly.html.part' \
- -e 's,###PALUDISENVIRONMENTONLY###,,g' \
- < $(srcdir)/repositories.html.part.in > repositories.html.part
-
packagemask.html.part : $(srcdir)/packagemask.html.part.in $(srcdir)/paludisenvironmentonly.html.part
sed \
-e '/###PALUDISENVIRONMENTONLY###/r $(srcdir)/paludisenvironmentonly.html.part' \
@@ -279,9 +209,6 @@ environment.html : header.html.part environment.html.part footer.html.part
keywords.html : header.html.part keywords.html.part footer.html.part
cat header.html.part keywords.html.part footer.html.part > $@
-repositories.html : header.html.part repositories.html.part footer.html.part
- cat header.html.part repositories.html.part footer.html.part > $@
-
packagemask.html : header.html.part packagemask.html.part footer.html.part
cat header.html.part packagemask.html.part footer.html.part > $@
@@ -303,24 +230,6 @@ use.html : header.html.part use.html.part footer.html.part
specpath.html : header.html.part specpath.html.part footer.html.part
cat header.html.part specpath.html.part footer.html.part > $@
-erepository.html : header.html.part erepository.html.part footer.html.part
- cat header.html.part erepository.html.part footer.html.part > $@
-
-installedunpackaged.html : header.html.part installedunpackaged.html.part footer.html.part
- cat header.html.part installedunpackaged.html.part footer.html.part > $@
-
-unavailable.html : header.html.part unavailable.html.part footer.html.part
- cat header.html.part unavailable.html.part footer.html.part > $@
-
-unwritten.html : header.html.part unwritten.html.part footer.html.part
- cat header.html.part unwritten.html.part footer.html.part > $@
-
-vdb.html : header.html.part vdb.html.part footer.html.part
- cat header.html.part vdb.html.part footer.html.part > $@
-
-exndbam.html : header.html.part exndbam.html.part footer.html.part
- cat header.html.part exndbam.html.part footer.html.part > $@
-
syncers.html : header.html.part syncers.html.part footer.html.part
cat header.html.part syncers.html.part footer.html.part > $@
diff --git a/doc/configuration/exndbam.html.part.in b/doc/configuration/exndbam.html.part.in
deleted file mode 100644
index 181d85f..0000000
--- a/doc/configuration/exndbam.html.part.in
+++ /dev/null
@@ -1,19 +0,0 @@
-<!-- vim: set tw=120 ft=html sw=4 sts=4 et : -->
-
-<h1>exndbam Options</h1>
-
-###PALUDISENVIRONMENTONLY###
-
-<p>As well as the general keys supported for all repositories, the following keys have meaning for exndbam format
-repositories:</p>
-
-<dl>
- <dt><code>location</code></dt>
- <dd>The location of the repository. Mandatory.</dd>
-
- <dt><code>builddir</code></dt>
- <dd>The directory to use when 'building' a package for an uninstall (a temporary directory is needed for various
- operations). Optional.</dd>
-</dl>
-
-
diff --git a/doc/configuration/index.html.part b/doc/configuration/index.html.part
index 085a3a9..6914cd1 100644
--- a/doc/configuration/index.html.part
+++ b/doc/configuration/index.html.part
@@ -33,12 +33,6 @@
<li><a href="packagemask.html">package_mask.conf and package_unmask.conf</a>: for masks.</li>
<li><a href="bashrc.html">bashrc</a>: for package build environment options.</li>
<li><a href="sets.html">sets/*.conf</a>: for user defined package sets.</li>
- <li><a href="repositories.html">repositories/*.conf and repository_defaults.conf</a>, in general.</li>
- <li>... and configuration keys for <a href="erepository.html">ebuild and exheres repositories</a>.</li>
- <li>... and configuration keys for <a href="vdb.html">vdb repositories</a>.</li>
- <li>... and configuration keys for <a href="exndbam.html">exndbam repositories</a>.</li>
- <li>... and configuration keys for <a href="installedunpackaged.html">installed unpackaged repositories</a>.</li>
- <li>... and configuration keys for <a href="unavailable.html">unavailable repositories</a>.</li>
- <li>... and configuration keys for <a href="unwritten.html">unwritten repositories</a>.</li>
+ <li><a href="repositories/index.html">repositories/*.conf and repository_defaults.conf</a></li>
</ul>
diff --git a/doc/configuration/installedunpackaged.html.part.in b/doc/configuration/installedunpackaged.html.part.in
deleted file mode 100644
index 2e089ef..0000000
--- a/doc/configuration/installedunpackaged.html.part.in
+++ /dev/null
@@ -1,16 +0,0 @@
-<!-- vim: set tw=120 ft=html sw=4 sts=4 et : -->
-
-<h1>installed_unpackaged Options</h1>
-
-###PALUDISENVIRONMENTONLY###
-
-<p>As well as the general keys supported for all repositories, the following
-keys have meaning for installed_unpackaged format repositories:</p>
-
-<dl>
- <dt><code>location</code></dt>
- <dd>The location of the repository. Mandatory.</dd>
-</dl>
-
-
-
diff --git a/doc/configuration/repositories/Makefile.am b/doc/configuration/repositories/Makefile.am
new file mode 100644
index 0000000..7a9eaf4
--- /dev/null
+++ b/doc/configuration/repositories/Makefile.am
@@ -0,0 +1,104 @@
+SUBDIRS = .
+
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda *.loT *.epicfail \
+ header.html.part \
+ toplinks.html.part \
+ footer.html.part \
+ index.html \
+ accounts.html \
+ e.html \
+ exndbam.html \
+ installed_accounts.html \
+ installed_unpackaged.html \
+ unavailable.html \
+ vdb.html
+
+MAINTAINERCLEANFILES = Makefile.in
+
+EXTRA_DIST = \
+ header.html.part \
+ toplinks.html.part \
+ footer.html.part \
+ index.html.part \
+ accounts.html \
+ e.html \
+ exndbam.html \
+ installed_accounts.html \
+ installed_unpackaged.html \
+ unavailable.html \
+ vdb.html
+
+paludisconfigurationrepositorieshtmldir = $(htmldir)/configuration/repositories/
+
+paludisconfigurationrepositorieshtml_DATA = \
+ index.html \
+ accounts.html \
+ e.html \
+ exndbam.html \
+ installed_accounts.html \
+ installed_unpackaged.html \
+ unavailable.html \
+ vdb.html
+
+if HAVE_HTMLTIDY
+
+TESTS = $(paludisconfigurationhtml_DATA)
+TESTS_ENVIRONMENT = bash $(top_srcdir)/doc/htmltidy.bash
+
+endif
+
+index.html : header.html.part $(srcdir)/index.html.part footer.html.part
+ cat header.html.part $(srcdir)/index.html.part footer.html.part > $@
+
+accounts.html : header.html.part $(srcdir)/accounts.html.part footer.html.part
+ cat header.html.part $(srcdir)/accounts.html.part footer.html.part > $@
+
+e.html : header.html.part $(srcdir)/e.html.part footer.html.part
+ cat header.html.part $(srcdir)/e.html.part footer.html.part > $@
+
+exndbam.html : header.html.part $(srcdir)/exndbam.html.part footer.html.part
+ cat header.html.part $(srcdir)/exndbam.html.part footer.html.part > $@
+
+installed_accounts.html : header.html.part $(srcdir)/installed_accounts.html.part footer.html.part
+ cat header.html.part $(srcdir)/installed_accounts.html.part footer.html.part > $@
+
+installed_unpackaged.html : header.html.part $(srcdir)/installed_unpackaged.html.part footer.html.part
+ cat header.html.part $(srcdir)/installed_unpackaged.html.part footer.html.part > $@
+
+unavailable.html : header.html.part $(srcdir)/unavailable.html.part footer.html.part
+ cat header.html.part $(srcdir)/unavailable.html.part footer.html.part > $@
+
+vdb.html : header.html.part $(srcdir)/vdb.html.part footer.html.part
+ cat header.html.part $(srcdir)/vdb.html.part footer.html.part > $@
+
+header.html.part : $(srcdir)/../../header.html.part.in toplinks.html.part
+ sed \
+ -e 's,###TOPURI###,../../,g' \
+ -e '/###TOPLINKS###/r $(srcdir)/toplinks.html.part' \
+ -e 's,###TOPLINKS###,,g' \
+ < $(srcdir)/../../header.html.part.in > header.html.part
+
+toplinks.html.part : $(srcdir)/toplinks.html.part.in
+ sed \
+ -e 's,###TOPURI###,../../,g' \
+ < $(srcdir)/toplinks.html.part.in > toplinks.html.part
+
+footer.html.part : $(srcdir)/../../footer.html.part.in
+ sed -e 's,###TOPURI###,../../,g' < $(srcdir)/../../footer.html.part.in > footer.html.part
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+distcheck-deps : $(DISTCHECK_DEPS) distcheck-deps-subdirs
+
+distcheck-deps-subdirs :
+ for s in `echo $(DIST_SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s distcheck-deps || exit 1 ; done
+
+htmldocs : htmldocs-subdirs
+
+htmldocs-subdirs :
+ for s in $(SUBDIRS) . ; do if test x$$s = x. ; then $(MAKE) htmldocs-local || exit 1 ; \
+ else $(MAKE) -C $$s htmldocs || exit 1 ; fi ; done
+
+htmldocs-local : $(paludisconfigurationrepositorieshtml_DATA)
+
diff --git a/doc/configuration/repositories/accounts.html.part b/doc/configuration/repositories/accounts.html.part
new file mode 100644
index 0000000..a8961cf
--- /dev/null
+++ b/doc/configuration/repositories/accounts.html.part
@@ -0,0 +1,15 @@
+<!-- vim: set tw=120 ft=html sw=4 sts=4 et : -->
+
+<h1>accounts Repository Format</h1>
+
+<p>The <code>accounts</code> repository format, along with the <a href="installed_accounts.html">installed_accounts</a>
+format, is used by Exherbo to track user and group accounts. It is not used by Gentoo and derived distributions.</p>
+
+<p>As well as the <a href="index.html">general keys supported for all repositories</a>, the following keys have meaning
+for <code>accounts</code> format repositories:</p>
+
+<dl>
+ <dt><code>name</code></dt>
+ <dd>If set, use this as the repository name instead of <code>accounts</code>.</dd>
+</dl>
+
diff --git a/doc/configuration/erepository.html.part.in b/doc/configuration/repositories/e.html.part
index 959e778..7233277 100644
--- a/doc/configuration/erepository.html.part.in
+++ b/doc/configuration/repositories/e.html.part
@@ -1,22 +1,24 @@
<!-- vim: set tw=120 ft=html sw=4 sts=4 et : -->
-<h1>ebuild and exheres Options</h1>
+<h1>ebuild and exheres Repository Formats</h1>
-###PALUDISENVIRONMENTONLY###
+<p>The <code>ebuild</code> repository format is used on Gentoo and derived distributions for repositories containing
+ebuilds. The <code>exheres</code> repository format is used on Exherbo for repositories containing exheres packages.
+Except where noted, all options described below are common to both formats.</p>
-<p>As well as the general keys supported for all repositories, the following keys have meaning for ebuild
-and exheres format repositories:</p>
+<p>As well as the <a href="index.html">general keys supported for all repositories</a>, the following keys have meaning
+for <code>ebuild</code> and <code>exheres</code> format repositories:</p>
<dl>
<dt><code>location</code></dt>
<dd>The location of the repository. Mandatory.</dd>
<dt><code>master_repository</code></dt>
- <dd>If set to the name of another ebuild- or exheres-format repository, that repository is used as a 'master' for
- any part of this repository that is not defined. Also changes the default importance of this repository from 0 to
- 10. (In Portage terms, this is similar to saying that this repository is an overlay with the master as the main
- repository. However, identically named and versioned packages in this repository do not hide those in the
- master.)</dd>
+ <dd>If set to the name of another ebuild-format repository, that repository is used as a 'master' for any part of
+ this repository that is not defined. Also changes the default importance of this repository from 0 to 10. (In
+ Portage terms, this is similar to saying that this repository is an overlay with the master as the main repository.
+ However, identically named and versioned packages in this repository do not hide those in the master.)
+ <code>Exheres</code> format repositories describe their own masters, so this option does not apply to them.</dd>
<dt><code>profiles</code></dt>
<dd>A space separated list of directories to use as profiles. Later entries override earlier entries. Inherited from
@@ -25,7 +27,8 @@ and exheres format repositories:</p>
<dt><code>eclassdirs</code></dt>
<dd>A space separated list of directories in which to find eclasses. The first directory is used to set
- <code>ECLASSDIR</code>, but eclasses in later directories have priority. Optional.</dd>
+ <code>ECLASSDIR</code>, but eclasses in later directories have priority. Optional, and not used by
+ <code>exheres</code> format repositories.</dd>
<dt><code>distdir</code></dt>
<dd>Where to look for and save downloaded files. Inherited from a master. Optional.</dd>
@@ -63,16 +66,16 @@ and exheres format repositories:</p>
<dd>The EAPI to use when a package does not specify an EAPI, either explicitly or by suffix. Optional, generally set
by the distribution.</dd>
- <dt><code>profile_eapi</code></dt>
- <dd>The EAPI to use for profiles. Optional, generally set by the distribution.</dd>
+ <dt><code>profile_eapi_when_unspecified</code></dt>
+ <dd>The EAPI to use for profiles when unspecified. Optional, generally set by the distribution.</dd>
<dt><code>names_cache</code></dt>
<dd>The directory in which to look for a names cache, and in which to generate a names cache. A names cache will
significantly speed up converting a <code>pkg</code> into a <code>cat/pkg</code>. See <a
- href="../overview/gettingstarted.html">Getting Started</a> for notes. Optional.</dd>
+ href="../../overview/gettingstarted.html">Getting Started</a> for notes. Optional.</dd>
<dt><code>sync</code></dt>
- <dd>How to sync the repository. See <a href="syncers.html">Syncers</a> for supported formats. Optional if the
+ <dd>How to sync the repository. See <a href="../syncers.html">Syncers</a> for supported formats. Optional if the
repository does not need to be synced.</dd>
<dt><code>sync_options</code></dt>
diff --git a/doc/configuration/repositories/exndbam.html.part b/doc/configuration/repositories/exndbam.html.part
new file mode 100644
index 0000000..15a6dae
--- /dev/null
+++ b/doc/configuration/repositories/exndbam.html.part
@@ -0,0 +1,21 @@
+<!-- vim: set tw=120 ft=html sw=4 sts=4 et : -->
+
+<h1>exndbam Repository Format</h1>
+
+<p>The <code>exndbam</code> repository format is used on Exherbo to track packages installed from an exheres. It is not
+used on Gentoo and derived distributions; <a href="vdb.html">VDB</a> serves the equivalent purpose there.</p>
+
+<p>As well as the <a href="index.html">general keys supported for all repositories</a>, the following keys have meaning
+for <code>exndbam</code> format repositories:</p>
+
+<dl>
+ <dt><code>location</code></dt>
+ <dd>The location of the repository. Mandatory.</dd>
+
+ <dt><code>builddir</code></dt>
+ <dd>The directory to use when 'building' a package for an uninstall (a temporary directory is needed for various
+ operations). Optional.</dd>
+</dl>
+
+
+
diff --git a/doc/configuration/repositories.html.part.in b/doc/configuration/repositories/index.html.part
index 7c4a688..7266ef2 100644
--- a/doc/configuration/repositories.html.part.in
+++ b/doc/configuration/repositories/index.html.part
@@ -1,8 +1,8 @@
<!-- vim: set tw=120 ft=html sw=4 sts=4 et : -->
-<h1>Repositories</h1>
+<h1>repositories/ Configuration</h1>
-###PALUDISENVIRONMENTONLY###
+<h2>In General</h2>
<p>Each file in <code>repositories/</code> named <code>*.conf</code> defines a repository. A repository configuration
file is a standard key=value config file, and it may be in bash format (in which case it has a <code>.bash</code>
@@ -18,7 +18,8 @@ prepended to each individual file.</p>
<h2>Predefined Keys</h2>
-<p>The following keys are predefined. They should not be modified.</p>
+<p>The following keys are predefined. They should not be modified, but may be used in configuration files to define
+other keys.</p>
<dl>
<dt><code>root</code></dt>
@@ -44,9 +45,26 @@ prepended to each individual file.</p>
<p>For format-specific keys, see the documentation for that format.</p>
-<h2>Predefined Repositories</h2>
+<h2>Repository Formats</h2>
-<p>If using a distribution that supports old-style virtuals, two repositories are magically defined:</p>
+<h3>For All Distributions</h3>
+
+<ul>
+ <li><a href="unavailable.html">unavailable</a>, for information about ebuilds that are present in an overlay or
+ supplemental repository that is not configured on this system.</li>
+ <li><a href="installedunpackaged.html">installed_unpackaged</a>, for tracking installs of packages installed
+ manually rather than through an ebuild.</li>
+</ul>
+
+<h3>Gentoo and Derived Distributions</h3>
+
+<ul>
+ <li><a href="e.html">ebuild</a> format repositories.</li>
+ <li><a href="vdb.html">VDB</a>, for tracking installed ebuilds.</li>
+</ul>
+
+<p>In addition, the following repositories are magically defined on Gentoo and derived distributions that make use of
+old-style virtuals:</p>
<dl>
<dt><code>virtuals</code></dt>
@@ -58,3 +76,12 @@ prepended to each individual file.</p>
packages).</dd>
</dl>
+<h3>Exherbo</h3>
+
+<ul>
+ <li><a href="e.html">exheres</a> format repositories.</li>
+ <li><a href="exndbam.html">exndbam</a>, for tracking installed packages installed from an exheres.</li>
+ <li><a href="accounts.html">accounts</a> and <a href="installed_accounts.html">installed_accounts</a> format
+ repositories, for tracking user and group accounts.</li>
+</ul>
+
diff --git a/doc/configuration/repositories/installed_accounts.html.part b/doc/configuration/repositories/installed_accounts.html.part
new file mode 100644
index 0000000..75ce0ef
--- /dev/null
+++ b/doc/configuration/repositories/installed_accounts.html.part
@@ -0,0 +1,21 @@
+<!-- vim: set tw=120 ft=html sw=4 sts=4 et : -->
+
+<h1>installed_accounts Repository Format</h1>
+
+<p>The <code>installed_accounts</code> repository format, along with the <a href="accounts.html">accounts</a> format, is
+used by Exherbo to track user and group accounts. It is not used by Gentoo and derived distributions.</p>
+
+<p>As well as the <a href="index.html">general keys supported for all repositories</a>, the following keys have meaning
+for <code>installed_accounts</code> format repositories:</p>
+
+<dl>
+ <dt><code>name</code></dt>
+ <dd>If set, use this as the repository name instead of <code>accounts</code>.</dd>
+
+ <dt><code>handler</code></dt>
+ <dd>The handler to use for creating accounts. Currently only <code>passwd</code> is supported, which uses
+ <code>useradd</code> and <code>groupadd</code>. Mandatory</dd>
+</dl>
+
+
+
diff --git a/doc/configuration/repositories/installed_unpackaged.html.part b/doc/configuration/repositories/installed_unpackaged.html.part
new file mode 100644
index 0000000..2176d9b
--- /dev/null
+++ b/doc/configuration/repositories/installed_unpackaged.html.part
@@ -0,0 +1,15 @@
+<!-- vim: set tw=120 ft=html sw=4 sts=4 et : -->
+
+<h1>installed_unpackaged Repository Format</h1>
+
+<p>The <code>installed_unpackaged</code> repository format is used to keep
+track of packages installed using <code>importare</code>.</p>
+
+<p>As well as the <a href="index.html">general keys supported for all repositories</a>, the following keys have meaning
+for <code>installed_unpackaged</code> format repositories:</p>
+
+<dl>
+ <dt><code>location</code></dt>
+ <dd>The location of the repository. Mandatory.</dd>
+</dl>
+
diff --git a/doc/configuration/repositories/toplinks.html.part.in b/doc/configuration/repositories/toplinks.html.part.in
new file mode 100644
index 0000000..f5f283a
--- /dev/null
+++ b/doc/configuration/repositories/toplinks.html.part.in
@@ -0,0 +1,138 @@
+<!-- vim: set tw=120 ft=html sw=4 sts=4 et : -->
+
+<div class="topnavinner">
+ <table border="0" cellspacing="0" summary="Navigation links">
+ <tr>
+ <td rowspan="7" class="logotab">
+ <a href="###TOPURI###index.html" class="noarrow"><img style="border: 0px; padding-right: 50px;"
+ src="###TOPURI###paludis_270.png" alt="Paludis Logo"
+ /></a>
+ </td>
+
+ <td>
+ <a href="###TOPURI###index.html">Introduction</a>
+ </td>
+
+ <td>
+ &nbsp;
+ </td>
+
+ <td class="currentpage">
+ <a href="###TOPURI###configuration/repositories/accounts.html">accounts</a>
+ </td>
+
+ <td class="currentpage">
+ &nbsp;
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <a href="http://trac.pioto.org/paludis/">Bugs, Requests, Support</a>
+ </td>
+
+ <td>
+ &nbsp;
+ </td>
+
+ <td class="currentpage">
+ <a href="###TOPURI###configuration/repositories/e.html">ebuild and exheres</a>
+ </td>
+
+ <td class="currentpage">
+ &nbsp;
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <a href="###TOPURI###overview/index.html">Overview</a>
+ </td>
+
+ <td>
+ &nbsp;
+ </td>
+
+ <td class="currentpage">
+ <a href="###TOPURI###configuration/repositories/exndbam.html">exndbam</a>
+ </td>
+
+ <td class="currentpage">
+ &nbsp;
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <a href="###TOPURI###faq/index.html">FAQ</a>
+ </td>
+
+ <td>
+ &nbsp;
+ </td>
+
+ <td class="currentpage">
+ <a href="###TOPURI###configuration/repositories/installed_accounts.html">installed_accounts</a>
+ </td>
+
+ <td class="currentpage">
+ &nbsp;
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <a href="###TOPURI###clients/index.html">Clients</a>
+ </td>
+
+ <td>
+ &nbsp;
+ </td>
+
+ <td class="currentpage">
+ <a href="###TOPURI###configuration/repositories/installed_unpackaged.html">installed_unpackaged</a>
+ </td>
+
+ <td class="currentpage">
+ &nbsp;
+ </td>
+ </tr>
+
+ <tr>
+ <td class="currenttab">
+ <a href="###TOPURI###configuration/index.html">Configuration</a>
+ </td>
+
+ <td class="currenttab">
+ <a href="###TOPURI###configuration/repositories/index.html">repositories/</a>
+ </td>
+
+ <td class="currentpage">
+ <a href="###TOPURI###configuration/repositories/unavailable.html">unavailable</a>
+ </td>
+
+ <td class="currentpage">
+ &nbsp;
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <a href="###TOPURI###api/index.html">API</a>
+ </td>
+
+ <td>
+ &nbsp;
+ </td>
+
+ <td class="currentpage">
+ <a href="###TOPURI###configuration/repositories/vdb.html">VDB</a>
+ </td>
+
+ <td class="currentpage">
+ &nbsp;
+ </td>
+ </tr>
+ </table>
+</div>
+
diff --git a/doc/configuration/unavailable.html.part.in b/doc/configuration/repositories/unavailable.html.part
index bdaf9a6..52d697f 100644
--- a/doc/configuration/unavailable.html.part.in
+++ b/doc/configuration/repositories/unavailable.html.part
@@ -1,11 +1,14 @@
<!-- vim: set tw=120 ft=html sw=4 sts=4 et : -->
-<h1>unavailable Options</h1>
+<h1>unavailable Repository Format</h1>
-###PALUDISENVIRONMENTONLY###
+<p>The <code>unavailable</code> repository format can be used to see basic information about packages that are available
+in other repositories that have not been configured on this system. On Gentoo, this is used for seeing repositories
+known to <code>layman</code> and <code>playman.rb</code>. On Exherbo, this is used for seeing all official and
+selected unofficial repositories.</p>
-<p>As well as the general keys supported for all repositories, the following
-keys have meaning for unavailable format repositories:</p>
+<p>As well as the <a href="index.html">general keys supported for all repositories</a>, the following keys have meaning
+for <code>unavailable</code> format repositories:</p>
<dl>
<dt><code>location</code></dt>
@@ -46,3 +49,13 @@ sync = tar+http://git.exherbo.org/exherbo_repositories.tar.bz2
importance = -100
</pre>
+<p>The following lists selected unofficial repositories:</p>
+
+<pre>
+format = unavailable
+name = unavailable-unofficial
+location = /var/db/paludis/repositories/unavailable-unofficial
+sync = tar+http://git.exherbo.org/exherbo_unofficial_repositories.tar.bz2
+importance = -100
+</pre>
+
diff --git a/doc/configuration/vdb.html.part.in b/doc/configuration/repositories/vdb.html.part
index 7a1d4ba..bda17f2 100644
--- a/doc/configuration/vdb.html.part.in
+++ b/doc/configuration/repositories/vdb.html.part
@@ -1,11 +1,12 @@
<!-- vim: set tw=120 ft=html sw=4 sts=4 et : -->
-<h1>vdb Options</h1>
+<h1>vdb Repository Format</h1>
-###PALUDISENVIRONMENTONLY###
+<p>The <code>vdb</code> repository format is used on Gentoo and derived distributions to track packages installed from
+an ebuild. It is not used on Exherbo; <a href="exndbam.html">exndbam</a> serves the equivalent purpose there.</p>
-<p>As well as the general keys supported for all repositories, the following keys have meaning for vdb format
-repositories:</p>
+<p>As well as the <a href="index.html">general keys supported for all repositories</a>, the following keys have meaning
+for <code>vdb</code> format repositories:</p>
<dl>
<dt><code>location</code></dt>
@@ -14,13 +15,13 @@ repositories:</p>
<dt><code>provides_cache</code></dt>
<dd>The directory to use for reading and writing a cache of providers of old-style virtuals. See <a
- href="../overview/gettingstarted.html">Getting Started</a> for notes. Optional, set to <code>/var/empty</code>
+ href="../../overview/gettingstarted.html">Getting Started</a> for notes. Optional, set to <code>/var/empty</code>
to disable.</dd>
<dt><code>names_cache</code></dt>
<dd>The directory in which to look for a names cache, and in which to generate a names cache. A names cache will
significantly speed up converting a <code>pkg</code> into a <code>cat/pkg</code>. See <a
- href="../overview/gettingstarted.html">Getting Started</a> for notes. Optional, set to <code>/var/empty</code>
+ href="../../overview/gettingstarted.html">Getting Started</a> for notes. Optional, set to <code>/var/empty</code>
to disable.</dd>
<dt><code>builddir</code></dt>
@@ -29,3 +30,4 @@ repositories:</p>
</dl>
+
diff --git a/doc/configuration/toplinks.html.part.in b/doc/configuration/toplinks.html.part.in
index d4c4f98..cae0ae4 100644
--- a/doc/configuration/toplinks.html.part.in
+++ b/doc/configuration/toplinks.html.part.in
@@ -40,7 +40,7 @@
</td>
<td class="currentpage">
- <a href="###TOPURI###configuration/repositories.html">repositories/</a>
+ <a href="###TOPURI###configuration/repositories/index.html">repositories/</a>
</td>
</tr>
@@ -58,7 +58,7 @@
</td>
<td class="currentpage">
- <a href="###TOPURI###configuration/erepository.html">ebuild</a>
+ &nbsp;
</td>
</tr>
@@ -76,7 +76,7 @@
</td>
<td class="currentpage">
- <a href="###TOPURI###configuration/vdb.html">vdb</a>
+ &nbsp;
</td>
</tr>
@@ -94,7 +94,7 @@
</td>
<td class="currentpage">
- <a href="###TOPURI###configuration/installedunpackaged.html">installed unpackaged</a>
+ &nbsp;
</td>
</tr>
diff --git a/doc/configuration/unwritten.html.part.in b/doc/configuration/unwritten.html.part.in
deleted file mode 100644
index 9879556..0000000
--- a/doc/configuration/unwritten.html.part.in
+++ /dev/null
@@ -1,36 +0,0 @@
-<!-- vim: set tw=120 ft=html sw=4 sts=4 et : -->
-
-<h1>unwritten Options</h1>
-
-###PALUDISENVIRONMENTONLY###
-
-<p>As well as the general keys supported for all repositories, the following
-keys have meaning for unwritten format repositories:</p>
-
-<dl>
- <dt><code>location</code></dt>
- <dd>The location of the repository. Mandatory.</dd>
-
- <dt><code>name</code></dt>
- <dd>The name of the repository. Defaults to <code>unwritten</code>.</dd>
-
- <dt><code>sync</code></dt>
- <dd>How to sync the repository. See <a href="syncers.html">Syncers</a> for supported formats.</dd>
-
- <dt><code>sync_options</code></dt>
- <dd>Any options to be passed to the syncer. Optional.</dd>
-</dl>
-
-<h2>Reference Configurations</h2>
-
-<h3>Exherbo</h3>
-
-<p>The following is the official unwritten list:</p>
-
-<pre>
-format = unwritten
-location = /var/db/paludis/repositories/unwritten
-sync = git://git.exherbo.org/unwritten.git
-importance = -100
-</pre>
-
diff --git a/doc/index.html.part.in b/doc/index.html.part.in
index cb66f16..1661708 100644
--- a/doc/index.html.part.in
+++ b/doc/index.html.part.in
@@ -64,13 +64,7 @@ the exheres repository format.</p>
<li><a href="configuration/packagemask.html">package_mask.conf and package_unmask.conf</a>: for masks.</li>
<li><a href="configuration/bashrc.html">bashrc</a>: for package build environment options.</li>
<li><a href="configuration/sets.html">sets/*.conf</a>: for user defined package sets.</li>
- <li><a href="configuration/repositories.html">repositories/*.conf and repository_defaults.conf</a>, in general.</li>
- <li>... and configuration keys for <a href="configuration/erepository.html">ebuild and exheres repositories</a>.</li>
- <li>... and configuration keys for <a href="configuration/vdb.html">VDB repositories</a>.</li>
- <li>... and configuration keys for <a href="configuration/exndbam.html">Exndbam repositories</a>.</li>
- <li>... and configuration keys for <a href="configuration/installedunpackaged.html">installed unpackaged repositories</a>.</li>
- <li>... and configuration keys for <a href="configuration/unavailable.html">unavailable repositories</a>.</li>
- <li>... and configuration keys for <a href="configuration/unwritten.html">unwritten repositories</a>.</li>
+ <li><a href="repositories/index.html">repositories/*.conf and repository_defaults.conf</a></li>
</ul>
<h2>Client Documentation</h2>
diff --git a/paludis/repositories/accounts/Makefile.am b/paludis/repositories/accounts/Makefile.am
new file mode 100644
index 0000000..0cb9ec1
--- /dev/null
+++ b/paludis/repositories/accounts/Makefile.am
@@ -0,0 +1,98 @@
+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 \
+ accounts_dep_key.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 \
+ accounts_dep_key.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_dep_key.cc b/paludis/repositories/accounts/accounts_dep_key.cc
new file mode 100644
index 0000000..913ec40
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_dep_key.cc
@@ -0,0 +1,140 @@
+/* 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_dep_key.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/selection.hh>
+#include <paludis/generator.hh>
+#include <paludis/filtered_generator.hh>
+#include <paludis/filter.hh>
+#include <paludis/dep_spec.hh>
+#include <paludis/formatter.hh>
+#include <paludis/environment.hh>
+#include <sstream>
+
+using namespace paludis;
+using namespace paludis::accounts_repository;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<AccountsDepKey>
+ {
+ const Environment * const env;
+ const std::tr1::shared_ptr<Sequence<std::tr1::shared_ptr<PackageDepSpec> > > specs;
+ const std::tr1::shared_ptr<DependencySpecTree> tree;
+ const std::tr1::shared_ptr<DependencyLabelSequence> initial_labels;
+
+ Implementation(const Environment * const e, const std::tr1::shared_ptr<const Set<std::string> > & s) :
+ env(e),
+ specs(new Sequence<std::tr1::shared_ptr<PackageDepSpec> >),
+ tree(new DependencySpecTree(make_shared_ptr(new AllDepSpec))),
+ initial_labels(new DependencyLabelSequence)
+ {
+ for (Set<std::string>::ConstIterator i(s->begin()), i_end(s->end()) ;
+ i != i_end ; ++i)
+ {
+ std::tr1::shared_ptr<PackageDepSpec> spec(new PackageDepSpec(make_package_dep_spec()
+ .package(CategoryNamePart("group") + PackageNamePart(*i))));
+ specs->push_back(spec);
+ tree->root()->append(spec);
+ }
+
+ initial_labels->push_back(make_shared_ptr(new DependencyBuildLabel("build")));
+ initial_labels->push_back(make_shared_ptr(new DependencyRunLabel("run")));
+ }
+ };
+}
+
+AccountsDepKey::AccountsDepKey(const Environment * const e,
+ const std::tr1::shared_ptr<const Set<std::string> > & s) :
+ PrivateImplementationPattern<AccountsDepKey>(new Implementation<AccountsDepKey>(e, s))
+{
+}
+
+AccountsDepKey::~AccountsDepKey()
+{
+}
+
+const std::string
+AccountsDepKey::raw_name() const
+{
+ return "dependencies";
+}
+
+const std::string
+AccountsDepKey::human_name() const
+{
+ return "Dependencies";
+}
+
+MetadataKeyType
+AccountsDepKey::type() const
+{
+ return mkt_dependencies;
+}
+
+const std::tr1::shared_ptr<const DependencySpecTree>
+AccountsDepKey::value() const
+{
+ return _imp->tree;
+}
+
+const std::tr1::shared_ptr<const DependencyLabelSequence>
+AccountsDepKey::initial_labels() const
+{
+ return _imp->initial_labels;
+}
+
+std::string
+AccountsDepKey::pretty_print(const DependencySpecTree::ItemFormatter & f) const
+{
+ std::stringstream s;
+
+ for (Sequence<std::tr1::shared_ptr<PackageDepSpec> >::ConstIterator i(_imp->specs->begin()),
+ i_end(_imp->specs->end()) ; i != i_end ; ++i)
+ {
+ if (! s.str().empty())
+ s << ", ";
+
+ if (_imp->env)
+ {
+ if (! (*_imp->env)[selection::SomeArbitraryVersion(generator::Matches(**i, MatchPackageOptions()) |
+ filter::InstalledAtRoot(_imp->env->root()))]->empty())
+ s << f.format(**i, format::Installed());
+ else if (! (*_imp->env)[selection::SomeArbitraryVersion(generator::Matches(**i, MatchPackageOptions()) |
+ filter::SupportsAction<InstallAction>() | filter::NotMasked())]->empty())
+ s << f.format(**i, format::Installable());
+ else
+ s << f.format(**i, format::Plain());
+ }
+ else
+ s << f.format(**i, format::Plain());
+ }
+
+ return s.str();
+}
+
+std::string
+AccountsDepKey::pretty_print_flat(const DependencySpecTree::ItemFormatter & f) const
+{
+ return pretty_print(f);
+}
+
diff --git a/paludis/repositories/accounts/accounts_dep_key.hh b/paludis/repositories/accounts/accounts_dep_key.hh
new file mode 100644
index 0000000..a52af75
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_dep_key.hh
@@ -0,0 +1,56 @@
+/* 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_DEP_KEY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_ACCOUNTS_ACCOUNTS_DEP_KEY_HH 1
+
+#include <paludis/metadata_key.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace paludis
+{
+ namespace accounts_repository
+ {
+ class AccountsDepKey :
+ public MetadataSpecTreeKey<DependencySpecTree>,
+ private PrivateImplementationPattern<AccountsDepKey>
+ {
+ public:
+ AccountsDepKey(const Environment * const e,
+ const std::tr1::shared_ptr<const Set<std::string> > &);
+ ~AccountsDepKey();
+
+ virtual const std::string raw_name() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual const std::string human_name() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual MetadataKeyType type() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual const std::tr1::shared_ptr<const DependencySpecTree> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print(const DependencySpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual std::string pretty_print_flat(const DependencySpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual const std::tr1::shared_ptr<const DependencyLabelSequence> initial_labels() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
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..06e0924
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_id.cc
@@ -0,0 +1,465 @@
+/* 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/repositories/accounts/accounts_dep_key.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>
+#include <algorithm>
+
+using namespace paludis;
+using namespace paludis::accounts_repository;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<AccountsID>
+ {
+ 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;
+
+ const bool is_user;
+
+ 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;
+ mutable std::tr1::shared_ptr<const AccountsDepKey> dependencies_key;
+
+ mutable std::tr1::shared_ptr<const LiteralMetadataValueKey<std::string> > groupname_key;
+ mutable std::tr1::shared_ptr<const LiteralMetadataValueKey<std::string> > preferred_gid_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, const bool u) :
+ 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),
+ is_user(u),
+ has_file_keys(false),
+ has_metadata_keys(false)
+ {
+ }
+ };
+}
+
+AccountsID::AccountsID(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,
+ const bool u) :
+ PrivateImplementationPattern<AccountsID>(new Implementation<AccountsID>(e, q, r, f, l, u)),
+ _imp(PrivateImplementationPattern<AccountsID>::_imp)
+{
+}
+
+AccountsID::~AccountsID()
+{
+}
+
+void
+AccountsID::_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);
+ if (_imp->dependencies_key)
+ add_metadata_key(_imp->dependencies_key);
+
+ if (_imp->groupname_key)
+ add_metadata_key(_imp->groupname_key);
+ if (_imp->preferred_gid_key)
+ add_metadata_key(_imp->preferred_gid_key);
+
+ _imp->has_metadata_keys = true;
+}
+
+void
+AccountsID::_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 */
+
+ if (_imp->is_user)
+ {
+ _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")));
+
+ std::tr1::shared_ptr<Set<std::string> > all_groups_s(new Set<std::string>);
+
+ 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());
+ std::copy(groups_s->begin(), groups_s->end(), all_groups_s->inserter());
+ _imp->extra_groups_key.reset(new LiteralMetadataStringSetKey("extra_groups", "Extra Groups",
+ mkt_normal, groups_s));
+ }
+
+ 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")));
+ all_groups_s->insert(k.get("default_group"));
+ }
+
+ if (! all_groups_s->empty())
+ _imp->dependencies_key.reset(new AccountsDepKey(_imp->env, all_groups_s));
+ }
+ else
+ {
+ _imp->groupname_key.reset(new LiteralMetadataValueKey<std::string>("groupname", "Groupname",
+ mkt_significant, stringify(name().package())));
+
+ if (! k.get("preferred_gid").empty())
+ _imp->preferred_gid_key.reset(new LiteralMetadataValueKey<std::string>("preferred_gid", "Preferred GID",
+ mkt_normal, k.get("preferred_gid")));
+ }
+
+ _imp->has_file_keys = true;
+}
+
+void
+AccountsID::need_keys_added() const
+{
+ if (! _imp->has_file_keys)
+ _need_file_keys();
+
+ if (! _imp->has_metadata_keys)
+ _add_metadata_keys();
+}
+
+void
+AccountsID::clear_metadata_keys() const
+{
+ Lock lock(_imp->mutex);
+ _imp->has_metadata_keys = false;
+ PackageID::clear_metadata_keys();
+}
+
+void
+AccountsID::need_masks_added() const
+{
+}
+
+const QualifiedPackageName
+AccountsID::name() const
+{
+ return _imp->name;
+}
+
+const VersionSpec
+AccountsID::version() const
+{
+ return _imp->version;
+}
+
+const SlotName
+AccountsID::slot() const
+{
+ return _imp->slot;
+}
+
+const std::tr1::shared_ptr<const Repository>
+AccountsID::repository() const
+{
+ return _imp->repository;
+}
+
+const std::string
+AccountsID::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> > >
+AccountsID::virtual_for_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataCollectionKey<KeywordNameSet> >
+AccountsID::keywords_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<ProvideSpecTree> >
+AccountsID::provide_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataCollectionKey<PackageIDSequence> >
+AccountsID::contains_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const PackageID> > >
+AccountsID::contained_in_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+AccountsID::build_dependencies_key() const
+{
+ _need_file_keys();
+ return _imp->dependencies_key;
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+AccountsID::run_dependencies_key() const
+{
+ _need_file_keys();
+ return _imp->dependencies_key;
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+AccountsID::post_dependencies_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+AccountsID::suggested_dependencies_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<FetchableURISpecTree> >
+AccountsID::fetches_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<SimpleURISpecTree> >
+AccountsID::homepage_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::string> >
+AccountsID::short_description_key() const
+{
+ if (_imp->is_user)
+ {
+ _need_file_keys();
+ return _imp->gecos_key;
+ }
+ else
+ return _imp->groupname_key;
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::string> >
+AccountsID::long_description_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const Contents> > >
+AccountsID::contents_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataTimeKey>
+AccountsID::installed_time_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > >
+AccountsID::from_repositories_key() const
+{
+ return _imp->from_repositories_key;
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<FSEntry> >
+AccountsID::fs_location_key() const
+{
+ return _imp->fs_location_key;
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<bool> >
+AccountsID::transient_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const Choices> > >
+AccountsID::choices_key() const
+{
+ return make_null_shared_ptr();
+}
+
+std::tr1::shared_ptr<const Set<std::string> >
+AccountsID::breaks_portage() const
+{
+ return make_shared_ptr(new Set<std::string>);
+}
+
+bool
+AccountsID::arbitrary_less_than_comparison(const PackageID & other) const
+{
+ if (slot() < other.slot())
+ return true;
+
+ return false;
+}
+
+std::size_t
+AccountsID::extra_hash_value() const
+{
+ return Hash<SlotName>()(slot());
+}
+
+bool
+AccountsID::supports_action(const SupportsActionTestBase & test) const
+{
+ return simple_visitor_cast<const SupportsActionTest<InstallAction> >(test);
+}
+
+void
+AccountsID::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..557294c
--- /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 AccountsID :
+ public PackageID,
+ private PrivateImplementationPattern<AccountsID>,
+ public std::tr1::enable_shared_from_this<AccountsID>
+ {
+ private:
+ PrivateImplementationPattern<AccountsID>::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:
+ AccountsID(const Environment * const,
+ const QualifiedPackageName &, const std::tr1::shared_ptr<const Repository> &,
+ const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > > &,
+ const FSEntry &, const bool is_user);
+ ~AccountsID();
+
+ 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..6f34a97
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_repository_store.cc
@@ -0,0 +1,317 @@
+/* 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>
+#include <grp.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, from_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_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 InstalledAccountsID(_imp->env, qpn, repo, true)));
+ else
+ q->second->push_back(make_shared_ptr(new AccountsID(_imp->env, qpn, repo, from_repo, filename, true)));
+}
+
+void
+AccountsRepositoryStore::_load_one_groups(
+ 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_group(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_group(
+ 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("group");
+ PackageNamePart pkg(strip_trailing_string(filename.basename(), ".conf"));
+ QualifiedPackageName qpn(cat + pkg);
+ std::string groupname(stringify(pkg));
+
+ if (_imp->installed)
+ {
+ if (! getgrnam(groupname.c_str()))
+ return;
+ }
+ else
+ {
+ if (getgrnam(groupname.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 InstalledAccountsID(_imp->env, qpn, repo, false)));
+ else
+ q->second->push_back(make_shared_ptr(new AccountsID(_imp->env, qpn, repo, from_repo, filename, false)));
+}
+
+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..45de761
--- /dev/null
+++ b/paludis/repositories/accounts/accounts_repository_store.hh
@@ -0,0 +1,102 @@
+/* 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_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_groups(
+ 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_group(
+ const std::tr1::shared_ptr<const Repository> & repo,
+ const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > > & from_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..67eaa15
--- /dev/null
+++ b/paludis/repositories/accounts/installed_accounts_id.cc
@@ -0,0 +1,288 @@
+/* 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<InstalledAccountsID>
+ {
+ 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;
+
+ const bool is_user;
+
+ Implementation(const Environment * const e,
+ const QualifiedPackageName & q, const std::tr1::shared_ptr<const Repository> & r,
+ const bool u) :
+ env(e),
+ name(q),
+ version("0"),
+ slot("0"),
+ repository(r),
+ transient_key(new LiteralMetadataValueKey<bool>("transient", "Transient", mkt_internal, true)),
+ is_user(u)
+ {
+ }
+ };
+}
+
+InstalledAccountsID::InstalledAccountsID(const Environment * const e,
+ const QualifiedPackageName & q, const std::tr1::shared_ptr<const Repository> & r, const bool u) :
+ PrivateImplementationPattern<InstalledAccountsID>(new Implementation<InstalledAccountsID>(e, q, r, u)),
+ _imp(PrivateImplementationPattern<InstalledAccountsID>::_imp)
+{
+ add_metadata_key(_imp->transient_key);
+}
+
+InstalledAccountsID::~InstalledAccountsID()
+{
+}
+
+void
+InstalledAccountsID::need_keys_added() const
+{
+}
+
+void
+InstalledAccountsID::clear_metadata_keys() const
+{
+}
+
+void
+InstalledAccountsID::need_masks_added() const
+{
+}
+
+const QualifiedPackageName
+InstalledAccountsID::name() const
+{
+ return _imp->name;
+}
+
+const VersionSpec
+InstalledAccountsID::version() const
+{
+ return _imp->version;
+}
+
+const SlotName
+InstalledAccountsID::slot() const
+{
+ return _imp->slot;
+}
+
+const std::tr1::shared_ptr<const Repository>
+InstalledAccountsID::repository() const
+{
+ return _imp->repository;
+}
+
+const std::string
+InstalledAccountsID::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> > >
+InstalledAccountsID::virtual_for_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataCollectionKey<KeywordNameSet> >
+InstalledAccountsID::keywords_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<ProvideSpecTree> >
+InstalledAccountsID::provide_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataCollectionKey<PackageIDSequence> >
+InstalledAccountsID::contains_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const PackageID> > >
+InstalledAccountsID::contained_in_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+InstalledAccountsID::build_dependencies_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+InstalledAccountsID::run_dependencies_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+InstalledAccountsID::post_dependencies_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+InstalledAccountsID::suggested_dependencies_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<FetchableURISpecTree> >
+InstalledAccountsID::fetches_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataSpecTreeKey<SimpleURISpecTree> >
+InstalledAccountsID::homepage_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::string> >
+InstalledAccountsID::short_description_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::string> >
+InstalledAccountsID::long_description_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const Contents> > >
+InstalledAccountsID::contents_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataTimeKey>
+InstalledAccountsID::installed_time_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataCollectionKey<Set<std::string> > >
+InstalledAccountsID::from_repositories_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<FSEntry> >
+InstalledAccountsID::fs_location_key() const
+{
+ return make_null_shared_ptr();
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<bool> >
+InstalledAccountsID::transient_key() const
+{
+ return _imp->transient_key;
+}
+
+const std::tr1::shared_ptr<const MetadataValueKey<std::tr1::shared_ptr<const Choices> > >
+InstalledAccountsID::choices_key() const
+{
+ return make_null_shared_ptr();
+}
+
+std::tr1::shared_ptr<const Set<std::string> >
+InstalledAccountsID::breaks_portage() const
+{
+ return make_shared_ptr(new Set<std::string>);
+}
+
+bool
+InstalledAccountsID::arbitrary_less_than_comparison(const PackageID & other) const
+{
+ if (slot() < other.slot())
+ return true;
+
+ return false;
+}
+
+std::size_t
+InstalledAccountsID::extra_hash_value() const
+{
+ return Hash<SlotName>()(slot());
+}
+
+bool
+InstalledAccountsID::supports_action(const SupportsActionTestBase & test) const
+{
+ return simple_visitor_cast<const SupportsActionTest<InstalledAction> >(test);
+}
+
+void
+InstalledAccountsID::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..436dc2f
--- /dev/null
+++ b/paludis/repositories/accounts/installed_accounts_id.hh
@@ -0,0 +1,104 @@
+/* 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 InstalledAccountsID :
+ public PackageID,
+ private PrivateImplementationPattern<InstalledAccountsID>,
+ public std::tr1::enable_shared_from_this<InstalledAccountsID>
+ {
+ private:
+ PrivateImplementationPattern<InstalledAccountsID>::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:
+ InstalledAccountsID(const Environment * const,
+ const QualifiedPackageName &, const std::tr1::shared_ptr<const Repository> &,
+ const bool is_user);
+ ~InstalledAccountsID();
+
+ 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..4415272
--- /dev/null
+++ b/paludis/repositories/accounts/passwd_accounts_handler.cc
@@ -0,0 +1,266 @@
+/* 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>
+#include <grp.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;
+
+ if (params.package_id()->end_metadata() != params.package_id()->find_metadata("groupname"))
+ merge_group(params);
+ else
+ merge_user(params);
+
+ std::cout << ">>> Finished installing " << *params.package_id() << std::endl;
+}
+
+void
+PasswdAccountsHandler::merge_user(const MergeParams & params)
+{
+ 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 -r " + username + preferred_uid + 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));
+}
+
+void
+PasswdAccountsHandler::merge_group(const MergeParams & params)
+{
+ std::string groupname;
+ do
+ {
+ PackageID::MetadataConstIterator m(params.package_id()->find_metadata("groupname"));
+ if (params.package_id()->end_metadata() == m)
+ throw InstallActionError("Key 'groupname' 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 'groupname' for '" + stringify(*params.package_id()) + "' is not a string key");
+
+ groupname = k->value();
+
+ if (0 != getgrnam(groupname.c_str()))
+ throw InstallActionError("Group '" + groupname + "' already exists");
+ } while (false);
+
+ std::string preferred_gid;
+ do
+ {
+ PackageID::MetadataConstIterator m(params.package_id()->find_metadata("preferred_gid"));
+ 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_gid' for '" + stringify(*params.package_id()) + "' is not a string key");
+
+ preferred_gid = k->value();
+
+ if (std::string::npos != preferred_gid.find_first_not_of("0123456789"))
+ throw InstallActionError("Value for key 'preferred_gid' for '" + stringify(*params.package_id()) + "' must be a number");
+
+ uid_t gid(destringify<uid_t>(preferred_gid));
+ if (getgrgid(gid))
+ {
+ std::cout << ">>> Preferred GID " << gid << " already in use, not specifying an ID" << std::endl;
+ preferred_gid = "";
+ }
+
+ if (! preferred_gid.empty())
+ preferred_gid = " -g '" + preferred_gid + "'";
+ } while (false);
+
+ Command cmd("groupadd -r " + groupname + preferred_gid);
+ 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 groupadd returned "
+ + stringify(exit_status));
+}
+
diff --git a/paludis/repositories/accounts/passwd_accounts_handler.hh b/paludis/repositories/accounts/passwd_accounts_handler.hh
new file mode 100644
index 0000000..7da0cf9
--- /dev/null
+++ b/paludis/repositories/accounts/passwd_accounts_handler.hh
@@ -0,0 +1,41 @@
+/* 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 &);
+
+ void merge_user(const MergeParams &);
+ void merge_group(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();