aboutsummaryrefslogtreecommitdiff
path: root/paludis/repositories/e
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-06-28 21:45:56 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-06-28 21:45:56 +0000
commit45692e817c0a0c4b4f2ebc91501987efecff23aa (patch)
treeaf997ccbbb94eda5b55271ac1ba763ac49dc5540 /paludis/repositories/e
parente73fa3ac11891c1db89e1a600b1edeb9395d86c9 (diff)
downloadpaludis-45692e817c0a0c4b4f2ebc91501987efecff23aa.tar.gz
paludis-45692e817c0a0c4b4f2ebc91501987efecff23aa.tar.xz
r3634@snowflake: ciaranm | 2007-06-28 22:45:19 +0100
We'll call it 'E', not 'Gentoo'
Diffstat (limited to 'paludis/repositories/e')
-rw-r--r--paludis/repositories/e/Makefile.am309
-rw-r--r--paludis/repositories/e/e_key.cc581
-rw-r--r--paludis/repositories/e/e_key.hh225
-rw-r--r--paludis/repositories/e/eapi_phase.cc117
-rw-r--r--paludis/repositories/e/eapi_phase.hh93
-rw-r--r--paludis/repositories/e/ebin.cc301
-rw-r--r--paludis/repositories/e/ebin.hh202
-rw-r--r--paludis/repositories/e/ebin.se25
-rw-r--r--paludis/repositories/e/ebin.sr89
-rw-r--r--paludis/repositories/e/ebin_entries.cc471
-rw-r--r--paludis/repositories/e/ebin_entries.hh83
-rw-r--r--paludis/repositories/e/ebuild.cc705
-rw-r--r--paludis/repositories/e/ebuild.hh366
-rw-r--r--paludis/repositories/e/ebuild.sr183
-rw-r--r--paludis/repositories/e/ebuild/Makefile.am87
-rw-r--r--paludis/repositories/e/ebuild/build_functions.bash110
-rw-r--r--paludis/repositories/e/ebuild/builtin_fetch.bash137
-rw-r--r--paludis/repositories/e/ebuild/builtin_fetchbin.bash98
-rw-r--r--paludis/repositories/e/ebuild/builtin_init.bash95
-rw-r--r--paludis/repositories/e/ebuild/builtin_initbin.bash90
-rw-r--r--paludis/repositories/e/ebuild/builtin_loadenv.bash48
-rw-r--r--paludis/repositories/e/ebuild/builtin_merge.bash144
-rw-r--r--paludis/repositories/e/ebuild/builtin_metadata.bash41
-rw-r--r--paludis/repositories/e/ebuild/builtin_prepare.bash49
-rw-r--r--paludis/repositories/e/ebuild/builtin_saveenv.bash54
-rw-r--r--paludis/repositories/e/ebuild/builtin_strip.bash80
-rw-r--r--paludis/repositories/e/ebuild/builtin_tidyup.bash43
-rw-r--r--paludis/repositories/e/ebuild/builtin_unmerge.bash115
-rw-r--r--paludis/repositories/e/ebuild/builtin_unpackbin.bash40
-rw-r--r--paludis/repositories/e/ebuild/builtin_variable.bash23
-rw-r--r--paludis/repositories/e/ebuild/die_functions.bash58
-rw-r--r--paludis/repositories/e/ebuild/digests/Makefile.am31
-rw-r--r--paludis/repositories/e/ebuild/digests/domd5.cc54
-rw-r--r--paludis/repositories/e/ebuild/digests/dormd160.cc53
-rw-r--r--paludis/repositories/e/ebuild/digests/dosha256.cc52
-rwxr-xr-xpaludis/repositories/e/ebuild/ebuild.bash424
-rw-r--r--paludis/repositories/e/ebuild/echo_functions.bash.in238
-rw-r--r--paludis/repositories/e/ebuild/echo_functions_TEST.bash45
-rw-r--r--paludis/repositories/e/ebuild/eclass_functions.bash82
-rw-r--r--paludis/repositories/e/ebuild/exlib_functions.bash76
-rw-r--r--paludis/repositories/e/ebuild/install_functions.bash109
-rw-r--r--paludis/repositories/e/ebuild/kernel_functions.bash59
-rw-r--r--paludis/repositories/e/ebuild/kernel_functions_TEST.bash41
-rw-r--r--paludis/repositories/e/ebuild/list_functions.bash70
-rw-r--r--paludis/repositories/e/ebuild/list_functions_TEST.bash74
-rw-r--r--paludis/repositories/e/ebuild/merge.cc451
-rw-r--r--paludis/repositories/e/ebuild/merge_TEST.bash223
-rwxr-xr-xpaludis/repositories/e/ebuild/merge_TEST_cleanup.sh10
-rwxr-xr-xpaludis/repositories/e/ebuild/merge_TEST_setup.sh74
-rw-r--r--paludis/repositories/e/ebuild/merge_common.cc99
-rw-r--r--paludis/repositories/e/ebuild/merge_common.hh50
-rw-r--r--paludis/repositories/e/ebuild/multilib_functions.bash66
-rw-r--r--paludis/repositories/e/ebuild/pkg_config.bash58
-rw-r--r--paludis/repositories/e/ebuild/pkg_nofetch.bash62
-rw-r--r--paludis/repositories/e/ebuild/pkg_postinst.bash58
-rw-r--r--paludis/repositories/e/ebuild/pkg_postrm.bash59
-rw-r--r--paludis/repositories/e/ebuild/pkg_preinst.bash58
-rw-r--r--paludis/repositories/e/ebuild/pkg_prerm.bash58
-rw-r--r--paludis/repositories/e/ebuild/pkg_pretend.bash47
-rw-r--r--paludis/repositories/e/ebuild/pkg_setup.bash58
-rw-r--r--paludis/repositories/e/ebuild/portage_stubs.bash86
-rwxr-xr-xpaludis/repositories/e/ebuild/run_test.bash47
-rw-r--r--paludis/repositories/e/ebuild/sandbox.bash42
-rw-r--r--paludis/repositories/e/ebuild/src_compile.bash61
-rw-r--r--paludis/repositories/e/ebuild/src_install.bash58
-rw-r--r--paludis/repositories/e/ebuild/src_test.bash86
-rw-r--r--paludis/repositories/e/ebuild/src_unpack.bash54
-rw-r--r--paludis/repositories/e/ebuild/unmerge.cc320
-rw-r--r--paludis/repositories/e/ebuild/unmerge_TEST.bash94
-rwxr-xr-xpaludis/repositories/e/ebuild/unmerge_TEST_cleanup.sh11
-rwxr-xr-xpaludis/repositories/e/ebuild/unmerge_TEST_setup.sh15
-rw-r--r--paludis/repositories/e/ebuild/usage_error.bash31
-rw-r--r--paludis/repositories/e/ebuild/utils/Makefile.am93
-rwxr-xr-xpaludis/repositories/e/ebuild/utils/canonicalise6
-rwxr-xr-xpaludis/repositories/e/ebuild/utils/dobin48
-rw-r--r--paludis/repositories/e/ebuild/utils/dobin_TEST.bash70
-rw-r--r--paludis/repositories/e/ebuild/utils/doconfd32
-rw-r--r--paludis/repositories/e/ebuild/utils/dodir34
-rw-r--r--paludis/repositories/e/ebuild/utils/dodoc50
-rw-r--r--paludis/repositories/e/ebuild/utils/doenvd32
-rw-r--r--paludis/repositories/e/ebuild/utils/doexe58
-rw-r--r--paludis/repositories/e/ebuild/utils/dohard34
-rw-r--r--paludis/repositories/e/ebuild/utils/dohtml122
-rw-r--r--paludis/repositories/e/ebuild/utils/doinfo50
-rw-r--r--paludis/repositories/e/ebuild/utils/doinitd32
-rw-r--r--paludis/repositories/e/ebuild/utils/doins89
-rw-r--r--paludis/repositories/e/ebuild/utils/dolib62
-rw-r--r--paludis/repositories/e/ebuild/utils/dolib.a.in27
-rw-r--r--paludis/repositories/e/ebuild/utils/dolib.so.in26
-rw-r--r--paludis/repositories/e/ebuild/utils/doman75
-rw-r--r--paludis/repositories/e/ebuild/utils/domo54
-rw-r--r--paludis/repositories/e/ebuild/utils/donewins40
-rw-r--r--paludis/repositories/e/ebuild/utils/dosbin45
-rw-r--r--paludis/repositories/e/ebuild/utils/dosed52
-rw-r--r--paludis/repositories/e/ebuild/utils/dosym42
-rwxr-xr-xpaludis/repositories/e/ebuild/utils/dounpack132
-rwxr-xr-xpaludis/repositories/e/ebuild/utils/emake22
-rw-r--r--paludis/repositories/e/ebuild/utils/exheres-0/Makefile.am49
-rwxr-xr-xpaludis/repositories/e/ebuild/utils/exheres-0/banned_in_eapi_exheres-025
-rw-r--r--paludis/repositories/e/ebuild/utils/fowners24
-rw-r--r--paludis/repositories/e/ebuild/utils/fperms24
-rwxr-xr-xpaludis/repositories/e/ebuild/utils/getfsize5
-rwxr-xr-xpaludis/repositories/e/ebuild/utils/getfsize_TEST.bash44
-rwxr-xr-xpaludis/repositories/e/ebuild/utils/getmtime5
-rw-r--r--paludis/repositories/e/ebuild/utils/newbin38
-rw-r--r--paludis/repositories/e/ebuild/utils/newconfd38
-rw-r--r--paludis/repositories/e/ebuild/utils/newdoc38
-rw-r--r--paludis/repositories/e/ebuild/utils/newenvd38
-rw-r--r--paludis/repositories/e/ebuild/utils/newexe38
-rw-r--r--paludis/repositories/e/ebuild/utils/newinitd38
-rw-r--r--paludis/repositories/e/ebuild/utils/newins38
-rw-r--r--paludis/repositories/e/ebuild/utils/newlib.a.in38
-rw-r--r--paludis/repositories/e/ebuild/utils/newlib.so.in38
-rw-r--r--paludis/repositories/e/ebuild/utils/newman38
-rw-r--r--paludis/repositories/e/ebuild/utils/newsbin38
-rw-r--r--paludis/repositories/e/ebuild/utils/prep.in21
-rw-r--r--paludis/repositories/e/ebuild/utils/run_test.bash62
-rw-r--r--paludis/repositories/e/ebuild/work_around_broken_utilities.bash.in26
-rwxr-xr-xpaludis/repositories/e/ebuild/write_vdb_entry.bash100
-rw-r--r--paludis/repositories/e/ebuild_entries.cc688
-rw-r--r--paludis/repositories/e/ebuild_entries.hh88
-rw-r--r--paludis/repositories/e/ebuild_flat_metadata_cache.cc207
-rw-r--r--paludis/repositories/e/ebuild_flat_metadata_cache.hh70
-rw-r--r--paludis/repositories/e/ebuild_id.cc551
-rw-r--r--paludis/repositories/e/ebuild_id.hh113
-rw-r--r--paludis/repositories/e/eclass_mtimes.cc71
-rw-r--r--paludis/repositories/e/eclass_mtimes.hh55
-rw-r--r--paludis/repositories/e/exheres_layout.cc441
-rw-r--r--paludis/repositories/e/exheres_layout.hh114
-rw-r--r--paludis/repositories/e/glsa.cc254
-rw-r--r--paludis/repositories/e/glsa.hh174
-rw-r--r--paludis/repositories/e/glsa.sr19
-rw-r--r--paludis/repositories/e/layout.cc76
-rw-r--r--paludis/repositories/e/layout.hh171
-rw-r--r--paludis/repositories/e/make_ebin_repository.cc196
-rw-r--r--paludis/repositories/e/make_ebin_repository.hh51
-rw-r--r--paludis/repositories/e/make_ebuild_repository.cc222
-rw-r--r--paludis/repositories/e/make_ebuild_repository.hh50
-rw-r--r--paludis/repositories/e/portage_repository.cc938
-rw-r--r--paludis/repositories/e/portage_repository.hh239
-rw-r--r--paludis/repositories/e/portage_repository_TEST.cc664
-rwxr-xr-xpaludis/repositories/e/portage_repository_TEST_cleanup.sh10
-rwxr-xr-xpaludis/repositories/e/portage_repository_TEST_setup.sh248
-rw-r--r--paludis/repositories/e/portage_repository_entries.cc51
-rw-r--r--paludis/repositories/e/portage_repository_entries.hh133
-rw-r--r--paludis/repositories/e/portage_repository_exceptions.cc29
-rw-r--r--paludis/repositories/e/portage_repository_exceptions.hh53
-rw-r--r--paludis/repositories/e/portage_repository_news.cc292
-rw-r--r--paludis/repositories/e/portage_repository_news.hh131
-rw-r--r--paludis/repositories/e/portage_repository_params.cc8
-rw-r--r--paludis/repositories/e/portage_repository_params.hh43
-rw-r--r--paludis/repositories/e/portage_repository_params.sr42
-rw-r--r--paludis/repositories/e/portage_repository_profile.cc757
-rw-r--r--paludis/repositories/e/portage_repository_profile.hh131
-rw-r--r--paludis/repositories/e/portage_repository_profile_file.cc89
-rw-r--r--paludis/repositories/e/portage_repository_profile_file.hh65
-rw-r--r--paludis/repositories/e/portage_repository_sets.cc348
-rw-r--r--paludis/repositories/e/portage_repository_sets.hh76
-rw-r--r--paludis/repositories/e/portage_repository_sets_TEST.cc180
-rwxr-xr-xpaludis/repositories/e/portage_repository_sets_TEST_cleanup.sh10
-rwxr-xr-xpaludis/repositories/e/portage_repository_sets_TEST_setup.sh214
-rw-r--r--paludis/repositories/e/registration.cc68
-rw-r--r--paludis/repositories/e/traditional_layout.cc460
-rw-r--r--paludis/repositories/e/traditional_layout.hh116
-rw-r--r--paludis/repositories/e/use_desc.cc96
-rw-r--r--paludis/repositories/e/use_desc.hh59
-rw-r--r--paludis/repositories/e/vdb_id.cc535
-rw-r--r--paludis/repositories/e/vdb_id.hh90
-rw-r--r--paludis/repositories/e/vdb_merger.cc256
-rw-r--r--paludis/repositories/e/vdb_merger.hh73
-rw-r--r--paludis/repositories/e/vdb_merger.sr29
-rw-r--r--paludis/repositories/e/vdb_repository.cc1115
-rw-r--r--paludis/repositories/e/vdb_repository.hh268
-rw-r--r--paludis/repositories/e/vdb_repository.sr28
-rw-r--r--paludis/repositories/e/vdb_repository_TEST.cc249
-rwxr-xr-xpaludis/repositories/e/vdb_repository_TEST_cleanup.sh11
-rwxr-xr-xpaludis/repositories/e/vdb_repository_TEST_setup.sh35
-rw-r--r--paludis/repositories/e/vdb_unmerger.cc391
-rw-r--r--paludis/repositories/e/vdb_unmerger.hh98
-rw-r--r--paludis/repositories/e/vdb_unmerger.sr30
-rw-r--r--paludis/repositories/e/vdb_unmerger_TEST.cc351
-rwxr-xr-xpaludis/repositories/e/vdb_unmerger_TEST_cleanup.sh9
-rwxr-xr-xpaludis/repositories/e/vdb_unmerger_TEST_setup.sh78
-rw-r--r--paludis/repositories/e/xml_things.cc219
-rw-r--r--paludis/repositories/e/xml_things.hh30
-rw-r--r--paludis/repositories/e/xml_things_TEST.cc93
-rwxr-xr-xpaludis/repositories/e/xml_things_TEST_cleanup.sh11
-rwxr-xr-xpaludis/repositories/e/xml_things_TEST_setup.sh115
188 files changed, 24211 insertions, 0 deletions
diff --git a/paludis/repositories/e/Makefile.am b/paludis/repositories/e/Makefile.am
new file mode 100644
index 000000000..24d3003f1
--- /dev/null
+++ b/paludis/repositories/e/Makefile.am
@@ -0,0 +1,309 @@
+SUBDIRS = ebuild .
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+DISTCLEANFILES = \
+ glsa-sr.hh glsa-sr.cc \
+ portage_repository_params-sr.hh portage_repository_params-sr.cc \
+ vdb_repository-sr.hh vdb_repository-sr.cc \
+ ebuild-sr.hh ebuild-sr.cc \
+ ebin-sr.hh ebin-sr.cc ebin-se.hh ebin-se.cc \
+ vdb_merger-sr.hh vdb_merger-sr.cc \
+ vdb_unmerger-sr.hh vdb_unmerger-sr.cc
+
+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 = libpaludiserepository.la
+
+if ENABLE_GLSA
+
+lib_LTLIBRARIES = libpaludiserepositoryxmlthings.la
+
+endif
+
+paludis_repositories_e_includedir = $(includedir)/paludis-$(PALUDIS_PC_SLOT)/paludis/repositories/e/
+libpaludiserepository_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+
+paludis_repositories_e_include_HEADERS = \
+ ebuild.hh \
+ ebuild-sr.hh \
+ ebin.hh \
+ ebin-se.hh \
+ ebin-sr.hh \
+ glsa.hh \
+ glsa-sr.hh \
+ portage_repository.hh \
+ portage_repository_profile_file.hh \
+ portage_repository_profile.hh \
+ portage_repository_exceptions.hh \
+ portage_repository_news.hh \
+ portage_repository_params.hh \
+ portage_repository_params-sr.hh \
+ portage_repository_sets.hh \
+ portage_repository_entries.hh \
+ ebuild_entries.hh \
+ ebin_entries.hh \
+ ebuild_flat_metadata_cache.hh \
+ eclass_mtimes.hh \
+ make_ebuild_repository.hh \
+ make_ebin_repository.hh \
+ use_desc.hh \
+ vdb_repository.hh \
+ vdb_repository-sr.hh \
+ vdb_merger-sr.hh \
+ vdb_merger.hh \
+ vdb_unmerger-sr.hh \
+ vdb_unmerger.hh \
+ layout.hh \
+ traditional_layout.hh \
+ exheres_layout.hh \
+ eapi_phase.hh \
+ ebuild_id.hh \
+ vdb_id.hh \
+ e_key.hh
+
+libpaludiserepository_la_SOURCES = \
+ ebuild.cc \
+ ebin.cc \
+ glsa.cc \
+ portage_repository.cc \
+ portage_repository_profile_file.cc \
+ portage_repository_profile.cc \
+ portage_repository_exceptions.cc \
+ portage_repository_news.cc \
+ portage_repository_sets.cc \
+ portage_repository_entries.cc \
+ ebuild_entries.cc \
+ ebin_entries.cc \
+ ebuild_flat_metadata_cache.cc \
+ eclass_mtimes.cc \
+ portage_repository_params.cc \
+ make_ebuild_repository.cc \
+ make_ebin_repository.cc \
+ use_desc.cc \
+ registration.cc \
+ vdb_repository.cc \
+ vdb_merger.cc \
+ vdb_unmerger.cc \
+ layout.cc \
+ traditional_layout.cc \
+ exheres_layout.cc \
+ eapi_phase.cc \
+ ebuild_id.cc \
+ vdb_id.cc \
+ e_key.cc \
+ $(paludis_repositories_e_include_HEADERS)
+
+libpaludiserepository_la_LIBADD = \
+ $(top_builddir)/paludis/repositories/libpaludisrepositories.la \
+ $(top_builddir)/paludis/merger/libpaludismerger.la \
+ $(top_builddir)/paludis/digests/libpaludisdigests.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+portage_repository_TEST_SOURCES = portage_repository_TEST.cc
+
+portage_repository_TEST_LDADD = \
+ libpaludiserepository.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a \
+ $(DYNAMIC_LD_LIBS)
+
+portage_repository_TEST_CXXFLAGS = $(AM_CXXFLAGS) -I$(top_srcdir)
+
+vdb_unmerger_TEST_SOURCES = vdb_unmerger_TEST.cc
+
+vdb_unmerger_TEST_LDADD = \
+ libpaludiserepository.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a \
+ $(DYNAMIC_LD_LIBS)
+
+vdb_unmerger_TEST_CXXFLAGS = $(AM_CXXFLAGS) -I$(top_srcdir)
+
+portage_repository_sets_TEST_SOURCES = portage_repository_sets_TEST.cc
+
+portage_repository_sets_TEST_LDADD = \
+ libpaludiserepository.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
+ $(top_builddir)/paludis/repositories/fake/libpaludisfakerepository.la \
+ $(top_builddir)/test/libtest.a \
+ $(DYNAMIC_LD_LIBS)
+
+portage_repository_sets_TEST_CXXFLAGS = $(AM_CXXFLAGS) -I$(top_srcdir)
+
+EXTRA_DIST = \
+ ebuild.sr \
+ ebuild-sr.hh \
+ ebuild-sr.cc \
+ ebin.sr \
+ ebin-sr.hh \
+ ebin-sr.cc \
+ ebin.se \
+ ebin-se.hh \
+ ebin-se.cc \
+ glsa.sr \
+ glsa-sr.hh \
+ glsa-sr.cc \
+ portage_repository_TEST.cc \
+ portage_repository_TEST_setup.sh \
+ portage_repository_TEST_cleanup.sh \
+ portage_repository_params-sr.hh \
+ portage_repository_params-sr.cc \
+ portage_repository_params.sr \
+ portage_repository_sets_TEST.cc \
+ portage_repository_sets_TEST_setup.sh \
+ portage_repository_sets_TEST_cleanup.sh \
+ xml_things_TEST.cc \
+ xml_things_TEST_setup.sh \
+ xml_things_TEST_cleanup.sh \
+ vdb_repository_TEST.cc \
+ vdb_repository_TEST_setup.sh \
+ vdb_repository_TEST_cleanup.sh \
+ vdb_repository-sr.hh \
+ vdb_repository-sr.cc \
+ vdb_repository.sr \
+ vdb_merger.sr \
+ vdb_merger-sr.hh \
+ vdb_merger-sr.cc \
+ vdb_unmerger.sr \
+ vdb_unmerger-sr.hh \
+ vdb_unmerger-sr.cc \
+ vdb_unmerger_TEST.cc \
+ vdb_unmerger_TEST_setup.sh \
+ vdb_unmerger_TEST_cleanup.sh
+
+BUILT_SOURCES = \
+ portage_repository_params-sr.hh \
+ portage_repository_params-sr.cc \
+ glsa-sr.hh \
+ glsa-sr.cc \
+ vdb_repository-sr.hh \
+ vdb_repository-sr.cc \
+ ebuild-sr.hh \
+ ebuild-sr.cc \
+ ebin-sr.hh \
+ ebin-sr.cc \
+ ebin-se.hh \
+ ebin-se.cc \
+ vdb_merger-sr.hh \
+ vdb_merger-sr.cc \
+ vdb_unmerger-sr.hh \
+ vdb_unmerger-sr.cc
+
+check_SCRIPTS = \
+ portage_repository_TEST_setup.sh portage_repository_TEST_cleanup.sh \
+ xml_things_TEST_setup.sh xml_things_TEST_cleanup.sh \
+ vdb_repository_TEST_setup.sh vdb_repository_TEST_cleanup.sh \
+ portage_repository_sets_TEST_setup.sh portage_repository_sets_TEST_cleanup.sh
+
+TESTS_ENVIRONMENT = env \
+ PALUDIS_EBUILD_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_srcdir)/paludis/repositories/e/ebuild/`" \
+ PALUDIS_EAPIS_DIR="$(top_srcdir)/paludis/eapis/" \
+ PALUDIS_DISTRIBUTIONS_DIR="$(top_srcdir)/paludis/distributions/" \
+ PALUDIS_SKIP_CONFIG="yes" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ PALUDIS_REPOSITORY_SO_DIR="$(top_builddir)/paludis/repositories" \
+ LD_LIBRARY_PATH="`echo $$LD_LIBRARY_PATH: | sed -e 's,^:,,'`` \
+ $(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/repositories/e/`:` \
+ $(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/repositories/e/.libs/`" \
+ bash $(top_srcdir)/test/run_test.sh
+
+portage_repository_params-sr.hh : portage_repository_params.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/portage_repository_params.sr > $@
+
+portage_repository_params-sr.cc : portage_repository_params.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/portage_repository_params.sr > $@
+
+vdb_merger-sr.hh : vdb_merger.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/vdb_merger.sr > $@
+
+vdb_merger-sr.cc : vdb_merger.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/vdb_merger.sr > $@
+
+vdb_unmerger-sr.hh : vdb_unmerger.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/vdb_unmerger.sr > $@
+
+vdb_unmerger-sr.cc : vdb_unmerger.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/vdb_unmerger.sr > $@
+
+ebuild-sr.hh : ebuild.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/ebuild.sr > $@
+
+ebuild-sr.cc : ebuild.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/ebuild.sr > $@
+
+ebin-sr.hh : ebin.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/ebin.sr > $@
+
+ebin-sr.cc : ebin.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/ebin.sr > $@
+
+glsa-sr.hh : glsa.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/glsa.sr > $@
+
+glsa-sr.cc : glsa.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/glsa.sr > $@
+
+vdb_repository-sr.hh : vdb_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/vdb_repository.sr > $@
+
+vdb_repository-sr.cc : vdb_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/vdb_repository.sr > $@
+
+ebin-se.hh : ebin.se $(top_srcdir)/misc/make_se.bash
+ if ! $(top_srcdir)/misc/make_se.bash --header $(srcdir)/ebin.se > $@ ; then rm -f $@ ; exit 1 ; fi
+
+ebin-se.cc : ebin.se $(top_srcdir)/misc/make_se.bash
+ if ! $(top_srcdir)/misc/make_se.bash --source $(srcdir)/ebin.se > $@ ; then rm -f $@ ; exit 1 ; fi
+
+
+libpaludiserepositoryxmlthings_la_SOURCES = xml_things.cc xml_things.hh
+libpaludiserepositoryxmlthings_la_CXXFLAGS = $(AM_CXXFLAGS) @LIBXML2DEPS_CFLAGS@
+
+libpaludiserepositoryxmlthings_la_LIBADD = @LIBXML2DEPS_LIBS@ \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/libpaludis.la
+
+libpaludiserepositoryxmlthings_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+
+if ENABLE_GLSA
+
+GLSA_TESTS = xml_things_TEST
+xml_things_TEST_SOURCES = xml_things_TEST.cc
+
+xml_things_TEST_LDADD = \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/test/libtest.a \
+ libpaludiserepository.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
+ $(top_builddir)/test/libtest.a \
+ $(DYNAMIC_LD_LIBS)
+
+endif
+
+TESTS = portage_repository_TEST vdb_unmerger_TEST $(GLSA_TESTS) portage_repository_sets_TEST
+check_PROGRAMS = $(TESTS)
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
diff --git a/paludis/repositories/e/e_key.cc b/paludis/repositories/e/e_key.cc
new file mode 100644
index 000000000..7989ed142
--- /dev/null
+++ b/paludis/repositories/e/e_key.cc
@@ -0,0 +1,581 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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/e/e_key.hh>
+#include <paludis/repositories/e/ebuild_id.hh>
+
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/log.hh>
+
+#include <paludis/portage_dep_parser.hh>
+#include <paludis/eapi.hh>
+#include <paludis/contents.hh>
+
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+
+#include <list>
+#include <vector>
+#include <fstream>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+EStringKey::EStringKey(const tr1::shared_ptr<const PackageID> &,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataStringKey(r, h, t),
+ _value(v)
+{
+}
+
+EStringKey::~EStringKey()
+{
+}
+
+const std::string
+EStringKey::value() const
+{
+ return _value;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EDependenciesKey>
+ {
+ const tr1::shared_ptr<const PackageID> id;
+ const std::string string_value;
+ mutable tr1::shared_ptr<const DependencySpecTree::ConstItem> value;
+
+ Implementation(const tr1::shared_ptr<const PackageID> & i, const std::string & v) :
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+EDependenciesKey::EDependenciesKey(const tr1::shared_ptr<const PackageID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataSpecTreeKey<DependencySpecTree>(r, h, t),
+ PrivateImplementationPattern<EDependenciesKey>(new Implementation<EDependenciesKey>(id, v)),
+ _imp(PrivateImplementationPattern<EDependenciesKey>::_imp.get())
+{
+}
+
+EDependenciesKey::~EDependenciesKey()
+{
+}
+
+const tr1::shared_ptr<const DependencySpecTree::ConstItem>
+EDependenciesKey::value() const
+{
+ if (_imp->value)
+ return _imp->value;
+
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ _imp->value = PortageDepParser::parse_depend(_imp->string_value, *_imp->id->eapi());
+ return _imp->value;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<ELicenseKey>
+ {
+ const tr1::shared_ptr<const PackageID> id;
+ const std::string string_value;
+ mutable tr1::shared_ptr<const LicenseSpecTree::ConstItem> value;
+
+ Implementation(const tr1::shared_ptr<const PackageID> & i, const std::string & v) :
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+ELicenseKey::ELicenseKey(const tr1::shared_ptr<const PackageID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataSpecTreeKey<LicenseSpecTree>(r, h, t),
+ PrivateImplementationPattern<ELicenseKey>(new Implementation<ELicenseKey>(id, v)),
+ _imp(PrivateImplementationPattern<ELicenseKey>::_imp.get())
+{
+}
+
+ELicenseKey::~ELicenseKey()
+{
+}
+
+const tr1::shared_ptr<const LicenseSpecTree::ConstItem>
+ELicenseKey::value() const
+{
+ if (_imp->value)
+ return _imp->value;
+
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ _imp->value = PortageDepParser::parse_license(_imp->string_value, *_imp->id->eapi());
+ return _imp->value;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EURIKey>
+ {
+ const tr1::shared_ptr<const PackageID> id;
+ const std::string string_value;
+ mutable tr1::shared_ptr<const URISpecTree::ConstItem> value;
+
+ Implementation(const tr1::shared_ptr<const PackageID> & i, const std::string & v) :
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+EURIKey::EURIKey(const tr1::shared_ptr<const PackageID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataSpecTreeKey<URISpecTree>(r, h, t),
+ PrivateImplementationPattern<EURIKey>(new Implementation<EURIKey>(id, v)),
+ _imp(PrivateImplementationPattern<EURIKey>::_imp.get())
+{
+}
+
+EURIKey::~EURIKey()
+{
+}
+
+const tr1::shared_ptr<const URISpecTree::ConstItem>
+EURIKey::value() const
+{
+ if (_imp->value)
+ return _imp->value;
+
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ _imp->value = PortageDepParser::parse_uri(_imp->string_value, *_imp->id->eapi());
+ return _imp->value;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<ERestrictKey>
+ {
+ const tr1::shared_ptr<const PackageID> id;
+ const std::string string_value;
+ mutable tr1::shared_ptr<const RestrictSpecTree::ConstItem> value;
+
+ Implementation(const tr1::shared_ptr<const PackageID> & i, const std::string & v) :
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+ERestrictKey::ERestrictKey(const tr1::shared_ptr<const PackageID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataSpecTreeKey<RestrictSpecTree>(r, h, t),
+ PrivateImplementationPattern<ERestrictKey>(new Implementation<ERestrictKey>(id, v)),
+ _imp(PrivateImplementationPattern<ERestrictKey>::_imp.get())
+{
+}
+
+ERestrictKey::~ERestrictKey()
+{
+}
+
+const tr1::shared_ptr<const RestrictSpecTree::ConstItem>
+ERestrictKey::value() const
+{
+ if (_imp->value)
+ return _imp->value;
+
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ _imp->value = PortageDepParser::parse_restrict(_imp->string_value, *_imp->id->eapi());
+ return _imp->value;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EProvideKey>
+ {
+ const tr1::shared_ptr<const PackageID> id;
+ const std::string string_value;
+ mutable tr1::shared_ptr<const ProvideSpecTree::ConstItem> value;
+
+ Implementation(const tr1::shared_ptr<const PackageID> & i, const std::string & v) :
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+EProvideKey::EProvideKey(const tr1::shared_ptr<const PackageID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataSpecTreeKey<ProvideSpecTree>(r, h, t),
+ PrivateImplementationPattern<EProvideKey>(new Implementation<EProvideKey>(id, v)),
+ _imp(PrivateImplementationPattern<EProvideKey>::_imp.get())
+{
+}
+
+EProvideKey::~EProvideKey()
+{
+}
+
+const tr1::shared_ptr<const ProvideSpecTree::ConstItem>
+EProvideKey::value() const
+{
+ if (_imp->value)
+ return _imp->value;
+
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ _imp->value = PortageDepParser::parse_provide(_imp->string_value, *_imp->id->eapi());
+ return _imp->value;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EIUseKey>
+ {
+ const tr1::shared_ptr<const PackageID> id;
+ const std::string string_value;
+ mutable tr1::shared_ptr<IUseFlagCollection> value;
+
+ Implementation(const tr1::shared_ptr<const PackageID> & i, const std::string & v) :
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+EIUseKey::EIUseKey(const tr1::shared_ptr<const PackageID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataCollectionKey<IUseFlagCollection>(r, h, t),
+ PrivateImplementationPattern<EIUseKey>(new Implementation<EIUseKey>(id, v)),
+ _imp(PrivateImplementationPattern<EIUseKey>::_imp.get())
+{
+}
+
+EIUseKey::~EIUseKey()
+{
+}
+
+const tr1::shared_ptr<const IUseFlagCollection>
+EIUseKey::value() const
+{
+ if (_imp->value)
+ return _imp->value;
+
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ _imp->value.reset(new IUseFlagCollection::Concrete);
+ std::list<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(_imp->string_value, std::back_inserter(tokens));
+ for (std::list<std::string>::const_iterator t(tokens.begin()), t_end(tokens.end()) ;
+ t != t_end ; ++t)
+ _imp->value->insert(IUseFlag(*t, _imp->id->eapi()->supported->iuse_flag_parse_mode));
+
+ return _imp->value;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EKeywordsKey>
+ {
+ const tr1::shared_ptr<const PackageID> id;
+ const std::string string_value;
+ mutable tr1::shared_ptr<KeywordNameCollection> value;
+
+ Implementation(const tr1::shared_ptr<const PackageID> & i, const std::string & v) :
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+EKeywordsKey::EKeywordsKey(const tr1::shared_ptr<const PackageID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataCollectionKey<KeywordNameCollection>(r, h, t),
+ PrivateImplementationPattern<EKeywordsKey>(new Implementation<EKeywordsKey>(id, v)),
+ _imp(PrivateImplementationPattern<EKeywordsKey>::_imp.get())
+{
+}
+
+EKeywordsKey::~EKeywordsKey()
+{
+}
+
+const tr1::shared_ptr<const KeywordNameCollection>
+EKeywordsKey::value() const
+{
+ if (_imp->value)
+ return _imp->value;
+
+ _imp->value.reset(new KeywordNameCollection::Concrete);
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ WhitespaceTokeniser::get_instance()->tokenise(_imp->string_value, create_inserter<KeywordName>(_imp->value->inserter()));
+ return _imp->value;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EUseKey>
+ {
+ const tr1::shared_ptr<const PackageID> id;
+ const std::string string_value;
+ mutable tr1::shared_ptr<UseFlagNameCollection> value;
+
+ Implementation(const tr1::shared_ptr<const PackageID> & i, const std::string & v) :
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+EUseKey::EUseKey(const tr1::shared_ptr<const PackageID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataCollectionKey<UseFlagNameCollection>(r, h, t),
+ PrivateImplementationPattern<EUseKey>(new Implementation<EUseKey>(id, v)),
+ _imp(PrivateImplementationPattern<EUseKey>::_imp.get())
+{
+}
+
+EUseKey::~EUseKey()
+{
+}
+
+const tr1::shared_ptr<const UseFlagNameCollection>
+EUseKey::value() const
+{
+ if (_imp->value)
+ return _imp->value;
+
+ _imp->value.reset(new UseFlagNameCollection::Concrete);
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ std::list<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(_imp->string_value, std::back_inserter(tokens));
+ for (std::list<std::string>::const_iterator t(tokens.begin()), t_end(tokens.end()) ;
+ t != t_end ; ++t)
+ if ('-' != t->at(0))
+ _imp->value->insert(UseFlagName(*t));
+ return _imp->value;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EInheritedKey>
+ {
+ const tr1::shared_ptr<const PackageID> id;
+ const std::string string_value;
+ mutable tr1::shared_ptr<InheritedCollection> value;
+
+ Implementation(const tr1::shared_ptr<const PackageID> & i, const std::string & v) :
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+EInheritedKey::EInheritedKey(const tr1::shared_ptr<const PackageID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataCollectionKey<InheritedCollection>(r, h, t),
+ PrivateImplementationPattern<EInheritedKey>(new Implementation<EInheritedKey>(id, v)),
+ _imp(PrivateImplementationPattern<EInheritedKey>::_imp.get())
+{
+}
+
+EInheritedKey::~EInheritedKey()
+{
+}
+
+const tr1::shared_ptr<const InheritedCollection>
+EInheritedKey::value() const
+{
+ if (_imp->value)
+ return _imp->value;
+
+ _imp->value.reset(new InheritedCollection::Concrete);
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ WhitespaceTokeniser::get_instance()->tokenise(_imp->string_value, _imp->value->inserter());
+ return _imp->value;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EContentsKey>
+ {
+ const tr1::shared_ptr<const PackageID> id;
+ const FSEntry filename;
+ mutable tr1::shared_ptr<Contents> value;
+
+ Implementation(const tr1::shared_ptr<const PackageID> & i, const FSEntry & v) :
+ id(i),
+ filename(v)
+ {
+ }
+ };
+}
+
+EContentsKey::EContentsKey(const tr1::shared_ptr<const PackageID> & id,
+ const std::string & r, const std::string & h, const FSEntry & v, const MetadataKeyType t) :
+ MetadataContentsKey(r, h, t),
+ PrivateImplementationPattern<EContentsKey>(new Implementation<EContentsKey>(id, v)),
+ _imp(PrivateImplementationPattern<EContentsKey>::_imp.get())
+{
+}
+
+EContentsKey::~EContentsKey()
+{
+}
+
+const tr1::shared_ptr<const Contents>
+EContentsKey::value() const
+{
+ if (_imp->value)
+ return _imp->value;
+
+ Context context("When creating contents for VDB key '" + stringify(*_imp->id) + "' from '" + stringify(_imp->filename) + "':");
+
+ _imp->value.reset(new Contents);
+
+ FSEntry f(_imp->filename);
+ if (! f.is_regular_file_or_symlink_to_regular_file())
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "CONTENTS lookup failed for request for '" <<
+ *_imp->id << "' using '" << _imp->filename << "'";
+ return _imp->value;
+ }
+
+ std::ifstream ff(stringify(f).c_str());
+ if (! ff)
+ throw ConfigurationError("Could not read '" + stringify(f) + "'");
+
+ std::string line;
+ unsigned line_number(0);
+ while (std::getline(ff, line))
+ {
+ ++line_number;
+
+ std::vector<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(line, std::back_inserter(tokens));
+ if (tokens.empty())
+ continue;
+
+ if (tokens.size() < 2)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context) << "CONTENTS has broken line " <<
+ line_number << ", skipping";
+ continue;
+ }
+
+ if ("obj" == tokens.at(0))
+ _imp->value->add(tr1::shared_ptr<ContentsEntry>(new ContentsFileEntry(tokens.at(1))));
+ else if ("dir" == tokens.at(0))
+ _imp->value->add(tr1::shared_ptr<ContentsEntry>(new ContentsDirEntry(tokens.at(1))));
+ else if ("misc" == tokens.at(0))
+ _imp->value->add(tr1::shared_ptr<ContentsEntry>(new ContentsMiscEntry(tokens.at(1))));
+ else if ("fif" == tokens.at(0))
+ _imp->value->add(tr1::shared_ptr<ContentsEntry>(new ContentsFifoEntry(tokens.at(1))));
+ else if ("dev" == tokens.at(0))
+ _imp->value->add(tr1::shared_ptr<ContentsEntry>(new ContentsDevEntry(tokens.at(1))));
+ else if ("sym" == tokens.at(0))
+ {
+ if (tokens.size() < 4)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context) << "CONTENTS has broken sym line " <<
+ line_number << ", skipping";
+ continue;
+ }
+
+ _imp->value->add(tr1::shared_ptr<ContentsEntry>(new ContentsSymEntry(tokens.at(1), tokens.at(3))));
+ }
+ }
+
+ return _imp->value;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<ECTimeKey>
+ {
+ const tr1::shared_ptr<const PackageID> id;
+ const FSEntry filename;
+ mutable tr1::shared_ptr<time_t> value;
+
+ Implementation(const tr1::shared_ptr<const PackageID> & i, const FSEntry & v) :
+ id(i),
+ filename(v)
+ {
+ }
+ };
+}
+
+ECTimeKey::ECTimeKey(const tr1::shared_ptr<const PackageID> & id,
+ const std::string & r, const std::string & h, const FSEntry & v, const MetadataKeyType t) :
+ MetadataTimeKey(r, h, t),
+ PrivateImplementationPattern<ECTimeKey>(new Implementation<ECTimeKey>(id, v)),
+ _imp(PrivateImplementationPattern<ECTimeKey>::_imp.get())
+{
+}
+
+ECTimeKey::~ECTimeKey()
+{
+}
+
+const time_t
+ECTimeKey::value() const
+{
+ if (_imp->value)
+ return *_imp->value;
+
+ _imp->value.reset(new time_t(0));
+
+ try
+ {
+ *_imp->value = _imp->filename.ctime();
+ }
+ catch (const FSError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Couldn't get ctime for '"
+ << _imp->filename << "' for ID '" << *_imp->id << "' due to exception '" << e.message()
+ << "' (" << e.what() << ")";
+ }
+
+ return *_imp->value;
+}
+
diff --git a/paludis/repositories/e/e_key.hh b/paludis/repositories/e/e_key.hh
new file mode 100644
index 000000000..bdcf17ea7
--- /dev/null
+++ b/paludis/repositories/e/e_key.hh
@@ -0,0 +1,225 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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_GENTOO_E_KEY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GENTOO_E_KEY_HH 1
+
+#include <paludis/metadata_key.hh>
+#include <paludis/util/fs_entry-fwd.hh>
+
+namespace paludis
+{
+ class PackageID;
+
+ namespace erepository
+ {
+ class EStringKey :
+ public MetadataStringKey
+ {
+ private:
+ const std::string _value;
+
+ public:
+ EStringKey(const tr1::shared_ptr<const PackageID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~EStringKey();
+
+ virtual const std::string value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EDependenciesKey :
+ public MetadataSpecTreeKey<DependencySpecTree>,
+ private PrivateImplementationPattern<EDependenciesKey>
+ {
+ private:
+ Implementation<EDependenciesKey> * const _imp;
+
+ public:
+ EDependenciesKey(const tr1::shared_ptr<const PackageID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~EDependenciesKey();
+
+ virtual const tr1::shared_ptr<const DependencySpecTree::ConstItem> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EURIKey :
+ public MetadataSpecTreeKey<URISpecTree>,
+ private PrivateImplementationPattern<EURIKey>
+ {
+ private:
+ Implementation<EURIKey> * const _imp;
+
+ public:
+ EURIKey(const tr1::shared_ptr<const PackageID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~EURIKey();
+
+ virtual const tr1::shared_ptr<const URISpecTree::ConstItem> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class ERestrictKey :
+ public MetadataSpecTreeKey<RestrictSpecTree>,
+ private PrivateImplementationPattern<ERestrictKey>
+ {
+ private:
+ Implementation<ERestrictKey> * const _imp;
+
+ public:
+ ERestrictKey(const tr1::shared_ptr<const PackageID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~ERestrictKey();
+
+ virtual const tr1::shared_ptr<const RestrictSpecTree::ConstItem> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EProvideKey :
+ public MetadataSpecTreeKey<ProvideSpecTree>,
+ private PrivateImplementationPattern<EProvideKey>
+ {
+ private:
+ Implementation<EProvideKey> * const _imp;
+
+ public:
+ EProvideKey(const tr1::shared_ptr<const PackageID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~EProvideKey();
+
+ virtual const tr1::shared_ptr<const ProvideSpecTree::ConstItem> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class ELicenseKey :
+ public MetadataSpecTreeKey<LicenseSpecTree>,
+ private PrivateImplementationPattern<ELicenseKey>
+ {
+ private:
+ Implementation<ELicenseKey> * const _imp;
+
+ public:
+ ELicenseKey(const tr1::shared_ptr<const PackageID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~ELicenseKey();
+
+ virtual const tr1::shared_ptr<const LicenseSpecTree::ConstItem> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EIUseKey :
+ public MetadataCollectionKey<IUseFlagCollection>,
+ private PrivateImplementationPattern<EIUseKey>
+ {
+ private:
+ Implementation<EIUseKey> * const _imp;
+
+ public:
+ EIUseKey(const tr1::shared_ptr<const PackageID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~EIUseKey();
+
+ const tr1::shared_ptr<const IUseFlagCollection> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EKeywordsKey :
+ public MetadataCollectionKey<KeywordNameCollection>,
+ private PrivateImplementationPattern<EKeywordsKey>
+ {
+ private:
+ Implementation<EKeywordsKey> * const _imp;
+
+ public:
+ EKeywordsKey(const tr1::shared_ptr<const PackageID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~EKeywordsKey();
+
+ const tr1::shared_ptr<const KeywordNameCollection> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EUseKey :
+ public MetadataCollectionKey<UseFlagNameCollection>,
+ private PrivateImplementationPattern<EUseKey>
+ {
+ private:
+ Implementation<EUseKey> * const _imp;
+
+ public:
+ EUseKey(const tr1::shared_ptr<const PackageID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~EUseKey();
+
+ const tr1::shared_ptr<const UseFlagNameCollection> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EInheritedKey :
+ public MetadataCollectionKey<InheritedCollection>,
+ private PrivateImplementationPattern<EInheritedKey>
+ {
+ private:
+ Implementation<EInheritedKey> * const _imp;
+
+ public:
+ EInheritedKey(const tr1::shared_ptr<const PackageID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~EInheritedKey();
+
+ const tr1::shared_ptr<const InheritedCollection> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EContentsKey :
+ public MetadataContentsKey,
+ private PrivateImplementationPattern<EContentsKey>
+ {
+ private:
+ Implementation<EContentsKey> * const _imp;
+
+ public:
+ EContentsKey(const tr1::shared_ptr<const PackageID> &,
+ const std::string &, const std::string &, const FSEntry &, const MetadataKeyType);
+ ~EContentsKey();
+
+ const tr1::shared_ptr<const Contents> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class ECTimeKey :
+ public MetadataTimeKey,
+ private PrivateImplementationPattern<ECTimeKey>
+ {
+ private:
+ Implementation<ECTimeKey> * const _imp;
+
+ public:
+ ECTimeKey(const tr1::shared_ptr<const PackageID> &,
+ const std::string &, const std::string &, const FSEntry &, const MetadataKeyType);
+ ~ECTimeKey();
+
+ const time_t value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/e/eapi_phase.cc b/paludis/repositories/e/eapi_phase.cc
new file mode 100644
index 000000000..70dafc200
--- /dev/null
+++ b/paludis/repositories/e/eapi_phase.cc
@@ -0,0 +1,117 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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 "eapi_phase.hh"
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/eapi.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+#include <set>
+#include <algorithm>
+#include <list>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EAPIPhase>
+ {
+ std::set<std::string> options;
+ std::list<std::string> commands;
+ };
+
+ template <>
+ struct Implementation<EAPIPhases>
+ {
+ std::list<tr1::shared_ptr<const EAPIPhase> > phases;
+ };
+}
+
+EAPIPhase::EAPIPhase(const std::string & s) :
+ PrivateImplementationPattern<EAPIPhase>(new Implementation<EAPIPhase>)
+{
+ Context c("When parsing EAPI phase '" + s + "'");
+
+ std::list<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(s, std::back_inserter(tokens));
+
+ std::list<std::string>::iterator t(std::find(tokens.begin(), tokens.end(), ":"));
+ if (t == tokens.end())
+ throw EAPIConfigurationError("EAPI phase '" + s + "' contains no ':'");
+
+ std::copy(tokens.begin(), t, std::inserter(_imp->options, _imp->options.begin()));
+ std::copy(next(t), tokens.end(), std::back_inserter(_imp->commands));
+}
+
+EAPIPhase::~EAPIPhase()
+{
+}
+
+bool
+EAPIPhase::option(const std::string & s) const
+{
+ return _imp->options.count(s);
+}
+
+EAPIPhase::Iterator
+EAPIPhase::begin_commands() const
+{
+ return Iterator(_imp->commands.begin());
+}
+
+EAPIPhase::Iterator
+EAPIPhase::end_commands() const
+{
+ return Iterator(_imp->commands.end());
+}
+
+EAPIPhases::EAPIPhases(const std::string & s) :
+ PrivateImplementationPattern<EAPIPhases>(new Implementation<EAPIPhases>)
+{
+ Context c("When parsing EAPI phases '" + s + "'");
+
+ std::list<std::string> tokens;
+ Tokeniser<delim_kind::AnyOfTag, delim_mode::DelimiterTag> tok(";");
+ tok.tokenise(s, std::back_inserter(tokens));
+ for (std::list<std::string>::const_iterator t(tokens.begin()), t_end(tokens.end()) ;
+ t != t_end ; ++t)
+ _imp->phases.push_back(make_shared_ptr(new EAPIPhase(*t)));
+}
+
+EAPIPhases::~EAPIPhases()
+{
+}
+
+EAPIPhases::Iterator
+EAPIPhases::begin_phases() const
+{
+ return Iterator(indirect_iterator(_imp->phases.begin()));
+}
+
+EAPIPhases::Iterator
+EAPIPhases::end_phases() const
+{
+ return Iterator(indirect_iterator(_imp->phases.end()));
+}
+
diff --git a/paludis/repositories/e/eapi_phase.hh b/paludis/repositories/e/eapi_phase.hh
new file mode 100644
index 000000000..10e4a6da1
--- /dev/null
+++ b/paludis/repositories/e/eapi_phase.hh
@@ -0,0 +1,93 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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_GENTOO_EAPI_PHASE_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GENTOO_EAPI_PHASE_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <libwrapiter/libwrapiter_forward_iterator-fwd.hh>
+#include <string>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ /**
+ * Holds a parsed EAPI phase.
+ *
+ * \nosubgrouping
+ * \ingroup grpportagerepository
+ * \ingroup grpeapi
+ */
+ class EAPIPhase :
+ private PrivateImplementationPattern<EAPIPhase>
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ explicit EAPIPhase(const std::string &);
+ ~EAPIPhase();
+
+ ///\}
+
+ ///\name Information about the phase
+ ///\{
+
+ bool option(const std::string &) const;
+
+ typedef libwrapiter::ForwardIterator<EAPIPhase, const std::string> Iterator;
+ Iterator begin_commands() const;
+ Iterator end_commands() const;
+
+ ///\}
+ };
+
+ /**
+ * Holds parsed EAPI phases.
+ *
+ * \nosubgrouping
+ * \ingroup grpportagerepository
+ * \ingroup grpeapi
+ */
+ class EAPIPhases :
+ private PrivateImplementationPattern<EAPIPhases>
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ explicit EAPIPhases(const std::string &);
+ ~EAPIPhases();
+
+ ///\}
+
+ ///\name Information about the phases
+ ///\{
+
+ typedef libwrapiter::ForwardIterator<EAPIPhases, const EAPIPhase> Iterator;
+ Iterator begin_phases() const;
+ Iterator end_phases() const;
+
+ ///\}
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/e/ebin.cc b/paludis/repositories/e/ebin.cc
new file mode 100644
index 000000000..488356645
--- /dev/null
+++ b/paludis/repositories/e/ebin.cc
@@ -0,0 +1,301 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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 "ebin.hh"
+#include <paludis/portage_dep_parser.hh>
+#include <paludis/environment.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/eapi.hh>
+#include <paludis/about.hh>
+#include <paludis/package_id.hh>
+#include <paludis/metadata_key.hh>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+#include <unistd.h>
+
+using namespace paludis;
+
+#include <paludis/repositories/e/ebin-se.cc>
+#include <paludis/repositories/e/ebin-sr.cc>
+
+EbinCommand::EbinCommand(const EbinCommandParams & p) :
+ params(p)
+{
+}
+
+EbinCommand::~EbinCommand()
+{
+}
+
+bool
+EbinCommand::success()
+{
+ return true;
+}
+
+bool
+EbinCommand::use_sandbox() const
+{
+ return true;
+}
+
+bool
+EbinCommand::do_run_command(const Command & cmd)
+{
+ return 0 == run_command(cmd);
+}
+
+bool
+EbinCommand::operator() ()
+{
+ Command cmd(getenv_with_default("PALUDIS_EBUILD_DIR", LIBEXECDIR "/paludis") +
+ "/ebuild.bash '-' " + commands());
+
+ if (use_sandbox())
+ cmd.with_sandbox();
+
+ tr1::shared_ptr<const FSEntryCollection> syncers_dirs(params.environment->syncers_dirs());
+ tr1::shared_ptr<const FSEntryCollection> bashrc_files(params.environment->bashrc_files());
+ tr1::shared_ptr<const FSEntryCollection> fetchers_dirs(params.environment->fetchers_dirs());
+ tr1::shared_ptr<const FSEntryCollection> hook_dirs(params.environment->hook_dirs());
+
+ cmd = extend_command(cmd
+ .with_setenv("P", stringify(params.package_id->name().package) + "-" +
+ stringify(params.package_id->version().remove_revision()))
+ .with_setenv("PV", stringify(params.package_id->version().remove_revision()))
+ .with_setenv("PR", stringify(params.package_id->version().revision_only()))
+ .with_setenv("PN", stringify(params.package_id->name().package))
+ .with_setenv("PVR", stringify(params.package_id->version()))
+ .with_setenv("PF", stringify(params.package_id->name().package) + "-" +
+ stringify(params.package_id->version()))
+ .with_setenv("CATEGORY", stringify(params.package_id->name().category))
+ .with_setenv("REPOSITORY", stringify(params.package_id->repository()->name()))
+ .with_setenv("PORTDIR", stringify(params.portdir))
+ .with_setenv("DISTDIR", stringify(params.distdir))
+ .with_setenv("PKGMANAGER", PALUDIS_PACKAGE "-" + stringify(PALUDIS_VERSION_MAJOR) + "." +
+ stringify(PALUDIS_VERSION_MINOR) + "." +
+ stringify(PALUDIS_VERSION_MICRO) +
+ (std::string(PALUDIS_SUBVERSION_REVISION).empty() ?
+ std::string("") : "-r" + std::string(PALUDIS_SUBVERSION_REVISION)))
+ .with_setenv("PALUDIS_TMPDIR", stringify(params.buildroot))
+ .with_setenv("PALUDIS_CONFIG_DIR", SYSCONFDIR "/paludis/")
+ .with_setenv("PALUDIS_BASHRC_FILES", join(bashrc_files->begin(), bashrc_files->end(), " "))
+ .with_setenv("PALUDIS_HOOK_DIRS", join(hook_dirs->begin(), hook_dirs->end(), " "))
+ .with_setenv("PALUDIS_FETCHERS_DIRS", join(fetchers_dirs->begin(), fetchers_dirs->end(), " "))
+ .with_setenv("PALUDIS_SYNCERS_DIRS", join(syncers_dirs->begin(), syncers_dirs->end(), " "))
+ .with_setenv("PALUDIS_COMMAND", params.environment->paludis_command())
+ .with_setenv("PALUDIS_REDUCED_GID", stringify(params.environment->reduced_gid()))
+ .with_setenv("PALUDIS_REDUCED_UID", stringify(params.environment->reduced_uid()))
+ .with_setenv("KV", kernel_version())
+ .with_setenv("PALUDIS_EBUILD_LOG_LEVEL", stringify(Log::get_instance()->log_level()))
+ .with_setenv("PALUDIS_EBUILD_DIR", getenv_with_default("PALUDIS_EBUILD_DIR", LIBEXECDIR "/paludis")));
+
+ if (do_run_command(add_portage_vars(cmd)))
+ return success();
+ else
+ return failure();
+}
+
+Command
+EbinCommand::add_portage_vars(const Command & cmd) const
+{
+ return Command(cmd)
+ .with_setenv("PORTAGE_BASHRC", "/dev/null")
+ .with_setenv("PORTAGE_BUILDDIR", stringify(params.buildroot) + "/" +
+ stringify(params.package_id->name().category) + "/" +
+ stringify(params.package_id->name().package) + "-" +
+ stringify(params.package_id->version()))
+ .with_setenv("PORTAGE_CALLER", params.environment->paludis_command())
+ .with_setenv("PORTAGE_GID", "0")
+ .with_setenv("PORTAGE_INST_GID", "0")
+ .with_setenv("PORTAGE_INST_UID", "0")
+ .with_setenv("PORTAGE_MASTER_PID", stringify(::getpid()))
+ .with_setenv("PORTAGE_NICENCESS", stringify(::getpriority(PRIO_PROCESS, 0)))
+ .with_setenv("PORTAGE_TMPDIR", stringify(params.buildroot))
+ .with_setenv("PORTAGE_TMPFS", "/dev/shm")
+ .with_setenv("PORTAGE_WORKDIR_MODE", "0700");
+}
+
+std::string
+EbinFetchCommand::commands() const
+{
+ return "fetchbin";
+}
+
+bool
+EbinFetchCommand::failure()
+{
+ throw PackageFetchActionError("Fetch failed for '" + stringify(*params.package_id) + "'");
+}
+
+Command
+EbinFetchCommand::extend_command(const Command & cmd)
+{
+ Command result(Command(cmd)
+ .with_setenv("B", fetch_params.b)
+ .with_setenv("FLAT_BIN_URI", fetch_params.flat_bin_uri)
+ .with_setenv("ROOT", fetch_params.root)
+ .with_setenv("PALUDIS_USE_SAFE_RESUME", fetch_params.safe_resume ? "oohyesplease" : "")
+ .with_setenv("ROOT", fetch_params.root)
+ .with_setenv("PALUDIS_USE_SAFE_RESUME", fetch_params.safe_resume ? "oohyesplease" : ""));
+
+ if (fetch_params.userpriv)
+ result.with_uid_gid(params.environment->reduced_uid(), params.environment->reduced_gid());
+
+ return result;
+}
+
+EbinFetchCommand::EbinFetchCommand(const EbinCommandParams & p, const EbinFetchCommandParams & f) :
+ EbinCommand(p),
+ fetch_params(f)
+{
+}
+
+std::string
+EbinInstallCommand::commands() const
+{
+ switch (install_params.phase)
+ {
+ case ebin_ip_prepare:
+ return "prepare";
+
+ case ebin_ip_initbinenv:
+ return "initbin saveenv";
+
+ case ebin_ip_setup:
+ return "loadenv setup saveenv";
+
+ case ebin_ip_unpackbin:
+ return "loadenv unpackbin saveenv";
+
+ case ebin_ip_preinstall:
+ return "loadenv strip preinst saveenv";
+
+ case ebin_ip_postinstall:
+ return "loadenv postinst saveenv";
+
+ case ebin_ip_tidyup:
+ return "tidyup";
+
+ case last_ebin_ip:
+ ;
+ }
+
+ throw InternalError(PALUDIS_HERE, "Bad phase");
+}
+
+bool
+EbinInstallCommand::failure()
+{
+ throw PackageInstallActionError("Install failed for '" + stringify(*params.package_id) + "'");
+}
+
+Command
+EbinInstallCommand::extend_command(const Command & cmd)
+{
+ std::string debug_build;
+ do
+ {
+ switch (install_params.debug_build)
+ {
+ case ido_none:
+ debug_build = "none";
+ continue;
+
+ case ido_split:
+ debug_build = "split";
+ continue;
+
+ case ido_internal:
+ debug_build = "internal";
+ continue;
+ }
+
+ throw InternalError(PALUDIS_HERE, "Bad debug_build value");
+ }
+ while (false);
+
+ Command result(Command(cmd)
+ .with_setenv("B", install_params.b)
+ .with_setenv("ROOT", install_params.root)
+ .with_setenv("PALUDIS_LOADSAVEENV_DIR", stringify(install_params.loadsaveenv_dir))
+ .with_setenv("PALUDIS_CONFIG_PROTECT", install_params.config_protect)
+ .with_setenv("PALUDIS_CONFIG_PROTECT_MASK", install_params.config_protect_mask)
+ .with_setenv("PALUDIS_EBUILD_OVERRIDE_CONFIG_PROTECT_MASK",
+ install_params.disable_cfgpro ? "/" : "")
+ .with_setenv("PALUDIS_DEBUG_BUILD", debug_build)
+ .with_setenv("SLOT", stringify(install_params.slot)));
+
+ return result;
+}
+
+EbinInstallCommand::EbinInstallCommand(const EbinCommandParams & p, const EbinInstallCommandParams & i) :
+ EbinCommand(p),
+ install_params(i)
+{
+}
+
+EbinMergeCommand::EbinMergeCommand(const EbinCommandParams & p, const EbinMergeCommandParams & m) :
+ params(p),
+ merge_params(m)
+{
+}
+
+void
+EbinMergeCommand::operator() ()
+{
+ std::string tar(strip_trailing_string(stringify(merge_params.pkg_file_name), ".bz2"));
+
+ Command build_tarball(Command("tar pcvf '" + stringify(tar) + "' ./")
+ .with_chdir(merge_params.image)
+ .with_echo_to_stderr());
+
+ if (0 != run_command(build_tarball))
+ throw PackageInstallActionError("Error creating '" + stringify(tar) + "'");
+
+ Command create_env(Command("cp -f '" + stringify(merge_params.environment_file) + "' '.paludis-binpkg-environment'")
+ .with_chdir(merge_params.image)
+ .with_echo_to_stderr());
+
+ Command add_env_to_tarball(Command("tar rpf '" + stringify(tar) +
+ "' '.paludis-binpkg-environment'")
+ .with_chdir(merge_params.image)
+ .with_echo_to_stderr());
+
+ if (0 != run_command(create_env) || 0 != run_command(add_env_to_tarball))
+ throw PackageInstallActionError("Error adding environment to '" + tar + "'");
+
+ Command clean_env(Command("rm -f '.paludis-binpkg-environment'")
+ .with_chdir(merge_params.image)
+ .with_echo_to_stderr());
+ if (0 != run_command(clean_env))
+ Log::get_instance()->message(ll_warning, lc_context, "Cleaning environment failed");
+
+ Command compress_tarball(Command("bzip2 '" + tar + "'")
+ .with_chdir(merge_params.image)
+ .with_echo_to_stderr());
+
+ if (0 != run_command(compress_tarball))
+ throw PackageInstallActionError("Error compressing '" + tar + "'");
+}
+
diff --git a/paludis/repositories/e/ebin.hh b/paludis/repositories/e/ebin.hh
new file mode 100644
index 000000000..8247d56cc
--- /dev/null
+++ b/paludis/repositories/e/ebin.hh
@@ -0,0 +1,202 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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_PALUDIS_REPOSITORIES_GENTOO_EBIN_HH
+#define PALUDIS_GUARD_PALUDIS_PALUDIS_REPOSITORIES_GENTOO_EBIN_HH 1
+
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/collection.hh>
+#include <paludis/package_database.hh>
+#include <string>
+
+namespace paludis
+{
+ class Command;
+
+#include <paludis/repositories/e/ebin-se.hh>
+#include <paludis/repositories/e/ebin-sr.hh>
+
+ /**
+ * A command related to a .ebin file.
+ *
+ * \ingroup grpebininterface
+ * \nosubgrouping
+ */
+ class EbinCommand :
+ private InstantiationPolicy<EbinCommand, instantiation_method::NonCopyableTag>
+ {
+ protected:
+ /**
+ * Our parameters.
+ */
+ EbinCommandParams params;
+
+ ///\name Basic operations
+ ///\{
+
+ EbinCommand(const EbinCommandParams &);
+
+ ///\}
+
+ ///\name Command options
+ ///\{
+
+ /**
+ * What commands should be run?
+ */
+ virtual std::string commands() const = 0;
+
+ /**
+ * Was our execution a success?
+ */
+ virtual bool success();
+
+ /**
+ * Should we use sandbox?
+ */
+ virtual bool use_sandbox() const;
+
+ /**
+ * Handle a failure.
+ */
+ virtual bool failure() = 0;
+
+ /**
+ * Run the command specified.
+ */
+ virtual bool do_run_command(const Command &);
+
+ /**
+ * Extend the basic command.
+ */
+ virtual Command extend_command(const Command &) = 0;
+
+ /**
+ * Add Portage emulation variables.
+ */
+ virtual Command add_portage_vars(const Command &) const;
+
+ ///\}
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ virtual ~EbinCommand();
+
+ ///\}
+
+ /**
+ * Run the command.
+ */
+ virtual bool operator() ();
+ };
+
+ /**
+ * Fetch a .ebin's bin_uri contents.
+ *
+ * \ingroup grpebininterface
+ * \nosubgrouping
+ */
+ class EbinFetchCommand :
+ public EbinCommand
+ {
+ protected:
+ /// Our parameters.
+ const EbinFetchCommandParams fetch_params;
+
+ virtual std::string commands() const;
+
+ virtual bool failure() PALUDIS_ATTRIBUTE((noreturn));
+
+ virtual Command extend_command(const Command &);
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ EbinFetchCommand(const EbinCommandParams &, const EbinFetchCommandParams &);
+
+ ///\}
+ };
+
+ /**
+ * Perform a part of a .ebin install sequence.
+ *
+ * \ingroup grpebininterface
+ * \nosubgrouping
+ */
+ class EbinInstallCommand :
+ public EbinCommand
+ {
+ protected:
+ /// Our parameters.
+ const EbinInstallCommandParams install_params;
+
+ virtual std::string commands() const;
+
+ virtual bool failure() PALUDIS_ATTRIBUTE((noreturn));
+
+ virtual Command extend_command(const Command &);
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ EbinInstallCommand(const EbinCommandParams &, const EbinInstallCommandParams &);
+
+ ///\}
+ };
+
+ /**
+ * Merge to a .ebin repository.
+ *
+ * \ingroup grpebininterface
+ * \nosubgrouping
+ */
+ class EbinMergeCommand
+ {
+ protected:
+ ///\name Parameters
+ ///\{
+
+ const EbinCommandParams params;
+ const EbinMergeCommandParams merge_params;
+
+ ///\}
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ EbinMergeCommand(const EbinCommandParams &, const EbinMergeCommandParams &);
+
+ ///\}
+
+ /**
+ * Perform the merge.
+ */
+ void operator() ();
+ };
+}
+
+#endif
+
diff --git a/paludis/repositories/e/ebin.se b/paludis/repositories/e/ebin.se
new file mode 100644
index 000000000..0bfb0796f
--- /dev/null
+++ b/paludis/repositories/e/ebin.se
@@ -0,0 +1,25 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et ft=sh :
+
+make_enum_EbinInstallCommandPhase()
+{
+ prefix ebin_ip
+
+ key ebin_ip_prepare "Prepare the working directory"
+ key ebin_ip_initbinenv "Extract and load the binary environment"
+ key ebin_ip_setup "Perform pre-unpack setup phases"
+ key ebin_ip_unpackbin "Extract the binary"
+ key ebin_ip_preinstall "Preinstall to a live system"
+ key ebin_ip_postinstall "Postinstall to a live system"
+ key ebin_ip_tidyup "Tidy up work."
+
+ doxygen_comment << "END"
+ /**
+ * Which phase of an EbinInstallCommand to run.
+ *
+ * \see EbinInstallCommand
+ * \ingroup grpportagerepository
+ */
+END
+}
+
diff --git a/paludis/repositories/e/ebin.sr b/paludis/repositories/e/ebin.sr
new file mode 100644
index 000000000..20800ef75
--- /dev/null
+++ b/paludis/repositories/e/ebin.sr
@@ -0,0 +1,89 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_EbinCommandParams()
+{
+ key environment "const Environment *"
+ key package_id "tr1::shared_ptr<const PackageID>"
+ key portdir FSEntry
+ key distdir FSEntry
+ key buildroot FSEntry
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for an EbinCommand.
+ *
+ * \see EbinCommand
+ * \ingroup grpebuildinterface
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
+make_class_EbinFetchCommandParams()
+{
+ key b std::string
+ key flat_bin_uri std::string
+ key root std::string
+ key safe_resume bool
+ key userpriv bool
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for an EbinFetchCommand.
+ *
+ * \see EbinFetchCommand
+ * \ingroup grpebuildinterface
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
+make_class_EbinInstallCommandParams()
+{
+ key b std::string
+ key root std::string
+ key disable_cfgpro bool
+ key debug_build InstallDebugOption
+ key slot SlotName
+ key phase EbinInstallCommandPhase
+ key config_protect std::string
+ key config_protect_mask std::string
+ key loadsaveenv_dir FSEntry
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for an EbinInstallCommand.
+ *
+ * \see EbinInstallCommand
+ * \ingroup grpebuildinterface
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
+make_class_EbinMergeCommandParams()
+{
+ key image FSEntry
+ key environment_file FSEntry
+ key pkg_file_name FSEntry
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for an EbinMergeCommand.
+ *
+ * \see EbinMergeCommand
+ * \ingroup grpebuildinterface
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
diff --git a/paludis/repositories/e/ebin_entries.cc b/paludis/repositories/e/ebin_entries.cc
new file mode 100644
index 000000000..6994b9505
--- /dev/null
+++ b/paludis/repositories/e/ebin_entries.cc
@@ -0,0 +1,471 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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 "ebin_entries.hh"
+#include <paludis/repositories/e/ebin.hh>
+#include <paludis/repositories/e/portage_repository.hh>
+#include <paludis/config_file.hh>
+#include <paludis/portage_dep_parser.hh>
+#include <paludis/dep_spec_flattener.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_id.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/eapi.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/dep_spec_pretty_printer.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+#include <set>
+#include <fstream>
+
+using namespace paludis;
+
+#if 0
+
+namespace paludis
+{
+ template<>
+ struct Implementation<EbinEntries>
+ {
+ const Environment * const environment;
+ PortageRepository * const portage_repository;
+ const PortageRepositoryParams params;
+
+ Implementation(const Environment * const e, PortageRepository * const p,
+ const PortageRepositoryParams & k) :
+ environment(e),
+ portage_repository(p),
+ params(k)
+ {
+ }
+ };
+}
+
+EbinEntries::EbinEntries(
+ const Environment * const e, PortageRepository * const p, const PortageRepositoryParams & k) :
+ PrivateImplementationPattern<EbinEntries>(new Implementation<EbinEntries>(e, p, k))
+{
+}
+
+EbinEntries::~EbinEntries()
+{
+}
+
+tr1::shared_ptr<VersionMetadata>
+EbinEntries::generate_version_metadata(const QualifiedPackageName & q,
+ const VersionSpec & v) const
+{
+ Context context("When generating version metadata for '" + stringify(q) + "-" + stringify(v) + "':");
+
+ tr1::shared_ptr<EbinVersionMetadata> result(new EbinVersionMetadata(SlotName("unset")));
+
+ KeyValueConfigFile f(_imp->portage_repository->layout()->package_directory(q) /
+ (stringify(q.package) + "-" + stringify(v) + ".ebin"),
+ KeyValueConfigFileOptions() + kvcfo_disallow_continuations + kvcfo_disallow_comments +
+ kvcfo_disallow_space_around_equals + kvcfo_disallow_source);
+
+ result->set_run_depend(f.get("RDEPEND"));
+ result->set_post_depend(f.get("PDEPEND"));
+ result->set_suggested_depend(f.get("SDEPEND"));
+
+ result->set_license(f.get("LICENSE"));
+
+ result->source.reset();
+ result->binary.reset();
+
+ result->slot = SlotName(f.get("SLOT"));
+ result->set_homepage(f.get("HOMEPAGE"));
+ result->description = f.get("DESCRIPTION");
+ result->eapi = EAPIData::get_instance()->eapi_from_string(f.get("EAPI"));
+
+ result->set_provide(f.get("PROVIDE"));
+ result->set_src_uri(f.get("SRC_URI"));
+ result->set_restrictions(f.get("RESTRICT"));
+ result->set_keywords(f.get("KEYWORDS"));
+ result->set_iuse(f.get("IUSE"));
+ result->set_inherited(f.get("INHERITED"));
+
+ result->set_bin_uri(f.get("BIN_URI"));
+
+ return result;
+}
+
+namespace
+{
+ FSEntry
+ get_root(tr1::shared_ptr<const DestinationsCollection> destinations)
+ {
+ if (destinations)
+ for (DestinationsCollection::Iterator d(destinations->begin()), d_end(destinations->end()) ;
+ d != d_end ; ++d)
+ if ((*d)->installed_interface)
+ return (*d)->installed_interface->root();
+
+ return FSEntry("/");
+ }
+}
+
+void
+EbinEntries::install(const tr1::shared_ptr<const PackageID> & id,
+ const InstallOptions & o, tr1::shared_ptr<const PortageRepositoryProfile>) const
+{
+ std::string binaries, flat_bin_uri;
+ {
+ std::set<std::string> already_in_binaries;
+
+ /* make B and FLAT_BIN_URI */
+ DepSpecFlattener f(_imp->params.environment, id);
+ if (id->bin_uri_key())
+ id->bin_uri_key()->value()->accept(f);
+
+ for (DepSpecFlattener::Iterator ff(f.begin()), ff_end(f.end()) ; ff != ff_end ; ++ff)
+ {
+ std::string::size_type pos((*ff)->text().rfind('/'));
+ if (std::string::npos == pos)
+ {
+ if (already_in_binaries.end() == already_in_binaries.find((*ff)->text()))
+ {
+ binaries.append((*ff)->text());
+ already_in_binaries.insert((*ff)->text());
+ }
+ }
+ else
+ {
+ if (already_in_binaries.end() == already_in_binaries.find((*ff)->text().substr(pos + 1)))
+ {
+ binaries.append((*ff)->text().substr(pos + 1));
+ already_in_binaries.insert((*ff)->text().substr(pos + 1));
+ }
+ }
+ binaries.append(" ");
+
+ /* add * mirror entries */
+ tr1::shared_ptr<const MirrorsCollection> star_mirrors(_imp->params.environment->mirrors("*"));
+ for (MirrorsCollection::Iterator m(star_mirrors->begin()), m_end(star_mirrors->end()) ; m != m_end ; ++m)
+ flat_bin_uri.append(*m + "/" + (*ff)->text().substr(pos + 1) + " ");
+
+ if (0 == (*ff)->text().compare(0, 9, "mirror://"))
+ {
+ std::string mirror((*ff)->text().substr(9));
+ std::string::size_type spos(mirror.find('/'));
+
+ if (std::string::npos == spos)
+ throw PackageInstallActionError("Can't install '" + stringify(*id) + "' since BIN_URI is broken");
+
+ tr1::shared_ptr<const MirrorsCollection> mirrors(_imp->params.environment->mirrors(mirror.substr(0, spos)));
+ if (! _imp->portage_repository->is_mirror(mirror.substr(0, spos)) &&
+ mirrors->empty())
+ throw PackageInstallActionError("Can't install '" + stringify(*id)
+ + "' since BIN_URI references unknown mirror:// '" +
+ mirror.substr(0, spos) + "'");
+
+ for (MirrorsCollection::Iterator m(mirrors->begin()), m_end(mirrors->end()) ; m != m_end ; ++m)
+ flat_bin_uri.append(*m + "/" + mirror.substr(spos + 1) + " ");
+
+ for (RepositoryMirrorsInterface::MirrorsIterator
+ m(_imp->portage_repository->begin_mirrors(mirror.substr(0, spos))),
+ m_end(_imp->portage_repository->end_mirrors(mirror.substr(0, spos))) ;
+ m != m_end ; ++m)
+ flat_bin_uri.append(m->second + "/" + mirror.substr(spos + 1) + " ");
+ }
+ else
+ flat_bin_uri.append((*ff)->text());
+ flat_bin_uri.append(" ");
+
+ /* add mirror://gentoo/ entries */
+ std::string master_mirror(strip_trailing_string(stringify(_imp->portage_repository->name()), "x-"));
+ if (_imp->portage_repository->is_mirror(master_mirror))
+ {
+ tr1::shared_ptr<const MirrorsCollection> repo_mirrors(_imp->params.environment->mirrors(master_mirror));
+ for (MirrorsCollection::Iterator m(repo_mirrors->begin()), m_end(repo_mirrors->end()) ; m != m_end ; ++m)
+ flat_bin_uri.append(*m + "/" + (*ff)->text().substr(pos + 1) + " ");
+
+ for (RepositoryMirrorsInterface::MirrorsIterator
+ m(_imp->portage_repository->begin_mirrors(master_mirror)),
+ m_end(_imp->portage_repository->end_mirrors(master_mirror)) ;
+ m != m_end ; ++m)
+ flat_bin_uri.append(m->second + "/" + (*ff)->text().substr(pos + 1) + " ");
+ }
+ }
+ }
+
+ EbinCommandParams command_params(EbinCommandParams::create()
+ .environment(_imp->params.environment)
+ .package_id(id)
+ .portdir(_imp->params.master_repository ? _imp->params.master_repository->params().location :
+ _imp->params.location)
+ .distdir(_imp->params.distdir)
+ .buildroot(_imp->params.buildroot));
+
+ bool fetch_userpriv_ok(_imp->environment->reduced_gid() != getgid());
+ if (fetch_userpriv_ok)
+ {
+ FSEntry f(_imp->params.distdir);
+ Context c("When checking permissions on '" + stringify(f) + "' for userpriv:");
+
+ if (f.exists())
+ {
+ if (f.group() != _imp->environment->reduced_gid())
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Directory '" +
+ stringify(f) + "' owned by group '" +
+ stringify(get_group_name(f.group())) + "', not '" +
+ stringify(get_group_name(_imp->environment->reduced_gid())) +
+ "', so cannot enable userpriv");
+ fetch_userpriv_ok = false;
+ }
+ else if (! f.has_permission(fs_ug_group, fs_perm_write))
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Directory '" +
+ stringify(f) + "' does not group write permission," +
+ "cannot enable userpriv");
+ fetch_userpriv_ok = false;
+ }
+ }
+ }
+
+ if (! o.destination)
+ throw PackageInstallActionError("Can't install '" + stringify(*id)
+ + "' because no destination was provided");
+
+ EbinFetchCommand fetch_cmd(command_params,
+ EbinFetchCommandParams::create()
+ .b(binaries)
+ .flat_bin_uri(flat_bin_uri)
+ .root(o.destination->installed_interface ? stringify(o.destination->installed_interface->root()) : "/")
+ .safe_resume(o.safe_resume)
+ .userpriv(false));
+
+ fetch_cmd();
+
+ if (o.fetch_only)
+ return;
+
+ EbinInstallCommandParams install_params(
+ EbinInstallCommandParams::create()
+ .b(binaries)
+ .root(o.destination->installed_interface ? stringify(o.destination->installed_interface->root()) : "/")
+ .debug_build(o.debug_build)
+ .phase(ebin_ip_prepare)
+ .disable_cfgpro(o.no_config_protect)
+ .config_protect(_imp->portage_repository->profile_variable("CONFIG_PROTECT"))
+ .config_protect_mask(_imp->portage_repository->profile_variable("CONFIG_PROTECT_MASK"))
+ .loadsaveenv_dir(_imp->params.buildroot / stringify(id->name().category) / (
+ stringify(id->name().package) + "-" + stringify(id->version())) / "temp")
+ .slot(SlotName(id->slot())));
+
+ EbinInstallCommand prepare_cmd(command_params, install_params);
+ prepare_cmd();
+
+ install_params.phase = ebin_ip_initbinenv;
+ EbinInstallCommand initbinenv_cmd(command_params, install_params);
+ initbinenv_cmd();
+
+ install_params.phase = ebin_ip_setup;
+ EbinInstallCommand setup_cmd(command_params, install_params);
+ setup_cmd();
+
+ install_params.phase = ebin_ip_unpackbin;
+ EbinInstallCommand unpackbin_cmd(command_params, install_params);
+ unpackbin_cmd();
+
+ if (! o.destination->destination_interface)
+ throw PackageInstallActionError("Can't install '" + stringify(*id)
+ + "' to destination '" + stringify(o.destination->name())
+ + "' because destination does not provide destination_interface");
+
+ if (o.destination->destination_interface->want_pre_post_phases())
+ {
+ install_params.phase = ebin_ip_preinstall;
+ install_params.root = o.destination->installed_interface ?
+ stringify(o.destination->installed_interface->root()) : "/";
+ EbinInstallCommand preinst_cmd(command_params, install_params);
+ preinst_cmd();
+ }
+
+ o.destination->destination_interface->merge(
+ MergeOptions::create()
+ .package_id(id)
+ .image_dir(_imp->params.buildroot / stringify(id->name().category) / (stringify(id->name().package) + "-"
+ + stringify(id->version())) / "image")
+ .environment_file(_imp->params.buildroot / stringify(id->name().category) / (stringify(id->name().package) + "-"
+ + stringify(id->version())) / "temp" / "loadsaveenv")
+ );
+
+ if (o.destination->destination_interface->want_pre_post_phases())
+ {
+ install_params.phase = ebin_ip_postinstall;
+ install_params.root = o.destination->installed_interface ?
+ stringify(o.destination->installed_interface->root()) : "/";
+ EbinInstallCommand postinst_cmd(command_params, install_params);
+ postinst_cmd();
+ }
+
+ install_params.phase = ebin_ip_tidyup;
+ EbinInstallCommand tidyup_cmd(command_params, install_params);
+ tidyup_cmd();
+}
+
+tr1::shared_ptr<PortageRepositoryEntries>
+EbinEntries::make_ebin_entries(
+ const Environment * const e, PortageRepository * const r, const PortageRepositoryParams & p)
+{
+ return tr1::shared_ptr<PortageRepositoryEntries>(new EbinEntries(e, r, p));
+}
+
+std::string
+EbinEntries::get_environment_variable(const tr1::shared_ptr<const PackageID> & id,
+ const std::string & var, tr1::shared_ptr<const PortageRepositoryProfile>) const
+{
+ PackageID::Iterator i(id->find(var));
+ if (id->end() != i)
+ {
+ MetadataKeyRawPrinter p;
+ i->accept(p);
+ return stringify(p);
+ }
+
+ throw EnvironmentVariableActionError("Couldn't get environment variable '" +
+ stringify(var) + "' for package '" + stringify(*id) + "'");
+}
+
+void
+EbinEntries::merge(const MergeOptions & m)
+{
+ Context context("When merging '" + stringify(*m.package_id) + "' at '" + stringify(m.image_dir)
+ + "' to ebin repository '" + stringify(_imp->portage_repository->name()) + "':");
+
+ if (! _imp->portage_repository->destination_interface->is_suitable_destination_for(m.package()))
+ throw PackageInstallActionError("Not a suitable destination for '" + stringify(*m.package()) + "'");
+
+ FSEntry ebin_dir(_imp->params.location);
+ ebin_dir /= stringify(m.package_id->name().category);
+ ebin_dir.mkdir();
+ ebin_dir /= stringify(m.package_id->name().package);
+ ebin_dir.mkdir();
+
+ FSEntry ebin_file_name(ebin_dir / (stringify(m.package_id->name.package()) + "-" +
+ stringify(m.package_id->version()) + ".ebin.incomplete"));
+ std::ofstream ebin_file(stringify(ebin_file_name).c_str());
+ if (! ebin_file)
+ throw PackageInstallActionError("Cannot write to '" + stringify(ebin_file_name) + "'");
+
+ if (metadata->deps_interface)
+ {
+ DepSpecPrettyPrinter r(0, false), p(0, false), s(0, false);
+ metadata->deps_interface->run_depend()->accept(r);
+ metadata->deps_interface->post_depend()->accept(p);
+ metadata->deps_interface->suggested_depend()->accept(s);
+ ebin_file << "RDEPEND=" << r << std::endl;
+ ebin_file << "PDEPEND=" << p << std::endl;
+ ebin_file << "SDEPEND=" << s << std::endl;
+ }
+
+ if (metadata->license_interface)
+ {
+ DepSpecPrettyPrinter l(0, false);
+ metadata->license_interface->license()->accept(l);
+ ebin_file << "LICENSE=" << l << std::endl;
+ }
+
+ ebin_file << "SLOT=" << metadata->slot << std::endl;
+ DepSpecPrettyPrinter h(0, false);
+ metadata->homepage()->accept(h);
+ ebin_file << "HOMEPAGE=" << h << std::endl;
+ ebin_file << "DESCRIPTION=" << metadata->description << std::endl;
+ ebin_file << "EAPI=" << metadata->eapi->name << std::endl;
+
+ if (metadata->ebuild_interface)
+ {
+ DepSpecPrettyPrinter p(0, false), s(0, false), r(0, false);
+ metadata->ebuild_interface->provide()->accept(p);
+ metadata->ebuild_interface->src_uri()->accept(s);
+ metadata->ebuild_interface->restrictions()->accept(r);
+ ebin_file << "PROVIDE=" << p << std::endl;
+ ebin_file << "SRC_URI=" << s << std::endl;
+ ebin_file << "RESTRICT=" << r << std::endl;
+ ebin_file << "KEYWORDS=" << join(metadata->ebuild_interface->keywords()->begin(),
+ metadata->ebuild_interface->keywords()->end(), " ") << std::endl;
+ ebin_file << "IUSE=" << join(metadata->ebuild_interface->iuse()->begin(),
+ metadata->ebuild_interface->iuse()->end(), " ") << std::endl;
+ ebin_file << "INHERITED=" << join(metadata->ebuild_interface->inherited()->begin(),
+ metadata->ebuild_interface->inherited()->end(), " ") << std::endl;
+ }
+
+ FSEntry pkg_file_name(_imp->params.distdir / (
+ stringify(_imp->portage_repository->name()) + "--" +
+ stringify(m.package_id->name.category) + "--" +
+ stringify(m.package_id->name.package) + "-" +
+ stringify(m.package_id->version) + ".tar.bz2"));
+
+ ebin_file << "BIN_URI=" << _imp->params.write_bin_uri_prefix << pkg_file_name.basename() << std::endl;
+
+ if (pkg_file_name.exists())
+ pkg_file_name.unlink();
+
+ EbinCommandParams command_params(EbinCommandParams::create()
+ .environment(_imp->params.environment)
+ .db_entry(&m.package)
+ .portdir(_imp->params.master_repository ? _imp->params.master_repository->params().location :
+ _imp->params.location)
+ .distdir(_imp->params.distdir)
+ .buildroot(_imp->params.buildroot));
+
+ EbinMergeCommand merge_cmd(
+ command_params,
+ EbinMergeCommandParams::create()
+ .pkg_file_name(pkg_file_name)
+ .image(m.image_dir)
+ .environment_file(m.environment_file));
+
+ merge_cmd();
+
+ FSEntry real_ebin_file_name(ebin_dir / (stringify(m.package_id->name.package) + "-" + stringify(m.package_id->version) + ".ebin"));
+ if (real_ebin_file_name.exists())
+ real_ebin_file_name.unlink();
+ ebin_file_name.rename(real_ebin_file_name);
+}
+
+bool
+EbinEntries::is_package_file(const QualifiedPackageName & n, const FSEntry & e) const
+{
+ return is_file_with_prefix_extension(e, stringify(n.package) + "-", ".ebin", IsFileWithOptions());
+}
+
+VersionSpec
+EbinEntries::extract_package_file_version(const QualifiedPackageName & n, const FSEntry & e) const
+{
+ Context context("When extracting version from '" + stringify(e) + "':");
+ return VersionSpec(strip_leading_string(strip_trailing_string(e.basename(), ".ebin"), stringify(n.package) + "-"));
+}
+
+bool
+EbinEntries::pretend(const QualifiedPackageName &, const VersionSpec &,
+ tr1::shared_ptr<const PortageRepositoryProfile>) const
+{
+ return true;
+}
+#endif
+
diff --git a/paludis/repositories/e/ebin_entries.hh b/paludis/repositories/e/ebin_entries.hh
new file mode 100644
index 000000000..8a7d6d146
--- /dev/null
+++ b/paludis/repositories/e/ebin_entries.hh
@@ -0,0 +1,83 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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_GENTOO_EBIN_ENTRIES_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GENTOO_EBIN_ENTRIES_HH 1
+
+#include <paludis/repositories/e/portage_repository_entries.hh>
+#include <paludis/repositories/e/portage_repository_params.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace paludis
+{
+ class FSEntry;
+ class PortageRepository;
+
+ /**
+ * PortageRepositoryEntries handler for ebins.
+ *
+ * \ingroup grpportagerepository
+ */
+ class PALUDIS_VISIBLE EbinEntries :
+ public PortageRepositoryEntries,
+ private PrivateImplementationPattern<EbinEntries>
+ {
+ public:
+ /**
+ * Create an EbinEntries instance.
+ */
+ static tr1::shared_ptr<PortageRepositoryEntries> make_ebin_entries(const Environment * const,
+ PortageRepository * const, const PortageRepositoryParams &);
+
+ ///\name Basic operations
+ ///\{
+
+ EbinEntries(const Environment * const,
+ PortageRepository * const portage_repository,
+ const PortageRepositoryParams &);
+
+ virtual ~EbinEntries();
+
+ ///\}
+
+ virtual bool is_package_file(const QualifiedPackageName &, const FSEntry &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual VersionSpec extract_package_file_version(const QualifiedPackageName &, const FSEntry &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual const tr1::shared_ptr<const PackageID> make_id(const QualifiedPackageName &, const VersionSpec &,
+ const FSEntry &, const std::string &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string get_environment_variable(const tr1::shared_ptr<const PackageID> &, const std::string & var,
+ tr1::shared_ptr<const PortageRepositoryProfile>) const;
+
+ virtual void install(const tr1::shared_ptr<const PackageID> &, const InstallOptions &,
+ tr1::shared_ptr<const PortageRepositoryProfile>) const;
+
+ virtual bool pretend(const tr1::shared_ptr<const PackageID> &,
+ tr1::shared_ptr<const PortageRepositoryProfile>) const;
+
+ virtual void merge(const MergeOptions &);
+ };
+}
+
+
+#endif
diff --git a/paludis/repositories/e/ebuild.cc b/paludis/repositories/e/ebuild.cc
new file mode 100644
index 000000000..ea8484e2e
--- /dev/null
+++ b/paludis/repositories/e/ebuild.cc
@@ -0,0 +1,705 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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/e/ebuild.hh>
+#include <paludis/repositories/e/ebuild_id.hh>
+#include <paludis/repositories/e/portage_repository.hh>
+
+#include <paludis/util/system.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/pstream.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/collection_concrete.hh>
+
+#include <paludis/about.hh>
+#include <paludis/environment.hh>
+#include <paludis/config_file.hh>
+#include <paludis/eapi.hh>
+#include <paludis/package_id.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/portage_dep_parser.hh>
+
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+
+#include "config.h"
+
+/** \file
+ * Implementation for ebuild.hh things.
+ *
+ * \ingroup grpebuildinterface
+ */
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+#include <paludis/repositories/e/ebuild-sr.cc>
+
+EbuildCommand::EbuildCommand(const EbuildCommandParams & p) :
+ params(p)
+{
+}
+
+EbuildCommand::~EbuildCommand()
+{
+}
+
+bool
+EbuildCommand::success()
+{
+ return true;
+}
+
+bool
+EbuildCommand::failure()
+{
+ return false;
+}
+
+bool
+EbuildCommand::operator() ()
+{
+ Command cmd(getenv_with_default("PALUDIS_EBUILD_DIR", LIBEXECDIR "/paludis") +
+ "/ebuild.bash '" + ebuild_file() + "' " + commands());
+
+ if (params.sandbox)
+ cmd.with_sandbox();
+
+ if (params.userpriv)
+ cmd.with_uid_gid(params.environment->reduced_uid(), params.environment->reduced_gid());
+
+
+ tr1::shared_ptr<const FSEntryCollection> syncers_dirs(params.environment->syncers_dirs());
+ tr1::shared_ptr<const FSEntryCollection> bashrc_files(params.environment->bashrc_files());
+ tr1::shared_ptr<const FSEntryCollection> fetchers_dirs(params.environment->fetchers_dirs());
+ tr1::shared_ptr<const FSEntryCollection> hook_dirs(params.environment->hook_dirs());
+
+ cmd = extend_command(cmd
+ .with_setenv("P", stringify(params.package_id->name().package) + "-" +
+ stringify(params.package_id->version().remove_revision()))
+ .with_setenv("PV", stringify(params.package_id->version().remove_revision()))
+ .with_setenv("PR", stringify(params.package_id->version().revision_only()))
+ .with_setenv("PN", stringify(params.package_id->name().package))
+ .with_setenv("PVR", stringify(params.package_id->version()))
+ .with_setenv("PF", stringify(params.package_id->name().package) + "-" +
+ stringify(params.package_id->version()))
+ .with_setenv("CATEGORY", stringify(params.package_id->name().category))
+ .with_setenv("REPOSITORY", stringify(params.package_id->repository()->name()))
+ .with_setenv("FILESDIR", stringify(params.files_dir))
+ .with_setenv("PORTDIR", stringify(params.portdir))
+ .with_setenv("DISTDIR", stringify(params.distdir))
+ .with_setenv("EAPI", stringify(params.package_id->eapi()->name))
+ .with_setenv("SLOT", "")
+ .with_setenv("PKGMANAGER", PALUDIS_PACKAGE "-" + stringify(PALUDIS_VERSION_MAJOR) + "." +
+ stringify(PALUDIS_VERSION_MINOR) + "." +
+ stringify(PALUDIS_VERSION_MICRO) +
+ (std::string(PALUDIS_SUBVERSION_REVISION).empty() ?
+ std::string("") : "-r" + std::string(PALUDIS_SUBVERSION_REVISION)))
+ .with_setenv("PALUDIS_TMPDIR", stringify(params.buildroot))
+ .with_setenv("PALUDIS_CONFIG_DIR", SYSCONFDIR "/paludis/")
+ .with_setenv("PALUDIS_BASHRC_FILES", join(bashrc_files->begin(), bashrc_files->end(), " "))
+ .with_setenv("PALUDIS_HOOK_DIRS", join(hook_dirs->begin(), hook_dirs->end(), " "))
+ .with_setenv("PALUDIS_FETCHERS_DIRS", join(fetchers_dirs->begin(), fetchers_dirs->end(), " "))
+ .with_setenv("PALUDIS_SYNCERS_DIRS", join(syncers_dirs->begin(), syncers_dirs->end(), " "))
+ .with_setenv("PALUDIS_COMMAND", params.environment->paludis_command())
+ .with_setenv("PALUDIS_REDUCED_GID", stringify(params.environment->reduced_gid()))
+ .with_setenv("PALUDIS_REDUCED_UID", stringify(params.environment->reduced_uid()))
+ .with_setenv("PALUDIS_EBUILD_LOG_LEVEL", stringify(Log::get_instance()->log_level()))
+ .with_setenv("PALUDIS_EBUILD_DIR", getenv_with_default("PALUDIS_EBUILD_DIR", LIBEXECDIR "/paludis"))
+ .with_setenv("PALUDIS_UTILITY_PATH_SUFFIXES",
+ params.package_id->eapi()->supported->ebuild_options->utility_path_suffixes)
+ .with_setenv("PALUDIS_EBUILD_MODULE_SUFFIXES",
+ params.package_id->eapi()->supported->ebuild_options->ebuild_module_suffixes)
+ .with_setenv("PALUDIS_NON_EMPTY_VARIABLES",
+ params.package_id->eapi()->supported->ebuild_options->non_empty_variables)
+ .with_setenv("PALUDIS_DIRECTORY_VARIABLES",
+ params.package_id->eapi()->supported->ebuild_options->directory_variables)
+ .with_setenv("PALUDIS_EBUILD_MUST_NOT_SET_VARIABLES",
+ params.package_id->eapi()->supported->ebuild_options->ebuild_must_not_set_variables)
+ .with_setenv("PALUDIS_DIRECTORY_IF_EXISTS_VARIABLES",
+ params.package_id->eapi()->supported->ebuild_options->directory_if_exists_variables)
+ .with_setenv("PALUDIS_SOURCE_MERGED_VARIABLES",
+ params.package_id->eapi()->supported->ebuild_options->source_merged_variables)
+ .with_setenv("PALUDIS_MUST_NOT_CHANGE_VARIABLES",
+ params.package_id->eapi()->supported->ebuild_options->must_not_change_variables)
+ .with_setenv("PALUDIS_RDEPEND_DEFAULTS_TO_DEPEND",
+ params.package_id->eapi()->supported->ebuild_options->rdepend_defaults_to_depend ? "yes" : "")
+ );
+
+ if (params.package_id->eapi()->supported->ebuild_options->want_kv_var)
+ cmd.with_setenv("KV", kernel_version());
+
+ if (params.package_id->eapi()->supported->ebuild_options->support_eclasses)
+ cmd
+ .with_setenv("ECLASSDIR", stringify(*params.eclassdirs->begin()))
+ .with_setenv("ECLASSDIRS", join(params.eclassdirs->begin(),
+ params.eclassdirs->end(), " "));
+
+ if (params.package_id->eapi()->supported->ebuild_options->support_exlibs)
+ cmd
+ .with_setenv("EXLIBSDIRS", join(params.exlibsdirs->begin(),
+ params.exlibsdirs->end(), " "));
+
+ if (params.package_id->eapi()->supported->ebuild_options->want_portage_emulation_vars)
+ cmd = add_portage_vars(cmd);
+
+ if (do_run_command(cmd))
+ return success();
+ else
+ return failure();
+}
+
+std::string
+EbuildCommand::ebuild_file() const
+{
+ return stringify(params.ebuild_file);
+}
+
+Command
+EbuildCommand::add_portage_vars(const Command & cmd) const
+{
+ return Command(cmd)
+ .with_setenv("PORTAGE_ACTUAL_DISTDIR", stringify(params.distdir))
+ .with_setenv("PORTAGE_BASHRC", "/dev/null")
+ .with_setenv("PORTAGE_BUILDDIR", stringify(params.buildroot) + "/" +
+ stringify(params.package_id->name().category) + "/" +
+ stringify(params.package_id->name().package) + "-" +
+ stringify(params.package_id->version()))
+ .with_setenv("PORTAGE_CALLER", params.environment->paludis_command())
+ .with_setenv("PORTAGE_GID", "0")
+ .with_setenv("PORTAGE_INST_GID", "0")
+ .with_setenv("PORTAGE_INST_UID", "0")
+ .with_setenv("PORTAGE_MASTER_PID", stringify(::getpid()))
+ .with_setenv("PORTAGE_NICENCESS", stringify(::getpriority(PRIO_PROCESS, 0)))
+ .with_setenv("PORTAGE_TMPDIR", stringify(params.buildroot))
+ .with_setenv("PORTAGE_TMPFS", "/dev/shm")
+ .with_setenv("PORTAGE_WORKDIR_MODE", "0700");
+}
+
+bool
+EbuildCommand::do_run_command(const Command & cmd)
+{
+ return 0 == run_command(cmd);
+}
+
+EbuildMetadataCommand::EbuildMetadataCommand(const EbuildCommandParams & p) :
+ EbuildCommand(p)
+{
+}
+
+EbuildMetadataCommand::~EbuildMetadataCommand()
+{
+}
+
+std::string
+EbuildMetadataCommand::commands() const
+{
+ return params.commands;
+}
+
+bool
+EbuildMetadataCommand::failure()
+{
+ return EbuildCommand::failure();
+}
+
+Command
+EbuildMetadataCommand::extend_command(const Command & cmd)
+{
+ return Command(cmd)
+ .with_uid_gid(params.environment->reduced_uid(), params.environment->reduced_gid())
+ .with_stderr_prefix(stringify(params.package_id->name().package) + "-" +
+ stringify(params.package_id->version()) + "> ");
+}
+
+bool
+EbuildMetadataCommand::do_run_command(const Command & cmd)
+{
+ bool ok(false);
+ keys.reset(new AssociativeCollection<std::string, std::string>::Concrete);
+
+ try
+ {
+ Context context("When generating metadata for '" + stringify(*params.package_id) + "':");
+
+ PStream prog(cmd);
+ KeyValueConfigFile f(prog, KeyValueConfigFileOptions() + kvcfo_disallow_continuations + kvcfo_disallow_comments
+ + kvcfo_disallow_space_around_equals + kvcfo_disallow_unquoted_values + kvcfo_disallow_source
+ + kvcfo_disallow_variables + kvcfo_preserve_whitespace);
+
+ std::copy(f.begin(), f.end(), keys->inserter());
+ if (0 == prog.exit_status())
+ ok = true;
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Caught exception '" +
+ stringify(e.message()) + "' (" + stringify(e.what()) +
+ ") when generating cache for '" + stringify(*params.package_id) + "'");
+ }
+
+ if (ok)
+ return true;
+ else
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Could not generate cache for '"
+ << *params.package_id << "'";
+ keys.reset(new AssociativeCollection<std::string, std::string>::Concrete);
+ keys->insert("EAPI", EAPIData::get_instance()->unknown_eapi()->name);
+ keys->insert("SLOT", "UNKNOWN");
+
+ return false;
+ }
+}
+
+namespace
+{
+ std::string get(const tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > & k, const std::string & s)
+ {
+ AssociativeCollection<std::string, std::string>::Iterator i(k->find(s));
+ if (k->end() == i)
+ return "";
+ return i->second;
+ }
+}
+
+void
+EbuildMetadataCommand::load(const tr1::shared_ptr<const EbuildID> & id)
+{
+ Context context("When loading generated metadata for '" + stringify(*params.package_id) + "':");
+
+ if (! keys)
+ throw InternalError(PALUDIS_HERE, "keys is 0");
+
+ if (! id->eapi()->supported)
+ {
+ Log::get_instance()->message(ll_debug, lc_context) << "ID pre-load EAPI '" << id->eapi()->name << "' not supported";
+ return;
+ }
+ else
+ Log::get_instance()->message(ll_debug, lc_context) << "ID pre-load EAPI '" << id->eapi()->name << "' is supported";
+
+ std::string s;
+ if (! ((s = get(keys, id->eapi()->supported->ebuild_metadata_variables->metadata_eapi))).empty())
+ id->set_eapi(s);
+ else
+ id->set_eapi(id->portage_repository()->params().eapi_when_unspecified);
+
+ if (! id->eapi()->supported)
+ {
+ Log::get_instance()->message(ll_debug, lc_context) << "ID post-load EAPI '" << id->eapi()->name << "' not supported";
+ return;
+ }
+ else
+ Log::get_instance()->message(ll_debug, lc_context) << "ID post-load EAPI '" << id->eapi()->name << "' is supported";
+
+ const EAPIEbuildMetadataVariables & m(*id->eapi()->supported->ebuild_metadata_variables);
+
+ if (! m.metadata_description.empty())
+ id->load_short_description(m.metadata_description, "Description", get(keys, m.metadata_description));
+
+ if (! m.metadata_build_depend.empty())
+ id->load_build_depend(m.metadata_build_depend, "Build depend", get(keys, m.metadata_build_depend));
+
+ if (! m.metadata_run_depend.empty())
+ id->load_run_depend(m.metadata_run_depend, "Run depend", get(keys, m.metadata_run_depend));
+
+ if (! m.metadata_pdepend.empty())
+ id->load_post_depend(m.metadata_pdepend, "Post depend", get(keys, m.metadata_pdepend));
+
+ if (! m.metadata_slot.empty())
+ {
+ try
+ {
+ Context c("When setting SLOT:");
+ std::string slot(get(keys, m.metadata_slot));
+ if (slot.empty())
+ {
+ Log::get_instance()->message(ll_qa, lc_context) << "Package '" << *id << "' set SLOT=\"\", using SLOT=\"0\" instead";
+ slot = "0";
+ }
+ id->set_slot(SlotName(slot));
+ }
+ catch (const Exception & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Setting SLOT for '" << *id << "' failed due to exception '"
+ << e.message() << "' (" << e.what() << ")";
+ id->set_slot(SlotName("0"));
+ }
+ }
+
+ if (! m.metadata_src_uri.empty())
+ id->load_src_uri(m.metadata_src_uri, "Source URI", get(keys, m.metadata_src_uri));
+
+ if (! m.metadata_homepage.empty())
+ id->load_homepage(m.metadata_homepage, "Homepage", get(keys, m.metadata_homepage));
+
+ if (! m.metadata_license.empty())
+ id->load_license(m.metadata_license, "License", get(keys, m.metadata_license));
+
+ if (! m.metadata_provide.empty())
+ id->load_provide(m.metadata_provide, "Provides", get(keys, m.metadata_provide));
+
+ if (! m.metadata_iuse.empty())
+ id->load_iuse(m.metadata_iuse, "Used USE flags", get(keys, m.metadata_iuse));
+
+ if (! m.metadata_inherited.empty())
+ id->load_inherited(m.metadata_inherited, "Inherited", get(keys, m.metadata_inherited));
+
+ if (! m.metadata_keywords.empty())
+ id->load_keywords(m.metadata_keywords, "Keywords", get(keys, m.metadata_keywords));
+
+ if (! m.metadata_restrict.empty())
+ id->load_restrict(m.metadata_restrict, "Restrictions", get(keys, m.metadata_restrict));
+}
+
+EbuildVariableCommand::EbuildVariableCommand(const EbuildCommandParams & p,
+ const std::string & var) :
+ EbuildCommand(p),
+ _var(var)
+{
+}
+
+std::string
+EbuildVariableCommand::commands() const
+{
+ return params.commands;
+}
+
+bool
+EbuildVariableCommand::failure()
+{
+ return EbuildCommand::failure();
+}
+
+Command
+EbuildVariableCommand::extend_command(const Command & cmd)
+{
+ return Command(cmd)
+ .with_setenv("PALUDIS_VARIABLE", _var)
+ .with_uid_gid(params.environment->reduced_uid(), params.environment->reduced_gid());
+}
+
+bool
+EbuildVariableCommand::do_run_command(const Command & cmd)
+{
+ PStream prog(cmd);
+ _result = strip_trailing_string(
+ std::string((std::istreambuf_iterator<char>(prog)),
+ std::istreambuf_iterator<char>()), "\n");
+
+ return (0 == prog.exit_status());
+}
+
+std::string
+EbuildFetchCommand::commands() const
+{
+ return params.commands;
+}
+
+bool
+EbuildFetchCommand::failure()
+{
+ throw PackageFetchActionError("Fetch failed for '" + stringify(*params.package_id) + "'");
+}
+
+Command
+EbuildFetchCommand::extend_command(const Command & cmd)
+{
+ Command result(Command(cmd)
+ .with_setenv("A", fetch_params.a)
+ .with_setenv("AA", fetch_params.aa)
+ .with_setenv("USE", fetch_params.use)
+ .with_setenv("USE_EXPAND", fetch_params.use_expand)
+ .with_setenv("FLAT_SRC_URI", fetch_params.flat_src_uri)
+ .with_setenv("ROOT", fetch_params.root)
+ .with_setenv("PALUDIS_USE_SAFE_RESUME", fetch_params.safe_resume ? "oohyesplease" : "")
+ .with_setenv("PALUDIS_PROFILE_DIR", stringify(*fetch_params.profiles->begin()))
+ .with_setenv("PALUDIS_PROFILE_DIRS", join(fetch_params.profiles->begin(),
+ fetch_params.profiles->end(), " ")));
+
+ for (AssociativeCollection<std::string, std::string>::Iterator
+ i(fetch_params.expand_vars->begin()),
+ j(fetch_params.expand_vars->end()) ; i != j ; ++i)
+ result.with_setenv(i->first, i->second);
+
+ return result;
+}
+
+EbuildFetchCommand::EbuildFetchCommand(const EbuildCommandParams & p,
+ const EbuildFetchCommandParams & f) :
+ EbuildCommand(p),
+ fetch_params(f)
+{
+}
+
+std::string
+EbuildInstallCommand::commands() const
+{
+ return params.commands;
+}
+
+bool
+EbuildInstallCommand::failure()
+{
+ throw PackageInstallActionError("Install failed for '" + stringify(*params.package_id) + "'");
+}
+
+Command
+EbuildInstallCommand::extend_command(const Command & cmd)
+{
+ std::string debug_build;
+ do
+ {
+ switch (install_params.debug_build)
+ {
+ case ido_none:
+ debug_build = "none";
+ continue;
+
+ case ido_split:
+ debug_build = "split";
+ continue;
+
+ case ido_internal:
+ debug_build = "internal";
+ continue;
+ }
+
+ throw InternalError(PALUDIS_HERE, "Bad debug_build value");
+ }
+ while (false);
+
+ Command result(Command(cmd)
+ .with_setenv("A", install_params.a)
+ .with_setenv("AA", install_params.aa)
+ .with_setenv("USE", install_params.use)
+ .with_setenv("USE_EXPAND", install_params.use_expand)
+ .with_setenv("ROOT", install_params.root)
+ .with_setenv("PALUDIS_LOADSAVEENV_DIR", stringify(install_params.loadsaveenv_dir))
+ .with_setenv("PALUDIS_CONFIG_PROTECT", install_params.config_protect)
+ .with_setenv("PALUDIS_CONFIG_PROTECT_MASK", install_params.config_protect_mask)
+ .with_setenv("PALUDIS_EBUILD_OVERRIDE_CONFIG_PROTECT_MASK",
+ install_params.disable_cfgpro ? "/" : "")
+ .with_setenv("PALUDIS_DEBUG_BUILD", debug_build)
+ .with_setenv("PALUDIS_PROFILE_DIR", stringify(*install_params.profiles->begin()))
+ .with_setenv("PALUDIS_PROFILE_DIRS", join(install_params.profiles->begin(),
+ install_params.profiles->end(), " "))
+ .with_setenv("SLOT", stringify(install_params.slot)));
+
+ for (AssociativeCollection<std::string, std::string>::Iterator
+ i(install_params.expand_vars->begin()),
+ j(install_params.expand_vars->end()) ; i != j ; ++i)
+ result.with_setenv(i->first, i->second);
+
+ return result;
+}
+
+EbuildInstallCommand::EbuildInstallCommand(const EbuildCommandParams & p,
+ const EbuildInstallCommandParams & f) :
+ EbuildCommand(p),
+ install_params(f)
+{
+}
+
+std::string
+EbuildUninstallCommand::commands() const
+{
+ return params.commands;
+}
+
+std::string
+EbuildUninstallCommand::ebuild_file() const
+{
+ return "-";
+}
+
+bool
+EbuildUninstallCommand::failure()
+{
+ throw PackageUninstallActionError("Uninstall failed for '" + stringify(*params.package_id) + "'");
+}
+
+Command
+EbuildUninstallCommand::extend_command(const Command & cmd)
+{
+ Command result(Command(cmd)
+ .with_setenv("ROOT", uninstall_params.root)
+ .with_setenv("PALUDIS_LOADSAVEENV_DIR", stringify(uninstall_params.loadsaveenv_dir))
+ .with_setenv("PALUDIS_EBUILD_OVERRIDE_CONFIG_PROTECT_MASK",
+ uninstall_params.disable_cfgpro ? "/" : ""));
+
+ if (uninstall_params.load_environment)
+ result
+ .with_setenv("PALUDIS_LOAD_ENVIRONMENT", stringify(*uninstall_params.load_environment))
+ .with_setenv("PALUDIS_SKIP_INHERIT", "yes");
+
+ return result;
+}
+
+EbuildUninstallCommand::EbuildUninstallCommand(const EbuildCommandParams & p,
+ const EbuildUninstallCommandParams & f) :
+ EbuildCommand(p),
+ uninstall_params(f)
+{
+}
+
+std::string
+EbuildConfigCommand::commands() const
+{
+ return params.commands;
+}
+
+bool
+EbuildConfigCommand::failure()
+{
+ throw PackageConfigActionError("Configure failed for '" + stringify(
+ *params.package_id) + "'");
+}
+
+Command
+EbuildConfigCommand::extend_command(const Command & cmd)
+{
+ Command result(Command(cmd)
+ .with_setenv("ROOT", config_params.root));
+
+ if (config_params.load_environment)
+ result
+ .with_setenv("PALUDIS_LOAD_ENVIRONMENT", stringify(*config_params.load_environment))
+ .with_setenv("PALUDIS_SKIP_INHERIT", "yes");
+
+ return result;
+}
+
+EbuildConfigCommand::EbuildConfigCommand(const EbuildCommandParams & p,
+ const EbuildConfigCommandParams & f) :
+ EbuildCommand(p),
+ config_params(f)
+{
+}
+
+WriteVDBEntryCommand::WriteVDBEntryCommand(const WriteVDBEntryParams & p) :
+ params(p)
+{
+}
+
+void
+WriteVDBEntryCommand::operator() ()
+{
+ std::string ebuild_cmd(getenv_with_default("PALUDIS_EBUILD_DIR", LIBEXECDIR "/paludis") +
+ "/write_vdb_entry.bash '" +
+ stringify(params.output_directory) + "' '" +
+ stringify(params.environment_file) + "'");
+
+ tr1::shared_ptr<const FSEntryCollection> syncers_dirs(params.environment->syncers_dirs());
+ tr1::shared_ptr<const FSEntryCollection> bashrc_files(params.environment->bashrc_files());
+ tr1::shared_ptr<const FSEntryCollection> fetchers_dirs(params.environment->fetchers_dirs());
+ tr1::shared_ptr<const FSEntryCollection> hook_dirs(params.environment->hook_dirs());
+
+ Command cmd(Command(ebuild_cmd)
+ .with_setenv("PKGMANAGER", PALUDIS_PACKAGE "-" + stringify(PALUDIS_VERSION_MAJOR) + "." +
+ stringify(PALUDIS_VERSION_MINOR) + "." +
+ stringify(PALUDIS_VERSION_MICRO) +
+ (std::string(PALUDIS_SUBVERSION_REVISION).empty() ?
+ std::string("") : "-r" + std::string(PALUDIS_SUBVERSION_REVISION)))
+ .with_setenv("PALUDIS_CONFIG_DIR", SYSCONFDIR "/paludis/")
+ .with_setenv("PALUDIS_BASHRC_FILES", join(bashrc_files->begin(), bashrc_files->end(), " "))
+ .with_setenv("PALUDIS_HOOK_DIRS", join(hook_dirs->begin(), hook_dirs->end(), " "))
+ .with_setenv("PALUDIS_FETCHERS_DIRS", join(fetchers_dirs->begin(), fetchers_dirs->end(), " "))
+ .with_setenv("PALUDIS_SYNCERS_DIRS", join(syncers_dirs->begin(), syncers_dirs->end(), " "))
+ .with_setenv("PALUDIS_COMMAND", params.environment->paludis_command())
+ .with_setenv("PALUDIS_EBUILD_LOG_LEVEL", stringify(Log::get_instance()->log_level()))
+ .with_setenv("PALUDIS_EBUILD_DIR", getenv_with_default("PALUDIS_EBUILD_DIR", LIBEXECDIR "/paludis")));
+
+ if (0 != (run_command(cmd)))
+ throw PackageInstallActionError("Write VDB Entry command failed");
+}
+
+VDBPostMergeCommand::VDBPostMergeCommand(const VDBPostMergeCommandParams & p) :
+ params(p)
+{
+}
+
+void
+VDBPostMergeCommand::operator() ()
+{
+ if (! getenv_with_default("PALUDIS_NO_GLOBAL_HOOKS", "").empty())
+ return;
+
+#ifdef HAVE_GNU_LDCONFIG
+ std::string ebuild_cmd("ldconfig -r '" + stringify(params.root) + "'");
+#else
+ std::string ebuild_cmd("ldconfig -elf -i -f '" + stringify(params.root) +
+ "var/run/ld-elf.so.hints' '" + stringify(params.root) + "etc/ld.so.conf'");
+#endif
+
+ if (0 != (run_command(ebuild_cmd)))
+ throw PackageInstallActionError("VDB Entry post merge commands failed");
+}
+
+std::string
+EbuildPretendCommand::commands() const
+{
+ return params.commands;
+}
+
+bool
+EbuildPretendCommand::failure()
+{
+ return false;
+}
+
+Command
+EbuildPretendCommand::extend_command(const Command & cmd)
+{
+ Command result(Command(cmd)
+ .with_stdout_prefix(stringify(params.package_id->name().package) + "-" +
+ stringify(params.package_id->version()) + "> ")
+ .with_stderr_prefix(stringify(params.package_id->name().package) + "-" +
+ stringify(params.package_id->version()) + "> ")
+ .with_prefix_discard_blank_output()
+ .with_prefix_blank_lines()
+ .with_setenv("USE", pretend_params.use)
+ .with_setenv("USE_EXPAND", pretend_params.use_expand)
+ .with_setenv("ROOT", pretend_params.root)
+ .with_setenv("PALUDIS_PROFILE_DIR", stringify(*pretend_params.profiles->begin()))
+ .with_setenv("PALUDIS_PROFILE_DIRS", join(pretend_params.profiles->begin(),
+ pretend_params.profiles->end(), " ")));
+
+ for (AssociativeCollection<std::string, std::string>::Iterator
+ i(pretend_params.expand_vars->begin()),
+ j(pretend_params.expand_vars->end()) ; i != j ; ++i)
+ result.with_setenv(i->first, i->second);
+
+ result.with_uid_gid(params.environment->reduced_uid(), params.environment->reduced_gid());
+
+ return result;
+}
+
+EbuildPretendCommand::EbuildPretendCommand(const EbuildCommandParams & p,
+ const EbuildPretendCommandParams & f) :
+ EbuildCommand(p),
+ pretend_params(f)
+{
+}
+
diff --git a/paludis/repositories/e/ebuild.hh b/paludis/repositories/e/ebuild.hh
new file mode 100644
index 000000000..42f7975b5
--- /dev/null
+++ b/paludis/repositories/e/ebuild.hh
@@ -0,0 +1,366 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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_EBUILD_HH
+#define PALUDIS_GUARD_PALUDIS_EBUILD_HH 1
+
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/collection.hh>
+#include <paludis/package_database.hh>
+#include <string>
+
+/** \file
+ * Declarations for the EbuildCommand classes.
+ *
+ * \ingroup grpebuildinterface
+ */
+
+namespace paludis
+{
+ class Environment;
+ class Command;
+
+ namespace erepository
+ {
+ class EbuildID;
+
+#include <paludis/repositories/e/ebuild-sr.hh>
+
+ /**
+ * An EbuildCommand is the base class from which specific ebuild
+ * command interfaces are descended.
+ *
+ * \ingroup grpebuildinterface
+ */
+ class EbuildCommand :
+ private InstantiationPolicy<EbuildCommand, instantiation_method::NonCopyableTag>
+ {
+ protected:
+ /**
+ * Our parameters.
+ */
+ const EbuildCommandParams params;
+
+ /**
+ * Constructor.
+ */
+ EbuildCommand(const EbuildCommandParams &);
+
+ /**
+ * Override in descendents: which commands (for example, 'prerm
+ * unmerge postrm') do we give to ebuild.bash?
+ */
+ virtual std::string commands() const = 0;
+
+ /**
+ * Return our ebuild file.
+ */
+ virtual std::string ebuild_file() const;
+
+ /**
+ * Actions to be taken after a successful command.
+ *
+ * The return value of this function is used for the return value
+ * of operator().
+ */
+ virtual bool success();
+
+ /**
+ * Actions to be taken after a failed command.
+ *
+ * The return value of this function is used for the return value
+ * of operator(). In some descendents, this function throws and
+ * does not return.
+ */
+ virtual bool failure() = 0;
+
+ /**
+ * Run the specified command. Can be overridden if, for example,
+ * the command output needs to be captured.
+ *
+ * \return Whether the command succeeded.
+ */
+ virtual bool do_run_command(const Command &);
+
+ /**
+ * Add Portage emulation vars.
+ */
+ virtual Command add_portage_vars(const Command &) const;
+
+ /**
+ * Extend the command to be run.
+ */
+ virtual Command extend_command(const Command &) = 0;
+
+ public:
+ /**
+ * Destructor.
+ */
+ virtual ~EbuildCommand();
+
+ /**
+ * Run the command.
+ */
+ virtual bool operator() ();
+ };
+
+ /**
+ * An EbuildVariableCommand is used to fetch the value of an environment
+ * variable for a particular ebuild in a PortageRepository.
+ *
+ * \ingroup grpebuildinterface
+ */
+ class EbuildVariableCommand :
+ public EbuildCommand
+ {
+ private:
+ std::string _result;
+ const std::string _var;
+
+ protected:
+ virtual std::string commands() const;
+
+ virtual Command extend_command(const Command &);
+
+ virtual bool do_run_command(const Command &);
+
+ virtual bool failure();
+
+ public:
+ /**
+ * Constructor.
+ */
+ EbuildVariableCommand(const EbuildCommandParams &, const std::string &);
+
+ /**
+ * Fetch our result.
+ */
+ std::string result() const
+ {
+ return _result;
+ }
+ };
+
+ /**
+ * An EbuildFetchCommand is used to download and verify the digests for a
+ * particular ebuild in a PortageRepository. On failure it throws.
+ *
+ * \ingroup grpebuildinterface
+ */
+ class EbuildFetchCommand :
+ public EbuildCommand
+ {
+ protected:
+ /// Parameters for fetch.
+ const EbuildFetchCommandParams fetch_params;
+
+ virtual std::string commands() const;
+
+ virtual bool failure() PALUDIS_ATTRIBUTE((noreturn));
+
+ virtual Command extend_command(const Command &);
+
+ public:
+ /**
+ * Constructor.
+ */
+ EbuildFetchCommand(const EbuildCommandParams &, const EbuildFetchCommandParams &);
+ };
+
+ /**
+ * An EbuildInstallCommand is used to install an ebuild from a
+ * PortageRepository. On failure it throws.
+ *
+ * \ingroup grpebuildinterface
+ */
+ class EbuildInstallCommand :
+ public EbuildCommand
+ {
+ protected:
+ /// Parameters for install.
+ const EbuildInstallCommandParams install_params;
+
+ virtual std::string commands() const;
+
+ virtual bool failure() PALUDIS_ATTRIBUTE((noreturn));
+
+ virtual Command extend_command(const Command &);
+
+ public:
+ /**
+ * Constructor.
+ */
+ EbuildInstallCommand(const EbuildCommandParams &, const EbuildInstallCommandParams &);
+ };
+
+ /**
+ * An EbuildUninstallCommand is used to uninstall a package in a VDBRepository.
+ *
+ * \ingroup grpebuildinterface
+ */
+ class EbuildUninstallCommand :
+ public EbuildCommand
+ {
+ protected:
+ /// Parameters for uninstall.
+ const EbuildUninstallCommandParams uninstall_params;
+
+ virtual std::string commands() const;
+
+ virtual bool failure() PALUDIS_ATTRIBUTE((noreturn));
+
+ virtual Command extend_command(const Command &);
+
+ virtual std::string ebuild_file() const;
+
+ public:
+ /**
+ * Constructor.
+ */
+ EbuildUninstallCommand(const EbuildCommandParams &, const EbuildUninstallCommandParams &);
+ };
+
+ /**
+ * An EbuildConfigCommand is used to configure a package in a VDBRepository.
+ *
+ * \ingroup grpebuildinterface
+ */
+ class EbuildConfigCommand :
+ public EbuildCommand
+ {
+ protected:
+ /// Parameters for config.
+ const EbuildConfigCommandParams config_params;
+
+ virtual std::string commands() const;
+
+ virtual bool failure() PALUDIS_ATTRIBUTE((noreturn));
+
+ virtual Command extend_command(const Command &);
+
+ public:
+ /**
+ * Constructor.
+ */
+ EbuildConfigCommand(const EbuildCommandParams &, const EbuildConfigCommandParams &);
+ };
+
+ /**
+ * An EbuildPretendCommand is used to configure a package in a VDBRepository.
+ *
+ * \ingroup grpebuildinterface
+ */
+ class EbuildPretendCommand :
+ public EbuildCommand
+ {
+ protected:
+ /// Parameters for config.
+ const EbuildPretendCommandParams pretend_params;
+
+ virtual std::string commands() const;
+
+ virtual bool failure();
+
+ virtual Command extend_command(const Command &);
+
+ public:
+ /**
+ * Constructor.
+ */
+ EbuildPretendCommand(const EbuildCommandParams &, const EbuildPretendCommandParams &);
+ };
+
+ /**
+ * Command for generating VDB entries (not a regular EbuildCommand).
+ *
+ * \ingroup grpebuildinterface
+ */
+ class WriteVDBEntryCommand :
+ private InstantiationPolicy<WriteVDBEntryCommand, instantiation_method::NonCopyableTag>
+ {
+ protected:
+ /**
+ * Our parameters.
+ */
+ const WriteVDBEntryParams params;
+
+ public:
+ /**
+ * Constructor.
+ */
+ WriteVDBEntryCommand(const WriteVDBEntryParams &);
+
+ /**
+ * Run the command.
+ */
+ void operator() ();
+ };
+
+ /**
+ * Command to be run after a VDB merge.
+ *
+ * \ingroup grpebuildinterface
+ */
+ class VDBPostMergeCommand :
+ private InstantiationPolicy<VDBPostMergeCommand, instantiation_method::NonCopyableTag>
+ {
+ private:
+ const VDBPostMergeCommandParams params;
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ VDBPostMergeCommand(const VDBPostMergeCommandParams &);
+
+ ///\}
+
+ /**
+ * Run the command.
+ */
+ void operator() ();
+ };
+
+ class EbuildMetadataCommand :
+ public EbuildCommand
+ {
+ private:
+ tr1::shared_ptr<AssociativeCollection<std::string, std::string> > keys;
+
+ public:
+ EbuildMetadataCommand(const EbuildCommandParams &);
+
+ ~EbuildMetadataCommand();
+
+ std::string commands() const;
+
+ bool failure();
+
+ bool do_run_command(const Command &);
+
+ Command extend_command(const Command &);
+
+ void load(const tr1::shared_ptr<const EbuildID> &);
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/e/ebuild.sr b/paludis/repositories/e/ebuild.sr
new file mode 100644
index 000000000..48cde63da
--- /dev/null
+++ b/paludis/repositories/e/ebuild.sr
@@ -0,0 +1,183 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_EbuildCommandParams()
+{
+ key environment "const Environment *"
+ key package_id "tr1::shared_ptr<const PackageID>"
+ key ebuild_dir FSEntry
+ key ebuild_file FSEntry
+ key files_dir FSEntry
+ key eclassdirs "tr1::shared_ptr<const FSEntryCollection>"
+ key exlibsdirs "tr1::shared_ptr<const FSEntryCollection>"
+ key portdir FSEntry
+ key distdir FSEntry
+ key buildroot FSEntry
+ key userpriv bool
+ key sandbox bool
+ key commands std::string
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for an EbuildCommand.
+ *
+ * \see EbuildCommand
+ * \ingroup grpebuildinterface
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
+make_class_EbuildFetchCommandParams()
+{
+ key a std::string
+ key aa std::string
+ key use std::string
+ key use_expand std::string
+ key flat_src_uri std::string
+ key root std::string
+ key profiles "tr1::shared_ptr<const FSEntryCollection>"
+ key expand_vars "tr1::shared_ptr<const AssociativeCollection<std::string, std::string> >"
+ key safe_resume bool
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for an EbuildFetchCommand.
+ *
+ * \see EbuildFetchCommand
+ * \ingroup grpebuildinterface
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
+make_class_EbuildInstallCommandParams()
+{
+ key a std::string
+ key aa std::string
+ key use std::string
+ key use_expand std::string
+ key root std::string
+ key profiles "tr1::shared_ptr<const FSEntryCollection>"
+ key expand_vars "tr1::shared_ptr<const AssociativeCollection<std::string, std::string> >"
+ key disable_cfgpro bool
+ key debug_build InstallDebugOption
+ key slot SlotName
+ key config_protect std::string
+ key config_protect_mask std::string
+ key loadsaveenv_dir FSEntry
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for an EbuildInstallCommand.
+ *
+ * \see EbuildInstallCommand
+ * \ingroup grpebuildinterface
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
+make_class_EbuildPretendCommandParams()
+{
+ key use std::string
+ key use_expand std::string
+ key root std::string
+ key profiles "tr1::shared_ptr<const FSEntryCollection>"
+ key expand_vars "tr1::shared_ptr<const AssociativeCollection<std::string, std::string> >"
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for an EbuildPretendCommand.
+ *
+ * \see EbuildPretendCommand
+ * \ingroup grpebuildinterface
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
+make_class_EbuildUninstallCommandParams()
+{
+ key root std::string
+ key disable_cfgpro bool
+ key unmerge_only bool
+ key load_environment "const FSEntry *"
+ key loadsaveenv_dir FSEntry
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for an EbuildUninstallCommand.
+ *
+ * \see EbuildUninstallCommand
+ * \ingroup grpebuildinterface
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
+make_class_EbuildConfigCommandParams()
+{
+ key root std::string
+ key load_environment "const FSEntry *"
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for an EbuildConfigCommand.
+ *
+ * \see EbuildConfigCommand
+ * \ingroup grpebuildinterface
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
+make_class_WriteVDBEntryParams()
+{
+ key environment "const Environment *"
+ key package_id "tr1::shared_ptr<const PackageID>"
+ key output_directory "FSEntry"
+ key environment_file "FSEntry"
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for writing a VDB entry.
+ *
+ * \see WriteVDBEntryCommand
+ * \ingroup grpebuildinterface
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
+make_class_VDBPostMergeCommandParams()
+{
+ key root "FSEntry"
+
+ doxygen_comment << "END"
+ /**
+ * Parameters for a VDBPostMergeCommand.
+ *
+ * \see VDBPostMergeCommand
+ * \ingroup grpebuildinterface
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
diff --git a/paludis/repositories/e/ebuild/Makefile.am b/paludis/repositories/e/ebuild/Makefile.am
new file mode 100644
index 000000000..4346427db
--- /dev/null
+++ b/paludis/repositories/e/ebuild/Makefile.am
@@ -0,0 +1,87 @@
+MAINTAINERCLEANFILES = Makefile.in
+CLEANFILES = *~
+SUBDIRS = . digests utils
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@
+
+libexecprogdir = $(libexecdir)/paludis/
+
+libexecprog_SCRIPTS = \
+ build_functions.bash \
+ builtin_fetch.bash \
+ builtin_fetchbin.bash \
+ builtin_init.bash \
+ builtin_initbin.bash \
+ builtin_loadenv.bash \
+ builtin_merge.bash \
+ builtin_metadata.bash \
+ builtin_prepare.bash \
+ builtin_saveenv.bash \
+ builtin_strip.bash \
+ builtin_tidyup.bash \
+ builtin_unmerge.bash \
+ builtin_unpackbin.bash \
+ builtin_variable.bash \
+ die_functions.bash \
+ ebuild.bash \
+ echo_functions.bash \
+ kernel_functions.bash \
+ eclass_functions.bash \
+ exlib_functions.bash \
+ install_functions.bash \
+ list_functions.bash \
+ multilib_functions.bash \
+ pkg_config.bash \
+ pkg_nofetch.bash \
+ pkg_postinst.bash \
+ pkg_postrm.bash \
+ pkg_preinst.bash \
+ pkg_prerm.bash \
+ pkg_pretend.bash \
+ pkg_setup.bash \
+ portage_stubs.bash \
+ sandbox.bash \
+ src_compile.bash \
+ src_install.bash \
+ src_test.bash \
+ src_unpack.bash \
+ usage_error.bash \
+ write_vdb_entry.bash \
+ work_around_broken_utilities.bash
+
+TESTS_ENVIRONMENT = env \
+ PALUDIS_EBUILD_DIR="$(top_srcdir)/paludis/repositories/e/ebuild/" \
+ PALUDIS_EAPIS_DIR="$(top_srcdir)/paludis/eapis/" \
+ PALUDIS_DISTRIBUTIONS_DIR="$(top_srcdir)/paludis/distributions/" \
+ PALUDIS_EBUILD_LOG_LEVEL="warning" \
+ TOP_BUILD_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/`" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ bash $(top_srcdir)/test/run_test.sh $(top_srcdir)/paludis/repositories/e/ebuild/run_test.bash
+
+TESTS = echo_functions_TEST.bash list_functions_TEST.bash kernel_functions_TEST.bash \
+ merge_TEST.bash unmerge_TEST.bash
+
+libexecprog_PROGRAMS = merge unmerge
+merge_SOURCES = merge.cc merge_common.cc merge_common.hh
+merge_LDADD = \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/digests/libpaludisdigests.la \
+ $(top_builddir)/paludis/selinux/libpaludisselinux.la \
+ $(DYNAMIC_LD_LIBS)
+
+unmerge_SOURCES = unmerge.cc merge_common.cc merge_common.hh
+unmerge_LDADD = \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/digests/libpaludisdigests.la
+
+check_SCRIPTS = $(TESTS) \
+ merge_TEST_setup.sh merge_TEST_cleanup.sh \
+ unmerge_TEST_setup.sh unmerge_TEST_cleanup.sh \
+ run_test.bash $(TESTS)
+
+EXTRA_DIST = $(libexecprog_SCRIPTS) run_test.bash $(TESTS) $(check_SCRIPTS)
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+
diff --git a/paludis/repositories/e/ebuild/build_functions.bash b/paludis/repositories/e/ebuild/build_functions.bash
new file mode 100644
index 000000000..6e7aa11be
--- /dev/null
+++ b/paludis/repositories/e/ebuild/build_functions.bash
@@ -0,0 +1,110 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+econf()
+{
+ local LOCAL_EXTRA_ECONF="${EXTRA_ECONF}"
+ local LOCAL_ECONF_WRAPPER="${ECONF_WRAPPER}"
+
+ [[ -z "${ECONF_SOURCE}" ]] && ECONF_SOURCE=.
+
+ if [[ -x "${ECONF_SOURCE}/configure" ]] ; then
+ if [[ -d /usr/share/gnuconfig ]] ; then
+ local f
+ for f in $(find "${WORKDIR}" -type f -name config.guess -or -name config.sub ) ; do
+ echo "econf: updating ${f} with /usr/share/gnuconfig/${f##*/}"
+ cp -f /usr/share/gnuconfig/${f##*/} ${f}
+ done
+ fi
+
+ [[ -z "${CBUILD}" ]] || LOCAL_EXTRA_ECONF="--build=${CBUILD} ${LOCAL_EXTRA_ECONF}"
+ [[ -z "${CTARGET}" ]] || LOCAL_EXTRA_ECONF="--target=${CTARGET} ${LOCAL_EXTRA_ECONF}"
+
+ # If the ebuild passed in --prefix, use that to set --libdir. KDE at least needs this.
+
+ ECONF_PREFIX=/usr
+ for i in "$@"; do
+ if [[ ${i} == --prefix=* ]]; then
+ ECONF_PREFIX=${i#--prefix=}
+ elif [[ ${i} == --exec-prefix=* ]]; then
+ ECONF_PREFIX=${i#--exec-prefix=}
+ fi
+ done
+
+ local libcmd=
+ if [[ -n "${ABI}" ]] ; then
+ local v="LIBDIR_${ABI}"
+ if [[ -n "${!v}" ]] ; then
+ libcmd="--libdir=${ECONF_PREFIX}/$(ebuild_get_libdir)"
+ fi
+ fi
+
+ echo ${LOCAL_ECONF_WRAPPER} ${ECONF_SOURCE}/configure \
+ --prefix=/usr \
+ --host=${CHOST} \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --datadir=/usr/share \
+ --sysconfdir=/etc \
+ --localstatedir=/var/lib \
+ ${libcmd} "$@" ${LOCAL_EXTRA_ECONF} 1>&2
+
+ ${LOCAL_ECONF_WRAPPER} ${ECONF_SOURCE}/configure \
+ --prefix=/usr \
+ --host=${CHOST} \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --datadir=/usr/share \
+ --sysconfdir=/etc \
+ --localstatedir=/var/lib \
+ ${libcmd} "$@" ${LOCAL_EXTRA_ECONF} || die "econf failed"
+
+ else
+ die "No configure script for econf"
+ fi
+}
+
+einstall()
+{
+ if [[ -f Makefile ]] || [[ -f makefile ]] || [[ -f GNUmakefile ]] ; then
+ local makecmd=""
+ type -p gmake &>/dev/null && makecmd="gmake" || makecmd="make"
+ local cmd="${EINSTALL_WRAPPER} ${makecmd} prefix=${D}/usr"
+ cmd="${cmd} mandir=${D}/usr/share/man"
+ cmd="${cmd} infodir=${D}/usr/share/info"
+ cmd="${cmd} datadir=${D}/usr/share"
+ cmd="${cmd} sysconfdir=${D}/etc"
+ cmd="${cmd} localstatedir=${D}/var/lib"
+ cmd="${cmd} libdir=${D}/usr/$(ebuild_get_libdir)"
+ cmd="${cmd} ${EXTRA_EINSTALL} ${@} install"
+ echo "${cmd}" 1>&2
+ ${cmd} || die "einstall failed"
+ else
+ die "No Makefile for einstall"
+ fi
+}
+
+unpack()
+{
+ dounpack ${@} || die "unpack failed"
+}
+
diff --git a/paludis/repositories/e/ebuild/builtin_fetch.bash b/paludis/repositories/e/ebuild/builtin_fetch.bash
new file mode 100644
index 000000000..c3f6402d0
--- /dev/null
+++ b/paludis/repositories/e/ebuild/builtin_fetch.bash
@@ -0,0 +1,137 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+builtin_fetch()
+{
+ [[ -d "${DISTDIR}" ]] || die "DISTDIR \"${DISTDIR}\" is not a directory"
+
+ local a nofetch unique_aa old_aa
+ for a in ${FLAT_SRC_URI} ; do
+ local aa=${a##*/}
+ hasq "${aa}" ${unique_aa} || unique_aa="${unique_aa} ${aa}"
+
+ if [[ -f "${DISTDIR}/${aa}" ]] && [[ "0" != $(getfsize "${DISTDIR}/${aa}") ]] ; then
+ if [[ "${old_aa}" != "${aa}" ]] ; then
+ ebuild_section "Already have ${aa}"
+ old_aa="${aa}"
+ fi
+ else
+ if [[ -f "${DISTDIR}/${aa}" ]] ; then
+ ebuild_section "Trying to remove existing ${aa}..."
+ rm -f "${DISTDIR}/${aa}"
+ fi
+
+ if ! hasq fetch ${RESTRICT} ; then
+ if [[ "${old_aa}" != "${aa}" ]] ; then
+ ebuild_section "Need to fetch ${aa}"
+ old_aa="${aa}"
+ fi
+ local d
+ for d in ${PALUDIS_FETCHERS_DIRS:-${PALUDIS_EBUILD_DIR}/fetchers/} ; do
+ prg=${d}/do$(echo ${a%%://*} | tr '[:upper:]' '[:lower:]' )
+ ebuild_notice "debug" "fetcher program candidate for '${a}' is '${prg}'"
+ [[ -x "${prg}" ]] && break
+ done
+ if [[ -x "${prg}" ]] ; then
+ ${prg} "${a}" "${DISTDIR}/${aa}"
+ else
+ eerror "Don't know how to fetch '${a}'"
+ fi
+ else
+ if ! [[ "${old_aa}" != "${aa}" ]] ; then
+ ebuild_section "Can't fetch ${aa}"
+ old_aa="${aa}"
+ fi
+ fi
+ fi
+ done
+
+ for a in ${unique_aa} ; do
+ [[ -f ${DISTDIR}/${a} ]] || nofetch="${nofetch} ${a}"
+ done
+
+ if [[ -n "${nofetch}" ]] ; then
+ local c
+ echo
+ eerror "Couldn't fetch the following components:"
+ for c in ${nofetch} ; do
+ eerror " * ${c}"
+ done
+ echo
+ die "builtin_fetch failed"
+ fi
+
+ local badfetch=
+ if [[ -f "${FILESDIR}/digest-${PN}-${PVR%-r0}" ]] ; then
+ local line items prg
+ while read line ; do
+ line=( ${line} )
+ if ! hasq "${line[2]}" ${A} ; then
+ ebuild_section "Skipping check for ${line[2]}"
+ continue
+ fi
+
+ prg="${PALUDIS_EBUILD_DIR}/digests/do$(echo ${line[0]} | tr \
+ '[[:upper:]]' '[[:lower:]]')"
+ if [[ -x "${prg}" ]] ; then
+ ebegin_unhooked "Checking ${line[0]} for ${line[2]}"
+ if [[ $("${prg}" "${DISTDIR}/${line[2]}" ) == "${line[1]}" ]] ; then
+ eend 0
+ else
+ eend 1
+ hasq "${line[2]}" ${badfetch} || badfetch="${badfetch} ${line[2]}"
+ fi
+ else
+ einfo_unhooked "Can't check ${line[0]} for ${line[2]}"
+ fi
+
+ done < "${FILESDIR}"/digest-${PN}-${PVR%-r0}
+ else
+ ebuild_section "No digest file, skipping integrity checks"
+ fi
+
+ if [[ -n "${badfetch}" ]] ; then
+ local c
+ echo
+ eerror "Bad digests encountered for the following components:"
+ for c in ${badfetch} ; do
+ eerror " * ${c}"
+ done
+ echo
+ die "builtin_fetch failed"
+ fi
+}
+
+ebuild_f_fetch()
+{
+ local old_sandbox_write="${SANDBOX_WRITE}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}${DISTDIR}"
+ if hasq "fetch" ${RESTRICT} ; then
+ ebuild_section "Skipping builtin_fetch (RESTRICT)"
+ elif hasq "fetch" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping builtin_fetch (SKIP_FUNCTIONS)"
+ else
+ ebuild_section "Starting builtin_fetch"
+ builtin_fetch
+ ebuild_section "Done builtin_fetch"
+ fi
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${old_sandbox_write}"
+ true
+}
+
+
diff --git a/paludis/repositories/e/ebuild/builtin_fetchbin.bash b/paludis/repositories/e/ebuild/builtin_fetchbin.bash
new file mode 100644
index 000000000..17af258e9
--- /dev/null
+++ b/paludis/repositories/e/ebuild/builtin_fetchbin.bash
@@ -0,0 +1,98 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+builtin_fetchbin()
+{
+ [[ -d "${DISTDIR}" ]] || die "DISTDIR \"${DISTDIR}\" is not a directory"
+
+ local a nofetch unique_aa old_aa
+ for a in ${FLAT_BIN_URI} ; do
+ local aa=${a##*/}
+ hasq "${aa}" ${unique_aa} || unique_aa="${unique_aa} ${aa}"
+
+ if [[ -f "${DISTDIR}/${aa}" ]] && [[ "0" != $(getfsize "${DISTDIR}/${aa}") ]] ; then
+ if [[ "${old_aa}" != "${aa}" ]] ; then
+ ebuild_section "Already have ${aa}"
+ old_aa="${aa}"
+ fi
+ else
+ if [[ -f "${DISTDIR}/${aa}" ]] ; then
+ ebuild_section "Trying to remove existing ${aa}..."
+ rm -f "${DISTDIR}/${aa}"
+ fi
+
+ if ! hasq fetchbin ${RESTRICT} ; then
+ if [[ "${old_aa}" != "${aa}" ]] ; then
+ ebuild_section "Need to fetch ${aa}"
+ old_aa="${aa}"
+ fi
+ local d
+ for d in ${PALUDIS_FETCHERS_DIRS:-${PALUDIS_EBUILD_DIR}/fetchers/} ; do
+ prg=${d}/do$(echo ${a%%://*} | tr '[:upper:]' '[:lower:]' )
+ ebuild_notice "debug" "fetcher program candidate for '${a}' is '${prg}'"
+ [[ -x "${prg}" ]] && break
+ done
+ if [[ -x "${prg}" ]] ; then
+ ${prg} "${a}" "${DISTDIR}/${aa}"
+ else
+ eerror "Don't know how to fetch '${a}'"
+ fi
+ else
+ if ! [[ "${old_aa}" != "${aa}" ]] ; then
+ ebuild_section "Can't fetch ${aa}"
+ old_aa="${aa}"
+ fi
+ fi
+ fi
+ done
+
+ for a in ${unique_aa} ; do
+ [[ -f ${DISTDIR}/${a} ]] || nofetch="${nofetch} ${a}"
+ done
+
+ if [[ -n "${nofetch}" ]] ; then
+ local c
+ echo
+ eerror "Couldn't fetch the following components:"
+ for c in ${nofetch} ; do
+ eerror " * ${c}"
+ done
+ echo
+ die "builtin_fetchbin failed"
+ fi
+}
+
+ebuild_f_fetchbin()
+{
+ local old_sandbox_write="${SANDBOX_WRITE}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}${DISTDIR}"
+ if hasq "fetchbin" ${RESTRICT} ; then
+ ebuild_section "Skipping builtin_fetchbin (RESTRICT)"
+ elif hasq "fetchbin" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping builtin_fetchbin (SKIP_FUNCTIONS)"
+ else
+ ebuild_section "Starting builtin_fetchbin"
+ builtin_fetchbin
+ ebuild_section "Done builtin_fetchbin"
+ fi
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${old_sandbox_write}"
+ true
+}
+
+
+
diff --git a/paludis/repositories/e/ebuild/builtin_init.bash b/paludis/repositories/e/ebuild/builtin_init.bash
new file mode 100644
index 000000000..4a3836bf1
--- /dev/null
+++ b/paludis/repositories/e/ebuild/builtin_init.bash
@@ -0,0 +1,95 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+builtin_init()
+{
+ export ROOT="${ROOT//+(\/)//}"
+
+ local a
+ for a in PALUDIS_NON_EMPTY_VARIABLES ${PALUDIS_NON_EMPTY_VARIABLES} ; do
+ [[ -z "${!a}" ]] && die "\$${a} unset or empty"
+ declare -r ${a}="${!a}"
+ done
+
+ for a in ${PALUDIS_DIRECTORY_VARIABLES} ; do
+ [[ -d "${!a}" ]] || die "\$${a} (\"${!a}\") not a directory"
+ done
+
+ for a in ${PALUDIS_DIRECTORY_IF_EXISTS_VARIABLES} ; do
+ [[ -e "${!a}" ]] && [[ ! -d "${!a}" ]] && \
+ die "\$${a} (\"${!a}\") exists but is not a directory"
+ done
+
+ for a in PALUDIS_TMPDIR ; do
+ if ! [[ -d "${!a}" ]] ; then
+ PALUDIS_EXTRA_DIE_MESSAGE="
+!!! '${!a}' should be a directory, but does not exist. For,
+!!! security reasons, Paludis will not try to create this directory
+!!! automatically. Please create it by hand and give it appropriate
+!!! permissions. Typically you should use:
+!!! mkdir ${!a}
+!!! chgrp ${PALUDIS_REDUCED_GID} ${!a}
+!!! chmod g+rwx ${!a}
+!!! chmod +s ${!a}
+!!! although other values may be more appropriate for your system.
+"
+ die "\$${a} (\"${!a}\") not a directory"
+ fi
+ done
+
+ if [[ -e "${PALUDIS_TMPDIR}/${CATEGORY}/${PF}" ]] ; then
+ if type -p chflags &>/dev/null; then
+ chflags -R 0 "${PALUDIS_TMPDIR}/${CATEGORY}/${PF}" || die "Couldn't remove flags from workdir"
+ fi
+ rm -fr "${PALUDIS_TMPDIR}/${CATEGORY}/${PF}" || die "Couldn't remove previous work"
+ fi
+
+ export WORKDIR="${PALUDIS_TMPDIR}/${CATEGORY}/${PF}/work"
+ mkdir -p "${WORKDIR}" || die "Couldn't create \$WORKDIR (\"${WORKDIR}\")"
+ declare -r WORKDIR="${WORKDIR}"
+
+ export T="${PALUDIS_TMPDIR}/${CATEGORY}/${PF}/temp/"
+ mkdir -p "${T}" || die "Couldn't create \$T (\"${T}\")"
+ declare -r T="${T}"
+ export HOME="${T}"
+ export TMPDIR="${T}"
+
+ export D="${PALUDIS_TMPDIR}/${CATEGORY}/${PF}/image/"
+ export D="${D//+(\/)//}"
+ mkdir -p "${D}" || die "Couldn't create \$D (\"${D}\")"
+ declare -r D="${D}"
+
+ export IMAGE="${D}"
+ declare -r IMAGE="${IMAGE}"
+
+ export S="${WORKDIR}/${P}"
+}
+
+ebuild_f_init()
+{
+ if hasq "init" ${RESTRICT} ; then
+ ebuild_section "Skipping builtin_init (RESTRICT)"
+ elif hasq "init" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping builtin_init (SKIP_FUNCTIONS)"
+ else
+ ebuild_section "Starting builtin_init"
+ builtin_init
+ ebuild_section "Done builtin_init"
+ fi
+}
+
diff --git a/paludis/repositories/e/ebuild/builtin_initbin.bash b/paludis/repositories/e/ebuild/builtin_initbin.bash
new file mode 100644
index 000000000..bdd9650d8
--- /dev/null
+++ b/paludis/repositories/e/ebuild/builtin_initbin.bash
@@ -0,0 +1,90 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+builtin_initbin()
+{
+ export ROOT="${ROOT//+(\/)//}"
+
+ local a
+ for a in P PV PR PN PVR PF CATEGORY PORTDIR \
+ DISTDIR KV PALUDIS_TMPDIR PALUDIS_EBUILD_LOG_LEVEL PALUDIS_EBUILD_DIR \
+ CHOST PALUDIS_COMMAND ROOT PALUDIS_LOADSAVEENV_DIR ; do
+ [[ -z "${!a}" ]] && die "\$${a} unset or empty"
+ done
+
+ for a in DISTDIR ; do
+ [[ -d "${!a}" ]] || die "\$${a} (\"${!a}\") not a directory"
+ done
+
+ if [[ -e "${PALUDIS_TMPDIR}/${CATEGORY}/${PF}" ]] ; then
+ if type -p chflags &>/dev/null; then
+ chflags -R 0 "${PALUDIS_TMPDIR}/${CATEGORY}/${PF}" || die "Couldn't remove flags from workdir"
+ fi
+ rm -fr "${PALUDIS_TMPDIR}/${CATEGORY}/${PF}" || die "Couldn't remove previous work"
+ fi
+
+ export WORKDIR="${PALUDIS_TMPDIR}/${CATEGORY}/${PF}/work"
+ mkdir -p "${WORKDIR}" || die "Couldn't create \$WORKDIR (\"${WORKDIR}\")"
+
+ export T="${PALUDIS_TMPDIR}/${CATEGORY}/${PF}/temp/"
+ mkdir -p "${T}" || die "Couldn't create \$T (\"${T}\")"
+ export HOME="${T}"
+
+ export D="${PALUDIS_TMPDIR}/${CATEGORY}/${PF}/image/"
+ export D="${D//+(\/)//}"
+ mkdir -p "${D}" || die "Couldn't create \$D (\"${D}\")"
+
+ export IMAGE="${D}"
+
+ export S="${WORKDIR}/${P}"
+
+ [[ -n "${B}" ]] && unpack --binary --only .paludis-binpkg-environment ${B}
+
+ [[ -f "${IMAGE}/.paludis-binpkg-environment" ]] || \
+ die "No saved environment in binary tarball"
+
+ local save_PALUDIS_EXTRA_DIE_MESSAGE="${PALUDIS_EXTRA_DIE_MESSAGE}"
+
+ echo ebuild_scrub_environment "${IMAGE}/.paludis-binpkg-environment" 1>&2
+ ebuild_scrub_environment "${IMAGE}/.paludis-binpkg-environment" \
+ || die "Can't load saved environment for cleaning"
+
+ echo source "${IMAGE}/.paludis-binpkg-environment" 1>&2
+ source "${IMAGE}/.paludis-binpkg-environment" \
+ || die "Can't load saved environment"
+
+ export PALUDIS_EXTRA_DIE_MESSAGE="${save_PALUDIS_EXTRA_DIE_MESSAGE}"
+
+ echo rm "${IMAGE}/.paludis-binpkg-environment" 1>&2
+ rm "${IMAGE}/.paludis-binpkg-environment"
+}
+
+ebuild_f_initbin()
+{
+ if hasq "initbin" ${RESTRICT} ; then
+ ebuild_section "Skipping builtin_initbin (RESTRICT)"
+ elif hasq "init" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping builtin_initbin (SKIP_FUNCTIONS)"
+ else
+ ebuild_section "Starting builtin_initbin"
+ builtin_initbin
+ ebuild_section "Done builtin_initbin"
+ fi
+}
+
+
diff --git a/paludis/repositories/e/ebuild/builtin_loadenv.bash b/paludis/repositories/e/ebuild/builtin_loadenv.bash
new file mode 100644
index 000000000..4b057c0c9
--- /dev/null
+++ b/paludis/repositories/e/ebuild/builtin_loadenv.bash
@@ -0,0 +1,48 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+builtin_loadenv()
+{
+ [[ -d "${PALUDIS_LOADSAVEENV_DIR}" ]] \
+ || die "\$PALUDIS_LOADSAVEENV_DIR (\"${PALUDIS_LOADSAVEENV_DIR}\") not a directory"
+ [[ -f "${PALUDIS_LOADSAVEENV_DIR}/loadsaveenv" ]] || \
+ die "${PALUDIS_LOADSAVEENV_DIR}/loadsaveenv not a file"
+ source ${PALUDIS_LOADSAVEENV_DIR}/loadsaveenv
+}
+
+ebuild_f_loadenv()
+{
+ local old_sandbox_write="${SANDBOX_WRITE}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && \
+ SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}${PALUDIS_LOADSAVEENV_DIR%/}/"
+
+ if hasq "loadenv" ${RESTRICT} ; then
+ ebuild_section "Skipping builtin_loadenv (RESTRICT)"
+ elif hasq "loadenv" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping builtin_loadenv (SKIP_FUNCTIONS)"
+ else
+ ebuild_section "Starting builtin_loadenv"
+ builtin_loadenv
+ ebuild_section "Done builtin_loadenv"
+ fi
+
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${old_sandbox_write}"
+ true
+}
+
+
diff --git a/paludis/repositories/e/ebuild/builtin_merge.bash b/paludis/repositories/e/ebuild/builtin_merge.bash
new file mode 100644
index 000000000..d922e92a5
--- /dev/null
+++ b/paludis/repositories/e/ebuild/builtin_merge.bash
@@ -0,0 +1,144 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+# !!! This is used for compatibility with older Paludis versions only. When
+# !!! upgrading from versions below 0.20.0, this code will be used until the
+# !!! 'restart paludis' exec kicks in.
+
+builtin_merge()
+{
+ ebuild_section "Merging to '${ROOT:-/}'..."
+
+ shopt -q dotglob
+ local olddotglob=$?
+ shopt -s dotglob
+
+ local v=$(vdb_path)
+ if [[ -z "${v}" ]] ; then
+ v=${ROOT}/var/db/pkg
+ fi
+ local dbdir="${v}/${CATEGORY}/${PF}"
+ ebuild_section "Writing VDB entry to '${dbdir}'..."
+ install -d "${dbdir}" || die "couldn't make pkg db directory (\"${dbdir}\")"
+ install -d "${v}/".cache || die "couldn't make pkg db cache"
+
+ local v VDB_FORMAT="paludis-2" COUNTER="$(date +%s )"
+ for v in CATEGORY CBUILD CHOST COUNTER DEPEND DESCRIPTION EAPI \
+ FEATURES HOMEPAGE INHERITED IUSE KEYWORDS LICENSE PDEPEND PF \
+ PROVIDE RDEPEND SLOT SRC_URI USE CONFIG_PROTECT CONFIG_PROTECT_MASK \
+ VDB_FORMAT PKGMANAGER ; do
+ echo "${!v}" > "${dbdir}"/${v} || die "pkg db write ${v} failed"
+ ebuild_notice "debug" "Writing VDB key ${v}=${!v}"
+ done
+ for v in ASFLAGS CBUILD CC CFLAGS CHOST CTARGET CXX CXXFLAGS \
+ EXTRA_ECONF EXTRA_EINSTALL EXTRA_EMAKE LDFLAGS LIBCXXFLAGS \
+ REPOSITORY ; do
+ [[ -z "${!v}" ]] && continue
+ echo "${!v}" > "${dbdir}"/${v} || die "pkg db write ${v} failed"
+ ebuild_notice "debug" "Writing VDB key ${v}=${!v}"
+ done
+
+ if [[ -n ${PALUDIS_EBUILD_OVERRIDE_CONFIG_PROTECT} ]]; then
+ CONFIG_PROTECT=${PALUDIS_EBUILD_OVERRIDE_CONFIG_PROTECT}
+ fi
+ if [[ -n ${PALUDIS_EBUILD_OVERRIDE_CONFIG_PROTECT_MASK} ]]; then
+ CONFIG_PROTECT_MASK=${PALUDIS_EBUILD_OVERRIDE_CONFIG_PROTECT_MASK}
+ fi
+
+ export CONFIG_PROTECT="${CONFIG_PROTECT}"
+ export CONFIG_PROTECT_MASK="${CONFIG_PROTECT_MASK}"
+
+ [[ -f "${EBUILD}" ]] && cp "${EBUILD}" ${dbdir}/
+
+ local reinstall=
+ if [[ -f "${dbdir}/CONTENTS" ]] ; then
+ mv "${dbdir}/CONTENTS" "${dbdir}/OLDCONTENTS" || die "save contents failed"
+ reinstall="yes"
+ fi
+
+ ebuild_notice "debug" "Writing VDB environment.bz2"
+ for v in ${USE_EXPAND} ; do
+ ebuild_notice "debug" "USE_EXPAND ${v}=${!v}"
+ done
+ ( set ; export -p | sed 's:^declare -rx:declare -x:' ) | bzip2 > ${dbdir}/environment.bz2
+ > ${dbdir}/CONTENTS
+
+ local merge=${PALUDIS_EBUILD_DIR}/merge
+ [[ -x "${merge}" ]] || merge="${PALUDIS_EBUILD_DIR_FALLBACK}"/merge
+ [[ -x "${merge}" ]] || die "Couldn't find merge"
+
+ local unmerge=${PALUDIS_EBUILD_DIR}/unmerge
+ [[ -x "${unmerge}" ]] || unmerge="${PALUDIS_EBUILD_DIR_FALLBACK}"/unmerge
+ [[ -x "${unmerge}" ]] || die "Couldn't find unmerge"
+
+ if [[ -n "${D}" ]] && [[ -d "${D}" ]] ; then
+ install -d "${ROOT%/}/" || die "couldn't make \${ROOT} (\"${ROOT}\")"
+ if [[ -d "${D}" ]] ; then
+ ${merge} "${D%/}/" "${ROOT%/}/" "${dbdir}/CONTENTS" || die "merge failed"
+ fi
+ fi
+
+ echo hash -r
+ hash -r
+
+ if ! /bin/sh -c 'echo Good, our shell is still usable' ; then
+ echo "Looks like our shell broke. Trying an ldconfig to fix it..."
+ ldconfig -r ${ROOT}
+ fi
+
+ if [[ -n "${reinstall}" ]] ; then
+ ${unmerge} "${ROOT%/}/" "${dbdir}/OLDCONTENTS" || die "unmerge failed"
+
+ echo hash -r
+ hash -r
+
+ if ! /bin/sh -c 'echo Good, our shell is still usable' ; then
+ echo "Looks like our shell broke. Trying an ldconfig to fix it..."
+ ldconfig -r ${ROOT}
+ fi
+
+ rm -f "${dbdir}/OLDCONTENTS"
+ fi
+
+ [[ $olddotglob != 0 ]] && shopt -u dotglob
+ shopt -q dotglob
+ [[ $olddotglob == $? ]] || ebuild_notice "warning" "shopt dotglob restore failed"
+}
+
+ebuild_f_merge()
+{
+ local old_sandbox_write="${SANDBOX_WRITE}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}${ROOT%/}/"
+ local old_sandbox_on="${SANDBOX_ON}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && [[ "$(canonicalise ${ROOT} )" != "/" ]] || SANDBOX_ON=0
+
+ if hasq "merge" ${RESTRICT} ; then
+ ebuild_section "Skipping builtin_merge (RESTRICT)"
+ elif hasq "merge" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping builtin_merge (SKIP_FUNCTIONS)"
+ else
+ ebuild_section "Starting builtin_merge"
+ builtin_merge
+ ebuild_section "Done builtin_merge"
+ fi
+
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${old_sandbox_write}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_ON="${old_sandbox_on}"
+ true
+}
+
diff --git a/paludis/repositories/e/ebuild/builtin_metadata.bash b/paludis/repositories/e/ebuild/builtin_metadata.bash
new file mode 100644
index 000000000..36d181bd5
--- /dev/null
+++ b/paludis/repositories/e/ebuild/builtin_metadata.bash
@@ -0,0 +1,41 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+ebuild_f_metadata()
+{
+ local key
+
+ for a in ${PALUDIS_EBUILD_MUST_NOT_SET_VARIABLES} ; do
+ [[ -z "${!a}" ]] || die "\$${a} must not be set"
+ done
+
+ for key in ${EBUILD_METADATA_VARIABLES} ; do
+ set -o noglob
+ local k=${!key}
+ k=${k//\\/\\\\}
+ k=${k//\"/\\\"}
+ k=${k//\$/\\\$}
+ echo "${key}=\""${k}"\""
+ set +o noglob
+ done
+}
+
diff --git a/paludis/repositories/e/ebuild/builtin_prepare.bash b/paludis/repositories/e/ebuild/builtin_prepare.bash
new file mode 100644
index 000000000..4a1195e5f
--- /dev/null
+++ b/paludis/repositories/e/ebuild/builtin_prepare.bash
@@ -0,0 +1,49 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+builtin_prepare()
+{
+ export ROOT="${ROOT//+(\/)//}"
+
+ local a
+ for a in PF CATEGORY PALUDIS_TMPDIR ; do
+ [[ -z "${!a}" ]] && die "\$${a} unset or empty"
+ done
+
+ if [[ -e "${PALUDIS_TMPDIR}/${CATEGORY}/${PF}" ]] ; then
+ if type -p chflags &>/dev/null; then
+ chflags -R 0 "${PALUDIS_TMPDIR}/${CATEGORY}/${PF}" || die "Couldn't remove flags from workdir"
+ fi
+ rm -fr "${PALUDIS_TMPDIR}/${CATEGORY}/${PF}" || die "Couldn't remove previous work"
+ fi
+}
+
+ebuild_f_prepare()
+{
+ if hasq "prepare" ${RESTRICT} ; then
+ ebuild_section "Skipping builtin_prepare (RESTRICT)"
+ elif hasq "prepare" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping builtin_prepare (SKIP_FUNCTIONS)"
+ else
+ ebuild_section "Starting builtin_prepare"
+ builtin_prepare
+ ebuild_section "Done builtin_prepare"
+ fi
+}
+
+
diff --git a/paludis/repositories/e/ebuild/builtin_saveenv.bash b/paludis/repositories/e/ebuild/builtin_saveenv.bash
new file mode 100644
index 000000000..097578f64
--- /dev/null
+++ b/paludis/repositories/e/ebuild/builtin_saveenv.bash
@@ -0,0 +1,54 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+builtin_saveenv()
+{
+ [[ -d "${PALUDIS_LOADSAVEENV_DIR}" ]] || die "\$PALUDIS_LOADSAVEENV_DIR (\"${PALUDIS_LOADSAVEENV_DIR}\") not a directory"
+ [[ -f "${PALUDIS_LOADSAVEENV_DIR}/loadsaveenv" ]] && rm -f "${PALUDIS_LOADSAVEENV_DIR}/loadsaveenv"
+ ( set ; export -p ) | sed \
+ -e '/^\(declare -[rx]\+ \)\?SANDBOX_/d' \
+ -e '/^\(declare -[rx]\+ \)\?.\?[UP]ID/d' \
+ -e '/^\(declare -[rx]\+ \)\?BASH_VERSINFO/d' \
+ -e '/^\(declare -[rx]\+ \)\?PALUDIS_LOADSAVEENV_DIR/d' \
+ -e '/^\(declare -[rx]\+ \)\?PALUDIS_DO_NOTHING_SANDBOXY/d' \
+ -e '/^\(declare -[rx]\+ \)\?SHELLOPTS/d' \
+ -e '/^\(declare -[rx]\+ \)\?EBUILD_KILL_PID/d' \
+ -e 's:^declare -rx:declare -x:' \
+ -e 's:^declare -x :export :' \
+ > ${PALUDIS_LOADSAVEENV_DIR}/loadsaveenv
+}
+
+ebuild_f_saveenv()
+{
+ local old_sandbox_write="${SANDBOX_WRITE}"
+ SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}${PALUDIS_LOADSAVEENV_DIR%/}/"
+
+ if hasq "saveenv" ${RESTRICT} ; then
+ ebuild_section "Skipping builtin_saveenv (RESTRICT)"
+ elif hasq "saveenv" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping builtin_saveenv (SKIP_FUNCTIONS)"
+ else
+ ebuild_section "Starting builtin_saveenv"
+ builtin_saveenv
+ ebuild_section "Done builtin_saveenv"
+ fi
+
+ SANDBOX_WRITE="${old_sandbox_write}"
+ true
+}
+
diff --git a/paludis/repositories/e/ebuild/builtin_strip.bash b/paludis/repositories/e/ebuild/builtin_strip.bash
new file mode 100644
index 000000000..9a4168e7c
--- /dev/null
+++ b/paludis/repositories/e/ebuild/builtin_strip.bash
@@ -0,0 +1,80 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# 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
+
+builtin_strip()
+{
+ STRIP=${STRIP:-${CHOST}-strip}
+ if ! type -p -- ${STRIP} >/dev/null; then
+ STRIP=strip
+ fi
+ PALUDIS_STRIP_FLAGS=${PALUDIS_STRIP_FLAGS:---strip-unneeded}
+
+ if [[ "${PALUDIS_DEBUG_BUILD}" == "split" ]] ; then
+ OBJCOPY=${OBJCOPY:-${CHOST}-objcopy}
+ if ! type -p -- "${OBJCOPY}" &>/dev/null ; then
+ OBJCOPY=objcopy
+ fi
+ if ! type -p -- "${OBJCOPY}" &>/dev/null ; then
+ die "Can't work out what OBJCOPY should be"
+ fi
+ fi
+
+ for fn in $(find "${D}" -type f \
+ \( -perm -0100 -or -perm -0010 -or -perm -0001 -or -name '*.so' -or -name '*.so.*' \)); do
+ local ft=$(file "${fn}")
+ if [[ $? != 0 || -z ${ft} ]]; then
+ return 1
+ fi
+
+ if [[ ${ft} == *"current ar archive"* ]]; then
+ if [[ "${PALUDIS_DEBUG_BUILD}" != "internal" ]] ; then
+ echo ${STRIP} -g "${fn}"
+ ${STRIP} -g "${fn}"
+ fi
+ elif [[ ${ft} == *"SB executable"* || ${ft} == *"SB shared object"* ]]; then
+ if [[ "${PALUDIS_DEBUG_BUILD}" == "split" ]] ; then
+ local fd="${D}usr/lib/debug/${fn:${#D}}.debug"
+ mkdir -p "$(dirname "${fd}" )"
+ echo ${OBJCOPY} --only-keep-debug "${fn}" "${fd}"
+ ${OBJCOPY} --only-keep-debug "${fn}" "${fd}"
+ echo ${OBJCOPY} --add-gnu-debuglink="${fd}" "${fn}"
+ ${OBJCOPY} --add-gnu-debuglink="${fd}" "${fn}"
+ chmod a-x,o-w "${fd}"
+ fi
+ if [[ "${PALUDIS_DEBUG_BUILD}" != "internal" ]] ; then
+ echo ${STRIP} ${PALUDIS_STRIP_FLAGS} "${fn}"
+ ${STRIP} ${PALUDIS_STRIP_FLAGS} "${fn}"
+ fi
+ fi
+ done
+}
+
+ebuild_f_strip()
+{
+ if hasq "strip" ${RESTRICT} ; then
+ ebuild_section "Skipping builtin_strip (RESTRICT)"
+ elif hasq "strip" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping builtin_strip (SKIP_FUNCTIONS)"
+ else
+ ebuild_section "Starting builtin_strip"
+ builtin_strip
+ ebuild_section "Done builtin_strip"
+ fi
+}
+
diff --git a/paludis/repositories/e/ebuild/builtin_tidyup.bash b/paludis/repositories/e/ebuild/builtin_tidyup.bash
new file mode 100644
index 000000000..8927d23b8
--- /dev/null
+++ b/paludis/repositories/e/ebuild/builtin_tidyup.bash
@@ -0,0 +1,43 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+builtin_tidyup()
+{
+ if [[ -e "${PALUDIS_TMPDIR}/${CATEGORY}/${PF}" ]] ; then
+ if type -p chflags &>/dev/null; then
+ echo chflags -R 0 "${PALUDIS_TMPDIR}/${CATEGORY}/${PF}" 1>&2
+ chflags -R 0 "${PALUDIS_TMPDIR}/${CATEGORY}/${PF}" || die "Couldn't remove flags from workdir"
+ fi
+ echo rm -fr "${PALUDIS_TMPDIR}/${CATEGORY}/${PF}" 1>&2
+ rm -fr "${PALUDIS_TMPDIR}/${CATEGORY}/${PF}" || die "Couldn't remove work"
+ fi
+}
+
+ebuild_f_tidyup()
+{
+ if hasq "tidyup" ${RESTRICT} ; then
+ ebuild_section "Skipping builtin_tidyup (RESTRICT)"
+ elif hasq "tidyup" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping builtin_tidyup (SKIP_FUNCTIONS)"
+ else
+ ebuild_section "Starting builtin_tidyup"
+ builtin_tidyup
+ ebuild_section "Done builtin_tidyup"
+ fi
+}
+
diff --git a/paludis/repositories/e/ebuild/builtin_unmerge.bash b/paludis/repositories/e/ebuild/builtin_unmerge.bash
new file mode 100644
index 000000000..e358d8a3a
--- /dev/null
+++ b/paludis/repositories/e/ebuild/builtin_unmerge.bash
@@ -0,0 +1,115 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+builtin_unmerge()
+{
+ local v=$(${PALUDIS_COMMAND} --configuration-variable installed location 2>/dev/null )
+ if [[ -z "${v}" ]] ; then
+ v=${ROOT}/var/db/pkg
+ fi
+
+ local dbdir="${v}/${CATEGORY}/${PF}" entry
+ [[ -d "${dbdir}" ]] || die "couldn't find pkg db directory (\"${dbdir}\")"
+
+ for v in CATEGORY CBUILD CHOST DEPEND DESCRIPTION EAPI \
+ FEATURES HOMEPAGE INHERITED IUSE KEYWORDS LICENSE PDEPEND PF \
+ PROVIDE RDEPEND SLOT SRC_URI USE CONFIG_PROTECT CONFIG_PROTECT_MASK \
+ VDB_FORMAT ASFLAGS CBUILD CC CFLAGS CHOST CTARGET CXX CXXFLAGS \
+ EXTRA_ECONF EXTRA_EINSTALL EXTRA_EMAKE LDFLAGS LIBCXXFLAGS \
+ REPOSITORY ; do
+ if [[ -f "${dbdir}/${v}" ]] ; then
+ eval "${v}=\$(< ${dbdir}/${v} ) || die \"Load key ${v} failed\""
+ else
+ eval "${v}="
+ fi
+ done
+
+ if [[ -f ${dbdir}/CONFIG_PROTECT ]]; then
+ CONFIG_PROTECT="$(< ${dbdir}/CONFIG_PROTECT) ${CONFIG_PROTECT}"
+ if [[ -f ${dbdir}/CONFIG_PROTECT_MASK ]]; then
+ CONFIG_PROTECT_MASK="$(< ${dbdir}/CONFIG_PROTECT_MASK)"
+ fi
+ else
+ local old_CONFIG_PROTECT="${CONFIG_PROTECT:+${CONFIG_PROTECT} }/etc"
+ eval $(bzcat "${dbdir}/environment.bz2" | while read line; do
+ line=${line//\'}
+ if [[ ${line%%=*} == CONFIG_PROTECT ]]; then
+ echo "CONFIG_PROTECT='${line#*=} ${CONFIG_PROTECT}'"
+ elif [[ ${line%%=*} == CONFIG_PROTECT_MASK ]]; then
+ echo "CONFIG_PROTECT_MASK='${line#*=}'"
+ fi
+ done)
+
+ # catalyst creates things with an empty CONFIG_PROTECT...
+ if [[ -z "${CONFIG_PROTECT// }" ]] ; then
+ ewarn "CONFIG_PROTECT from environment.bz2 is empty"
+ ewarn "Using a fallback of '${old_CONFIG_PROTECT}'"
+ CONFIG_PROTECT="${old_CONFIG_PROTECT}"
+ fi
+ fi
+
+ if [[ -n ${PALUDIS_EBUILD_OVERRIDE_CONFIG_PROTECT} ]]; then
+ CONFIG_PROTECT=${PALUDIS_EBUILD_OVERRIDE_CONFIG_PROTECT}
+ fi
+ if [[ -n ${PALUDIS_EBUILD_OVERRIDE_CONFIG_PROTECT_MASK} ]]; then
+ CONFIG_PROTECT_MASK=${PALUDIS_EBUILD_OVERRIDE_CONFIG_PROTECT_MASK}
+ fi
+
+ export CONFIG_PROTECT="${CONFIG_PROTECT}"
+ export CONFIG_PROTECT_MASK="${CONFIG_PROTECT_MASK}"
+
+ local unmerge=${PALUDIS_EBUILD_DIR}/unmerge
+ [[ -x "${unmerge}" ]] || unmerge="${PALUDIS_EBUILD_DIR_FALLBACK}"/unmerge
+ [[ -x "${unmerge}" ]] || die "Couldn't find unmerge"
+
+ ${unmerge} "${ROOT}/" "${dbdir}/CONTENTS" || die "unmerge failed"
+
+ echo hash -r
+ hash -r
+
+ if ! /bin/sh -c 'echo Good, our shell is still usable' ; then
+ echo "Looks like our shell broke. Trying an ldconfig to fix it..."
+ ldconfig -r ${ROOT}
+ fi
+
+ rm -fr "${dbdir}"
+}
+
+ebuild_f_unmerge()
+{
+ local old_sandbox_write="${SANDBOX_WRITE}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}${ROOT%/}/"
+ local old_sandbox_on="${SANDBOX_ON}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && [[ "$(canonicalise ${ROOT} )" != "/" ]] || SANDBOX_ON=0
+
+ if hasq "unmerge" ${RESTRICT} ; then
+ ebuild_section "Skipping builtin_unmerge (RESTRICT)"
+ elif hasq "unmerge" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping builtin_unmerge (SKIP_FUNCTIONS)"
+ else
+ ebuild_section "Starting builtin_unmerge"
+ builtin_unmerge
+ ebuild_section "Done builtin_unmerge"
+ fi
+
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${old_sandbox_write}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_ON="${old_sandbox_on}"
+ true
+}
+
+
diff --git a/paludis/repositories/e/ebuild/builtin_unpackbin.bash b/paludis/repositories/e/ebuild/builtin_unpackbin.bash
new file mode 100644
index 000000000..975af78ba
--- /dev/null
+++ b/paludis/repositories/e/ebuild/builtin_unpackbin.bash
@@ -0,0 +1,40 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+builtin_unpackbin()
+{
+ [[ -n "${B}" ]] && unpack --binary ${B}
+ rm -f ${D}/.paludis-binpkg-environment
+}
+
+ebuild_f_unpackbin()
+{
+ cd ${WORKDIR} || die "cd to \${WORKDIR} (\"${WORKDIR}\") failed"
+
+ if hasq "unpackbin" ${RESTRICT} ; then
+ ebuild_section "Skipping builtin_unpackbin (RESTRICT)"
+ elif hasq "unpackbin" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping builtin_unpackbin (SKIP_FUNCTIONS)"
+ else
+ ebuild_section "Starting builtin_unpackbin"
+ builtin_unpackbin
+ ebuild_section "Done builtin_unpackbin"
+ fi
+}
+
+
diff --git a/paludis/repositories/e/ebuild/builtin_variable.bash b/paludis/repositories/e/ebuild/builtin_variable.bash
new file mode 100644
index 000000000..e140188d7
--- /dev/null
+++ b/paludis/repositories/e/ebuild/builtin_variable.bash
@@ -0,0 +1,23 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+ebuild_f_variable()
+{
+ echo "${!PALUDIS_VARIABLE}"
+}
+
diff --git a/paludis/repositories/e/ebuild/die_functions.bash b/paludis/repositories/e/ebuild/die_functions.bash
new file mode 100644
index 000000000..cfff825c4
--- /dev/null
+++ b/paludis/repositories/e/ebuild/die_functions.bash
@@ -0,0 +1,58 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+EBUILD_KILL_PID=$$
+declare -r EBUILD_KILL_PID
+
+alias die='diefunc "$FUNCNAME" "$LINENO"'
+alias assert='_pipestatus="${PIPESTATUS[*]}"; [[ -z "${_pipestatus//[ 0]/}" ]] || diefunc "$FUNCNAME" "$LINENO" "$_pipestatus"'
+trap 'echo "die trap: exiting with error." 1>&2 ; exit 250' 15
+
+diefunc()
+{
+ local func="$1" line="$2"
+ shift 2
+ echo 1>&2
+ echo "!!! ERROR in ${CATEGORY:-?}/${PF:-?}:" 1>&2
+ echo "!!! In ${func:-?} at line ${line:-?}" 1>&2
+ echo "!!! ${*:-(no message provided)}" 1>&2
+ echo 1>&2
+
+ echo "!!! Call stack:" 1>&2
+ for (( n = 1 ; n < ${#FUNCNAME[@]} ; ++n )) ; do
+ funcname=${FUNCNAME[${n}]}
+ sourcefile=${BASH_SOURCE[${n}]}
+ lineno=${BASH_LINENO[$(( n - 1 ))]}
+ echo "!!! * ${funcname} (${sourcefile}:${lineno})" 1>&2
+ done
+ echo 1>&2
+
+ if [[ -n "${PALUDIS_EXTRA_DIE_MESSAGE}" ]] ; then
+ echo "${PALUDIS_EXTRA_DIE_MESSAGE}" 1>&2
+ echo 1>&2
+ fi
+
+ kill ${EBUILD_KILL_PID}
+ exit 249
+}
+
+
diff --git a/paludis/repositories/e/ebuild/digests/Makefile.am b/paludis/repositories/e/ebuild/digests/Makefile.am
new file mode 100644
index 000000000..d4ad64597
--- /dev/null
+++ b/paludis/repositories/e/ebuild/digests/Makefile.am
@@ -0,0 +1,31 @@
+MAINTAINERCLEANFILES = Makefile.in
+CLEANFILES = *~
+SUBDIRS = .
+
+libexecprogdir = $(libexecdir)/paludis/digests/
+
+libexecprog_PROGRAMS = \
+ dosha256 \
+ dormd160 \
+ domd5
+
+dosha256_SOURCES = dosha256.cc
+dosha256_LDADD = $(top_builddir)/paludis/digests/libpaludisdigests.la
+
+dormd160_SOURCES = dormd160.cc
+dormd160_LDADD = $(top_builddir)/paludis/digests/libpaludisdigests.la
+
+domd5_SOURCES = domd5.cc
+domd5_LDADD = $(top_builddir)/paludis/digests/libpaludisdigests.la
+
+TESTS_ENVIRONMENT = env \
+ PALUDIS_EBUILD_DIR="$(srcdir)/ebuild/" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ bash $(top_srcdir)/test/run_test.sh
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+
diff --git a/paludis/repositories/e/ebuild/digests/domd5.cc b/paludis/repositories/e/ebuild/digests/domd5.cc
new file mode 100644
index 000000000..d139f472e
--- /dev/null
+++ b/paludis/repositories/e/ebuild/digests/domd5.cc
@@ -0,0 +1,54 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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/digests/md5.hh>
+#include <iostream>
+#include <cstdlib>
+#include <fstream>
+
+int
+main(int argc, char * argv[])
+{
+ if (argc >= 3)
+ {
+ std::cerr << "usage: " << argv[0] << " [filename]" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ if (argc == 2)
+ {
+ std::ifstream f(argv[1]);
+ if (! f)
+ {
+ std::cerr << argv[0] << ": could not open '" << argv[1] << "'" << std::endl;
+ return EXIT_FAILURE;
+ }
+ paludis::MD5 sum(f);
+ std::cout << sum.hexsum() << std::endl;
+ }
+ else
+ {
+ paludis::MD5 sum(std::cin);
+ std::cout << sum.hexsum() << std::endl;
+ }
+
+}
+
+
+
diff --git a/paludis/repositories/e/ebuild/digests/dormd160.cc b/paludis/repositories/e/ebuild/digests/dormd160.cc
new file mode 100644
index 000000000..47fcd7f00
--- /dev/null
+++ b/paludis/repositories/e/ebuild/digests/dormd160.cc
@@ -0,0 +1,53 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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/digests/rmd160.hh>
+#include <iostream>
+#include <fstream>
+#include <cstdlib>
+
+int
+main(int argc, char * argv[])
+{
+ if (argc >= 3)
+ {
+ std::cerr << "usage: " << argv[0] << " [filename]" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ if (argc == 2)
+ {
+ std::ifstream f(argv[1]);
+ if (! f)
+ {
+ std::cerr << argv[0] << ": could not open '" << argv[1] << "'" << std::endl;
+ return EXIT_FAILURE;
+ }
+ paludis::RMD160 sum(f);
+ std::cout << sum.hexsum() << std::endl;
+ }
+ else
+ {
+ paludis::RMD160 sum(std::cin);
+ std::cout << sum.hexsum() << std::endl;
+ }
+
+}
+
+
diff --git a/paludis/repositories/e/ebuild/digests/dosha256.cc b/paludis/repositories/e/ebuild/digests/dosha256.cc
new file mode 100644
index 000000000..056ce5a2a
--- /dev/null
+++ b/paludis/repositories/e/ebuild/digests/dosha256.cc
@@ -0,0 +1,52 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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/digests/sha256.hh>
+#include <iostream>
+#include <cstdlib>
+#include <fstream>
+
+int
+main(int argc, char * argv[])
+{
+ if (argc >= 3)
+ {
+ std::cerr << "usage: " << argv[0] << " [filename]" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ if (argc == 2)
+ {
+ std::ifstream f(argv[1]);
+ if (! f)
+ {
+ std::cerr << argv[0] << ": could not open '" << argv[1] << "'" << std::endl;
+ return EXIT_FAILURE;
+ }
+ paludis::SHA256 sum(f);
+ std::cout << sum.hexsum() << std::endl;
+ }
+ else
+ {
+ paludis::SHA256 sum(std::cin);
+ std::cout << sum.hexsum() << std::endl;
+ }
+
+}
+
diff --git a/paludis/repositories/e/ebuild/ebuild.bash b/paludis/repositories/e/ebuild/ebuild.bash
new file mode 100755
index 000000000..4c2a59f22
--- /dev/null
+++ b/paludis/repositories/e/ebuild/ebuild.bash
@@ -0,0 +1,424 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+unalias -a
+set +C
+unset GZIP BZIP BZIP2 CDPATH GREP_OPTIONS GREP_COLOR GLOBIGNORE
+eval unset LANG ${!LC_*}
+
+# The list below should include all variables from all EAPIs
+EBUILD_METADATA_VARIABLES="DEPEND RDEPEND PDEPEND IUSE SRC_URI RESTRICT \
+ LICENSE KEYWORDS INHERITED PROVIDE HOMEPAGE DESCRIPTION DEPENDENCIES \
+ E_IUSE E_DEPEND E_RDEPEND E_PDEPEND E_KEYWORDS"
+unset -v ${EBUILD_METADATA_VARIABLES}
+# These can be set by C++
+EBUILD_METADATA_VARIABLES="${EBUILD_METADATA_VARIABLES} SLOT EAPI"
+
+if [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] ; then
+ export SANDBOX_PREDICT="${SANDBOX_PREDICT+${SANDBOX_PREDICT}:}"
+ export SANDBOX_PREDICT="${SANDBOX_PREDICT}/proc/self/maps:/dev/console:/dev/random"
+ export SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}"
+ export SANDBOX_WRITE="${SANDBOX_WRITE}/dev/shm:/dev/stdout:/dev/stderr:/dev/null:/dev/tty:/dev/pts"
+ export SANDBOX_WRITE="${SANDBOX_WRITE}:${PALUDIS_TMPDIR}:/var/cache"
+ export SANDBOX_WRITE="${SANDBOX_WRITE}:/proc/self/attr:/proc/self/task:/selinux/context"
+ [[ -n "${CCACHE_DIR}" ]] && export SANDBOX_WRITE="${SANDBOX_WRITE}:${CCACHE_DIR}"
+ export SANDBOX_ON="1"
+ export SANDBOX_BASHRC="/dev/null"
+ unset BASH_ENV
+fi
+
+shopt -s expand_aliases
+shopt -s extglob
+
+export EBUILD_PROGRAM_NAME="$0"
+
+if [[ -n "${PALUDIS_EBUILD_DIR_FALLBACK}" ]] ; then
+ export PATH="${PALUDIS_EBUILD_DIR_FALLBACK}/utils:${PATH}"
+fi
+export PATH="${PALUDIS_EBUILD_DIR}/utils:${PATH}"
+for p in ${PALUDIS_UTILITY_PATH_SUFFIXES} ; do
+ export PATH="${PALUDIS_EBUILD_DIR}/utils/${p}:${PATH}"
+done
+EBUILD_MODULES_DIR=$(canonicalise $(dirname $0 ) )
+if ! [[ -d ${EBUILD_MODULES_DIR} ]] ; then
+ echo "${EBUILD_MODULES_DIR} is not a directory" 1>&2
+ exit 123
+fi
+export PALUDIS_EBUILD_MODULES_DIR="${EBUILD_MODULES_DIR}"
+
+for p in ${PALUDIS_EBUILD_MODULE_SUFFIXES}; do
+ EBUILD_MODULES_DIRS="${EBUILD_MODULES_DIRS} ${EBUILD_MODULES_DIR}/${p}"
+done
+EBUILD_MODULES_DIRS="${EBUILD_MODULES_DIRS} ${EBUILD_MODULES_DIR}"
+
+ebuild_load_module()
+{
+ for d in ${EBUILD_MODULES_DIRS}; do
+ if [[ -f "${d}/${1}.bash" ]]; then
+ if ! source "${d}/${1}.bash"; then
+ type die &>/dev/null && die "Error loading module ${1}"
+ echo "Error loading module ${1}" 1>&2
+ exit 123
+ fi
+ return
+ fi
+ done
+ type die &>/dev/null && die "Couldn't find module ${1}"
+ echo "Couldn't find module ${1}" 1>&2
+ exit 123
+}
+
+ebuild_load_module die_functions
+ebuild_load_module echo_functions
+ebuild_load_module kernel_functions
+ebuild_load_module sandbox
+ebuild_load_module portage_stubs
+ebuild_load_module list_functions
+ebuild_load_module multilib_functions
+ebuild_load_module install_functions
+ebuild_load_module build_functions
+ebuild_load_module eclass_functions
+ebuild_load_module exlib_functions
+ebuild_load_module work_around_broken_utilities
+
+export PALUDIS_HOME="$(canonicalise ${PALUDIS_HOME:-${HOME}} )"
+
+ebuild_source_profile()
+{
+ if [[ -f ${1}/parent ]] ; then
+ while read line ; do
+ grep --silent '^[[:space:]]*#' <<<"${line}" && continue
+ grep --silent '[^[:space:]]' <<<"${line}" || continue
+ ebuild_source_profile $(canonicalise ${1}/${line} )
+ done <${1}/parent
+ fi
+
+ local old_set=$-
+ set -a
+
+ if [[ -f ${1}/make.defaults ]] ; then
+ source ${1}/make.defaults || die "Couldn't source ${1}/make.defaults"
+ fi
+
+ if [[ -f ${1}/bashrc ]] ; then
+ source ${1}/bashrc || die "Couldn't source ${1}/bashrc"
+ fi
+
+ [[ "${old_set}" == *a* ]] || set +a
+}
+
+export CONFIG_PROTECT="${PALUDIS_CONFIG_PROTECT}"
+export CONFIG_PROTECT_MASK="${PALUDIS_CONFIG_PROTECT_MASK}"
+save_vars="USE USE_EXPAND USE_EXPAND_HIDDEN ${USE_EXPAND}"
+save_base_vars="CONFIG_PROTECT CONFIG_PROTECT_MASK"
+
+for var in ${save_vars} ${default_save_vars} ${save_base_vars} ; do
+ ebuild_notice "debug" "Saving ${var}=${!var}"
+ eval "export save_var_${var}='${!var}'"
+done
+
+if [[ -n "${PALUDIS_PROFILE_DIRS}" ]] ; then
+ for var in ${PALUDIS_PROFILE_DIRS} ; do
+ ebuild_source_profile $(canonicalise "${var}")
+ done
+elif [[ -n "${PALUDIS_PROFILE_DIR}" ]] ; then
+ ebuild_source_profile $(canonicalise "${PALUDIS_PROFILE_DIR}")
+fi
+
+unset ${save_vars} ${save_base_vars}
+
+for f in ${PALUDIS_BASHRC_FILES} ; do
+ if [[ -f ${f} ]] ; then
+ ebuild_notice "debug" "Loading bashrc file ${f}"
+ old_set=$-
+ set -a
+ source ${f}
+ [[ "${old_set}" == *a* ]] || set +a
+ else
+ ebuild_notice "debug" "Skipping bashrc file ${f}"
+ fi
+done
+
+for var in ${save_vars} ; do
+ if [[ -n ${!var} ]] ; then
+ die "${var} should not be set in bashrc. Aborting."
+ fi
+done
+
+for var in ${save_vars} ; do
+ eval "export ${var}=\${save_var_${var}}"
+done
+
+for var in ${save_base_vars} ; do
+ eval "export ${var}=\"\${save_var_${var}} \$$(echo ${var})\""
+done
+
+[[ -z "${CBUILD}" ]] && export CBUILD="${CHOST}"
+export REAL_CHOST="${CHOST}"
+
+ebuild_scrub_environment()
+{
+ local filters=(
+ -e '/^\(EU\|PP\|U\)ID=/d'
+ -e '/^BASH_\(ARGC\|ARGV\|LINENO\|SOURCE\|VERSINFO\)=/d'
+ -e '/^BASH_COMPLETION\(_DIR\)\?=/d'
+ -e '/^PALUDIS_SOURCE_MERGED_VARIABLES=/d'
+ -e '/^bash[0-9]\+[a-z]\?=/d'
+ -e '/^\(FUNCNAME\|GROUPS\|SHELLOPTS\)=/d'
+ -e '/^\(declare -x \|export \)\?SANDBOX_ACTIVE=/d'
+ )
+
+ sed -i "${filters[@]}" "${1}"
+
+ (
+ source "${1}" || exit 1
+
+ unset -f diefunc perform_hook inherit builtin_loadenv builtin_saveenv
+
+ unset -v PATH ROOTPATH T PALUDIS_TMPDIR PALUDIS_EBUILD_LOG_LEVEL
+ unset -v PORTDIR FILESDIR ECLASSDIR DISTDIR PALUDIS_EBUILD_DIR
+ unset -v PALUDIS_EXTRA_DIE_MESSAGE PALUDIS_COMMAND PALUDIS_CLIENT
+ unset -v PALUDIS_LOADSAVEENV_DIR SKIP_FUNCTIONS PALUDIS_DO_NOTHING_SANDBOXY
+
+ unset -v ${!PALUDIS_CMDLINE_*} PALUDIS_OPTIONS
+ unset -v ${!CONTRARIUS_CMDLINE_*} CONTRARIUS_OPTIONS
+ unset -v ${!GTKPALUDIS_CMDLINE_*} GTKPALUDIS_OPTIONS
+ unset -v ${!ADJUTRIX_CMDLINE_*} ADJUTRIX_OPTIONS
+ unset -v ${!QUALUDIS_CMDLINE_*} QUALUDIS_OPTIONS
+
+ unset -v PALUDIS_HOME PALUDIS_PID EBUILD_KILL_PID ROOT
+ unset -v CATEGORY PN PV P PVR PF ${!LD_*}
+
+ unset -v ebuild EBUILD
+ for v in ${PALUDIS_SOURCE_MERGED_VARIABLES} ; do
+ e_v=E_${v}
+ unset -v ${e_v}
+ done
+
+ for v in ${!SANDBOX*}; do
+ [[ "${v}" == SANDBOX_ACTIVE ]] || unset "${v}"
+ done
+
+ for v in ${!BASH_*}; do
+ case "${v#BASH_}" in
+ ARGC|ARGV|LINENO|SOURCE|VERSINFO) ;;
+ *) unset -v "${v}"
+ esac
+ done
+
+ set >"${1}"
+ export -p >>"${1}"
+ ) || return $?
+
+ sed -i \
+ -e 's:^declare -rx:declare -x:' \
+ -e 's:^declare -x :export :' \
+ "${filters[@]}" "${1}"
+}
+
+ebuild_load_environment()
+{
+ if [[ -n "${PALUDIS_LOAD_ENVIRONMENT}" ]] ; then
+ [[ -d ${PALUDIS_TMPDIR} ]] \
+ || die "You need to create PALUDIS_TMPDIR (${PALUDIS_TMPDIR})."
+
+ local save_PALUDIS_EXTRA_DIE_MESSAGE="${PALUDIS_EXTRA_DIE_MESSAGE}"
+ export PALUDIS_EXTRA_DIE_MESSAGE="
+!!! Could not extract the saved environment file. This is usually
+!!! caused by a broken environment.bz2 that was generated by an old
+!!! Portage version. The file that needs repairing is:
+!!! ${PALUDIS_LOAD_ENVIRONMENT}
+!!! Try copying this file, bunzip2ing it and sourcing it using a new
+!!! bash shell (do not continue to use said shell afterwards). You
+!!! should get an error that give you a rough idea of where the
+!!! problem lies.
+"
+
+ if [[ "${PALUDIS_LOAD_ENVIRONMENT%.bz2}" != "${PALUDIS_LOAD_ENVIRONMENT}" ]] ; then
+ echo bunzip2 \< "${PALUDIS_LOAD_ENVIRONMENT}" \> ${PALUDIS_TMPDIR}/environment-${CATEGORY}-${PF}-$$ 1>&2
+ bunzip2 < "${PALUDIS_LOAD_ENVIRONMENT}" > ${PALUDIS_TMPDIR}/environment-${CATEGORY}-${PF}-$$ \
+ || die "Can't extract ${PALUDIS_LOAD_ENVIRONMENT}"
+ else
+ echo cp "${PALUDIS_LOAD_ENVIRONMENT}" "${PALUDIS_TMPDIR}/environment-${CATEGORY}-${PF}-$$" 1>&2
+ cp "${PALUDIS_LOAD_ENVIRONMENT}" "${PALUDIS_TMPDIR}/environment-${CATEGORY}-${PF}-$$" \
+ || die "Can't copy ${PALUDIS_LOAD_ENVIRONMENT}"
+ fi
+
+ echo ebuild_scrub_environment "${PALUDIS_TMPDIR}/environment-${CATEGORY}-${PF}-$$" 1>&2
+ ebuild_scrub_environment "${PALUDIS_TMPDIR}/environment-${CATEGORY}-${PF}-$$" \
+ || die "Can't load saved environment for cleaning"
+
+ echo source "${PALUDIS_TMPDIR}/environment-${CATEGORY}-${PF}-$$" 1>&2
+ source "${PALUDIS_TMPDIR}/environment-${CATEGORY}-${PF}-$$" \
+ || die "Can't load saved environment"
+
+ export PALUDIS_EXTRA_DIE_MESSAGE="${save_PALUDIS_EXTRA_DIE_MESSAGE}"
+
+ echo rm "${PALUDIS_TMPDIR}/environment-${CATEGORY}-${PF}-$$" 1>&2
+ rm "${PALUDIS_TMPDIR}/environment-${CATEGORY}-${PF}-$$"
+ fi
+}
+
+ebuild_load_ebuild()
+{
+ export EBUILD="${1}"
+ unset ${SOURCE_MERGED_VARIABLES}
+
+ local v e_v
+ for v in ${PALUDIS_MUST_NOT_CHANGE_VARIABLES} ; do
+ e_v=saved_${v}
+ local ${e_v}="${!v}"
+ done
+
+ [[ -f "${1}" ]] || die "Ebuild '${1}' is not a file"
+ source ${1} || die "Error sourcing ebuild '${1}'"
+
+ if [[ -n "${PALUDIS_RDEPEND_DEFAULTS_TO_DEPEND}" ]] ; then
+ [[ ${RDEPEND-unset} == "unset" ]] && RDEPEND="${DEPEND}"
+ fi
+
+ for v in ${PALUDIS_SOURCE_MERGED_VARIABLES} ; do
+ e_v=E_${v}
+ export -n ${v}="${!v} ${!e_v}"
+ done
+
+ [[ ${EAPI-unset} == "unset" ]] && EAPI="0"
+
+ for v in ${PALUDIS_MUST_NOT_CHANGE_VARIABLES} ; do
+ s_v="saved_${v}"
+ if [[ -n "${!s_v}" ]] && [[ "${!v}" != "${!s_v}" ]] ; then
+ ebuild_notice "qa" \
+ "Ebuild ${1} illegally tried to change SLOT from '${!s_v}' to '${!v}'"
+ export ${v}="${!s_v}"
+ fi
+ done
+}
+
+perform_hook()
+{
+ export HOOK=${1}
+ ebuild_notice "debug" "Starting hook '${HOOK}'"
+
+ local old_sandbox_on="${SANDBOX_ON}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && export SANDBOX_ON="0"
+
+ local hook_dir
+ for hook_dir in ${PALUDIS_HOOK_DIRS} ; do
+ [[ -d "${hook_dir}/${HOOK}" ]] || continue
+ local hook_file
+ for hook_file in "${hook_dir}/${HOOK}/"*.bash ; do
+ [[ -e "${hook_file}" ]] || continue
+ ebuild_notice "debug" "Starting hook script '${hook_file}' for '${HOOK}'"
+ if ! ( source "${hook_file}" ) ; then
+ ebuild_notice "warning" "Hook '${hook_file}' returned failure"
+ else
+ ebuild_notice "debug" "Hook '${hook_file}' returned success"
+ fi
+ done
+ done
+
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && export SANDBOX_ON="${old_sandbox_on}"
+ true
+}
+
+ebuild_main()
+{
+ if ! [[ -e /proc/self ]] && [[ "$(uname -s)" == Linux ]] ; then
+ ebuild_notice "warning" "/proc appears to be unmounted or unreadable."
+ ebuild_notice "warning" "This will cause problems."
+ fi
+
+ local action ebuild="$1"
+ shift
+
+ if [[ ${#@} -ge 2 ]] ; then
+ ebuild_section "Running ebuild phases $@ as $(id -un ):$(id -gn )..."
+ elif [[ ${1} != variable ]] && [[ ${1} != metadata ]] && [[ ${1} != pretend ]] ; then
+ ebuild_section "Running ebuild phase $@ as $(id -un ):$(id -gn )..."
+ fi
+
+ for action in $@ ; do
+ case ${action} in
+ metadata|variable|init|prepare|fetch|merge|unmerge|tidyup|\
+ strip|loadenv|saveenv|fetchbin|initbin|unpackbin)
+ ebuild_load_module builtin_${action}
+ ;;
+
+ unpack|compile|install|test)
+ ebuild_load_module src_${action}
+ ;;
+
+ setup|config|nofetch|preinst|postinst|prerm|postrm|pretend)
+ ebuild_load_module pkg_${action}
+ ;;
+
+ *)
+ ebuild_load_module usage_error
+ ebuild_f_usage_error "Unknown action '${action}'"
+ exit 1
+ ;;
+ esac
+ done
+
+ if [[ $1 == metadata ]] || [[ $1 == variable ]] ; then
+ export EBUILD_PHASE="${1}"
+ perform_hook ebuild_${action}_pre
+ if [[ $1 != variable ]] || [[ -n "${ebuild}" ]] ; then
+ for f in cut tr date ; do
+ eval "export ebuild_real_${f}=\"$(which $f )\""
+ eval "${f}() { ebuild_notice qa 'global scope ${f}' ; $(which $f ) \"\$@\" ; }"
+ done
+ PATH="" ebuild_load_ebuild "${ebuild}"
+ fi
+ if ! ebuild_f_${1} ; then
+ perform_hook ebuild_${action}_fail
+ die "${1} failed"
+ fi
+ perform_hook ebuild_${action}_post
+ else
+ ebuild_load_environment
+ if [[ "${ebuild}" != "-" ]] ; then
+ ebuild_load_ebuild "${ebuild}"
+ fi
+ for action in $@ ; do
+ export EBUILD_PHASE="${action}"
+ perform_hook ebuild_${action}_pre
+ if ! ebuild_f_${action} ; then
+ perform_hook ebuild_${action}_fail
+ die "${action} failed"
+ fi
+ if [[ ${action} == "init" ]] ; then
+ ebuild_load_ebuild "${ebuild}"
+ fi
+ perform_hook ebuild_${action}_post
+ done
+ fi
+
+ if [[ ${#@} -ge 2 ]] ; then
+ ebuild_section "Completed ebuild phases $@"
+ elif [[ ${1} != variable ]] && [[ ${1} != metadata ]] && [[ ${1} != pretend ]] ; then
+ ebuild_section "Completed ebuild phase $@"
+ fi
+}
+
+ebuild_main "$@"
+
diff --git a/paludis/repositories/e/ebuild/echo_functions.bash.in b/paludis/repositories/e/ebuild/echo_functions.bash.in
new file mode 100644
index 000000000..98e538443
--- /dev/null
+++ b/paludis/repositories/e/ebuild/echo_functions.bash.in
@@ -0,0 +1,238 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+@GENERATED_FILE@
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+[[ -z ${PALUDIS_COLOURS} ]] && PALUDIS_COLOURS=@COLOURSCHEME@
+
+COLOUR_GREEN=$'\e[32;01m'
+COLOUR_YELLOW=$'\e[33;01m'
+COLOUR_RED=$'\e[31;01m'
+COLOUR_BLUE=$'\e[34;01m'
+COLOUR_PINK=$'\e[35;01m'
+
+if [[ ${PALUDIS_COLOURS} == pink ]]; then
+ COLOUR_GOOD=${COLOUR_PINK}
+ COLOUR_WARN=${COLOUR_YELLOW}
+ COLOUR_BAD=${COLOUR_RED}
+ COLOUR_BRACKET=${COLOUR_PINK}
+else
+ COLOUR_GOOD=${COLOUR_GREEN}
+ COLOUR_WARN=${COLOUR_YELLOW}
+ COLOUR_BAD=${COLOUR_RED}
+ COLOUR_BRACKET=${COLOUR_BLUE}
+fi
+
+COLOUR_NORMAL=$'\e[0m'
+PALUDIS_ENDCOL=$'\e[A\e['$(( ${COLUMNS:-80} - 7 ))'G'
+
+paludis_ecmd()
+{
+ local cmd="$1" hook="$2" prefix="$3" message="$4" newline="$5"
+
+ echo -n "${prefix}${message}"
+ [[ -z "${newline}" ]] && echo
+
+ if type perform_hook &>/dev/null ; then
+ if [[ -n "${hook}" ]] ; then
+ MESSAGE="${message}" perform_hook "${hook}"
+ fi
+ fi
+}
+
+einfon()
+{
+ paludis_ecmd \
+ "einfon" \
+ "einfo" \
+ "`echo -ne " ${COLOUR_GOOD}*${COLOUR_NORMAL} "`" \
+ "$*" \
+ "no"
+}
+
+einfo()
+{
+ paludis_ecmd \
+ "einfo" \
+ "einfo" \
+ "`echo -ne " ${COLOUR_GOOD}*${COLOUR_NORMAL} "`" \
+ "$*"
+}
+
+einfo_unhooked()
+{
+ paludis_ecmd \
+ "einfo" \
+ "" \
+ "`echo -ne " ${COLOUR_GOOD}*${COLOUR_NORMAL} "`" \
+ "$*"
+}
+
+elog()
+{
+ paludis_ecmd \
+ "elog" \
+ "elog" \
+ "`echo -ne " ${COLOUR_GOOD}*${COLOUR_NORMAL} "`" \
+ "$*"
+
+ if [[ -n "${PALUDIS_ELOG_FILE}" ]] ; then
+ echo "$@" >> "${PALUDIS_ELOG_FILE}"
+ fi
+}
+
+ewarn()
+{
+ paludis_ecmd \
+ "ewarn" \
+ "ewarn" \
+ "`echo -ne " ${COLOUR_WARN}*${COLOUR_NORMAL} "`" \
+ "$*"
+}
+
+eerror()
+{
+ paludis_ecmd \
+ "eerror" \
+ "eerror" \
+ "`echo -ne " ${COLOUR_BAD}*${COLOUR_NORMAL} "`" \
+ "$*"
+}
+
+ebegin()
+{
+ paludis_ecmd \
+ "ebegin" \
+ "einfo" \
+ "`echo -ne " ${COLOUR_GOOD}*${COLOUR_NORMAL} "`" \
+ "$* ..."
+}
+
+ebegin_unhooked()
+{
+ paludis_ecmd \
+ "ebegin" \
+ "" \
+ "`echo -ne " ${COLOUR_GOOD}*${COLOUR_NORMAL} "`" \
+ "$* ..."
+}
+
+_eend()
+{
+ local retval=${1:-0} efunc=${2:-eerror} msg
+ shift 2
+
+ if [[ ${retval} == 0 ]]; then
+ msg="${COLOUR_BRACKET}[ ${COLOUR_GOOD}ok${COLOUR_BRACKET} ]${COLOUR_NORMAL}"
+ else
+ if [[ -n "$*" ]]; then
+ ${efunc} $*
+ fi
+ msg="${COLOUR_BRACKET}[ ${COLOUR_BAD}!!${COLOUR_BRACKET} ]${COLOUR_NORMAL}"
+ fi
+
+ echo -e "${PALUDIS_ENDCOL} ${msg}"
+
+ return ${retval}
+}
+
+eend()
+{
+ local retval=${1:-0}
+ shift
+ _eend ${retval} eerror "$*"
+ return ${retval}
+}
+
+ewend()
+{
+ local retval=${1:-0}
+ shift
+ _eend ${retval} ewarn "$*"
+ return ${retval}
+}
+
+use_with()
+{
+ if useq "${1}" ; then
+ echo "--with-${2:-${1}}${3+=${3}}"
+ else
+ echo "--without-${2:-${1}}"
+ fi
+}
+
+use_enable()
+{
+ if useq "${1}" ; then
+ echo "--enable-${2:-${1}}${3+=${3}}"
+ else
+ echo "--disable-${2:-${1}}"
+ fi
+}
+
+ebuild_notice_level()
+{
+ case "$1" in
+ debug)
+ echo "1";
+ ;;
+
+ qa)
+ echo "2";
+ ;;
+
+ warning)
+ echo "3";
+ ;;
+
+ silent)
+ echo "4";
+ ;;
+
+ *)
+ echo "[WARNING.EBUILD] Bad value '$1' for qa level" 1>&2
+ echo "2";
+ ;;
+ esac
+}
+
+ebuild_notice()
+{
+ local level="$1"
+ shift
+
+ local level_num=$(ebuild_notice_level "${level}" )
+ local min_level_num=$(ebuild_notice_level "${PALUDIS_EBUILD_LOG_LEVEL}" )
+
+ if [[ "${level_num}" -ge "${min_level_num}" ]] ; then
+ local upper_level=$(echo ${level} | ${ebuild_real_tr:-tr} '[:lower:]' '[:upper:]' )
+ echo -n "${EBUILD_PROGRAM_NAME:-ebuild.bash}@$(${ebuild_real_date:-date} +%s ): " 1>&2
+ echo "[${upper_level}.EBUILD] $* (from ${EBUILD:-?})" 1>&2
+ fi
+ true
+}
+
+ebuild_section()
+{
+ echo ">>> $*"
+}
+
diff --git a/paludis/repositories/e/ebuild/echo_functions_TEST.bash b/paludis/repositories/e/ebuild/echo_functions_TEST.bash
new file mode 100644
index 000000000..6e4ad2786
--- /dev/null
+++ b/paludis/repositories/e/ebuild/echo_functions_TEST.bash
@@ -0,0 +1,45 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+use_with_TEST()
+{
+ export USE="foo"
+ test_equality "$(use_with foo )" "--with-foo"
+ test_equality "$(use_with foo bar )" "--with-bar"
+ test_equality "$(use_with foo bar baz )" "--with-bar=baz"
+
+ export USE="oink"
+ test_equality "$(use_with foo )" "--without-foo"
+ test_equality "$(use_with foo bar )" "--without-bar"
+ test_equality "$(use_with foo bar baz )" "--without-bar"
+}
+
+
+use_enable_TEST()
+{
+ export USE="foo"
+ test_equality "$(use_enable foo )" "--enable-foo"
+ test_equality "$(use_enable foo bar )" "--enable-bar"
+ test_equality "$(use_enable foo bar baz )" "--enable-bar=baz"
+
+ export USE="oink"
+ test_equality "$(use_enable foo )" "--disable-foo"
+ test_equality "$(use_enable foo bar )" "--disable-bar"
+ test_equality "$(use_enable foo bar baz )" "--disable-bar"
+}
+
diff --git a/paludis/repositories/e/ebuild/eclass_functions.bash b/paludis/repositories/e/ebuild/eclass_functions.bash
new file mode 100644
index 000000000..93e6151b2
--- /dev/null
+++ b/paludis/repositories/e/ebuild/eclass_functions.bash
@@ -0,0 +1,82 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+EXPORT_FUNCTIONS()
+{
+ [[ -z "${ECLASS}" ]] && die "EXPORT_FUNCTIONS called but ECLASS undefined"
+
+ local e
+ for e in "$@" ; do
+ case "$e" in
+ pkg_nofetch|pkg_setup|pkg_prerm|pkg_postrm|pkg_preinst|pkg_postinst|pkg_config)
+ eval "${e}() { ${ECLASS}_${e} \"\$@\" ; }"
+ ;;
+
+ src_unpack|src_compile|src_install|src_test)
+ eval "${e}() { ${ECLASS}_${e} \"\$@\" ; }"
+ ;;
+
+ *)
+ eval "${e}() { ${ECLASS}_${e} \"\$@\" ; }"
+ ebuild_notice "qa" "$e should not be in EXPORT_FUNCTIONS for ${ECLASS}"
+ ;;
+ esac
+ done
+}
+
+inherit()
+{
+ [[ -n "${PALUDIS_SKIP_INHERIT}" ]] && return
+
+ local e ee location= v
+ for e in "$@" ; do
+ for ee in ${ECLASSDIRS:-${ECLASSDIR}} ; do
+ [[ -f "${ee}/${e}.eclass" ]] && location="${ee}/${e}.eclass"
+ done
+ local old_ECLASS="${ECLASS}"
+ export ECLASS="${e}"
+
+ for v in ${PALUDIS_SOURCE_MERGED_VARIABLES} ; do
+ local c_v="current_${v}" u_v="unset_${v}"
+ local ${c_v}="${!v}"
+ local ${u_v}="${!v-unset}"
+ unset ${v}
+ done
+
+ [[ -z "${location}" ]] && die "Error finding eclass ${e}"
+ source "${location}" || die "Error sourcing eclass ${e}"
+ hasq "${ECLASS}" ${INHERITED} || export INHERITED="${INHERITED} ${ECLASS}"
+
+ for v in ${PALUDIS_SOURCE_MERGED_VARIABLES} ; do
+ local e_v="E_${v}"
+ export ${e_v}="${!e_v} ${!v}"
+ done
+
+ for v in ${PALUDIS_SOURCE_MERGED_VARIABLES} ; do
+ local c_v="current_${v}" u_v="unset_${v}"
+ [[ "unset" == ${!u_v} ]] && unset ${v} || export ${v}="${!c_v}"
+ done
+
+ export ECLASS="${old_ECLASS}"
+ done
+}
+
diff --git a/paludis/repositories/e/ebuild/exlib_functions.bash b/paludis/repositories/e/ebuild/exlib_functions.bash
new file mode 100644
index 000000000..44dcbd84c
--- /dev/null
+++ b/paludis/repositories/e/ebuild/exlib_functions.bash
@@ -0,0 +1,76 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+export_exlib_phases()
+{
+ [[ -z "${CURRENT_EXLIB}" ]] && die "export_exlib_phases called but ECLASS undefined"
+
+ local e
+ for e in "$@" ; do
+ case "$e" in
+ pkg_nofetch|pkg_setup|pkg_prerm|pkg_postrm|pkg_preinst|pkg_postinst|pkg_config|pkg_pretend)
+ eval "${e}() { ${CURRENT_EXLIB}_${e} \"\$@\" ; }"
+ ;;
+
+ src_unpack|src_compile|src_install|src_test)
+ eval "${e}() { ${CURRENT_EXLIB}_${e} \"\$@\" ; }"
+ ;;
+
+ *)
+ eval "${e}() { ${CURRENT_EXLIB}_${e} \"\$@\" ; }"
+ ebuild_notice "qa" "$e should not be in export_exlib_phases for ${CURRENT_EXLIB}"
+ ;;
+ esac
+ done
+}
+
+require()
+{
+ local e ee location= v
+ for e in "$@" ; do
+ for ee in ${EXLIBSDIRS} ; do
+ [[ -f "${ee}/${e}.exlib" ]] && location="${ee}/${e}.exlib"
+ done
+ local old_CURRENT_EXLIB="${CURRENT_EXLIB}"
+ export CURRENT_EXLIB="${e}"
+
+ for v in ${PALUDIS_SOURCE_MERGED_VARIABLES} ; do
+ local c_v="current_${v}" u_v="unset_${v}"
+ local ${c_v}="${!v}"
+ local ${u_v}="${!v-unset}"
+ unset ${v}
+ done
+
+ [[ -z "${location}" ]] && die "Error finding exlib ${e} in ${EXLIBSDIRS}"
+ source "${location}" || die "Error sourcing exlib ${e}"
+ hasq "${CURRENT_EXLIB}" ${INHERITED} || export INHERITED="${INHERITED} ${CURRENT_EXLIB}"
+
+ for v in ${PALUDIS_SOURCE_MERGED_VARIABLES} ; do
+ local e_v="E_${v}"
+ export ${e_v}="${!e_v} ${!v}"
+ done
+
+ for v in ${PALUDIS_SOURCE_MERGED_VARIABLES} ; do
+ local c_v="current_${v}" u_v="unset_${v}"
+ [[ "unset" == ${!u_v} ]] && unset ${v} || export ${v}="${!c_v}"
+ done
+
+ export CURRENT_EXLIB="${old_CURRENT_EXLIB}"
+ done
+}
+
diff --git a/paludis/repositories/e/ebuild/install_functions.bash b/paludis/repositories/e/ebuild/install_functions.bash
new file mode 100644
index 000000000..e23628c7b
--- /dev/null
+++ b/paludis/repositories/e/ebuild/install_functions.bash
@@ -0,0 +1,109 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+umask 022
+export DESTTREE="/usr"
+export INSDESTTREE=""
+export EXEDESTTREE=""
+export DOCDESTTREE=""
+export INSOPTIONS="-m0644"
+export EXEOPTIONS="-m0755"
+export LIBOPTIONS="-m0644"
+export DIROPTIONS="-m0755"
+export MOPREFIX="${PN}"
+
+keepdir()
+{
+ dodir "$@"
+ if [[ "${1}" == "-R" ]] || [[ "${1}" == "-r" ]] ; then
+ shift
+ find "$@" -type d -printf "${D}/%p/.keep\0" | xargs -0 touch
+ assert "Failed to create .keep files"
+ else
+ local f
+ for f in "$@" ; do
+ touch "${D}/${f}/.keep" || die "Couldn't touch .keep in ${f}"
+ done
+ fi
+}
+
+into()
+{
+ if [[ "${1}" == "/" ]] ; then
+ export DESTTREE=
+ else
+ export DESTTREE="${1}"
+ [[ -d "${D}${DESTTREE}" ]] || install -d "${D}${DESTTREE}"
+ fi
+}
+
+insinto()
+{
+ if [[ "${1}" == "/" ]] ; then
+ export INSDESTTREE=
+ else
+ export INSDESTTREE="${1}"
+ [[ -d "${D}${INSDESTTREE}" ]] || install -d "${D}${INSDESTTREE}"
+ fi
+}
+
+exeinto()
+{
+ if [[ "${1}" == "/" ]] ; then
+ export EXEDESTTREE=
+ else
+ export EXEDESTTREE="${1}"
+ [[ -d "${D}${EXEDESTTREE}" ]] || install -d "${D}${EXEDESTTREE}"
+ fi
+}
+
+docinto()
+{
+ if [[ "${1}" == "/" ]] ; then
+ export DOCDESTTREE=
+ else
+ export DOCDESTTREE="${1}"
+ [[ -d "${D}usr/share/doc/${PF}/${DOCDESTTREE}" ]] || \
+ install -d "${D}usr/share/doc/${PF}/${DOCDESTTREE}"
+ fi
+}
+
+insopts()
+{
+ export INSOPTIONS="$@"
+}
+
+diropts()
+{
+ export DIROPTIONS="$@"
+}
+
+exeopts()
+{
+ export EXEOPTIONS="$@"
+}
+
+libopts()
+{
+ export LIBOPTIONS="$@"
+}
+
diff --git a/paludis/repositories/e/ebuild/kernel_functions.bash b/paludis/repositories/e/ebuild/kernel_functions.bash
new file mode 100644
index 000000000..9126376e6
--- /dev/null
+++ b/paludis/repositories/e/ebuild/kernel_functions.bash
@@ -0,0 +1,59 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon functions.sh from Baselayout, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+KV_major()
+{
+ [[ -z $1 ]] && return 1
+ local KV=$@
+ echo ${KV%%.*}
+}
+
+KV_minor()
+{
+ [[ -z $1 ]] && return 1
+ local KV=$@
+ KV=${KV#*.}
+ echo ${KV%%.*}
+}
+
+KV_micro()
+{
+ [[ -z $1 ]] && return 1
+ local KV=$@
+ KV=${KV#*.*.}
+ echo ${KV%%[^[:digit:]]*}
+}
+
+KV_to_int()
+{
+ [[ -z $1 ]] && return 1
+
+ local major=$(KV_major "$1")
+ local minor=$(KV_minor "$1")
+ local micro=$(KV_micro "$1")
+ echo $(( major * 65536 + minor * 256 + micro ))
+}
+
+get_KV()
+{
+ echo $(KV_to_int "$(uname -r)")
+}
diff --git a/paludis/repositories/e/ebuild/kernel_functions_TEST.bash b/paludis/repositories/e/ebuild/kernel_functions_TEST.bash
new file mode 100644
index 000000000..4b3271df3
--- /dev/null
+++ b/paludis/repositories/e/ebuild/kernel_functions_TEST.bash
@@ -0,0 +1,41 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# 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
+
+KV_major_TEST()
+{
+ test_equality "$(KV_major 2.4.6)" "2"
+}
+
+KV_minor_TEST()
+{
+ test_equality "$(KV_minor 2.6.16)" "6"
+ test_equality "$(KV_minor 2.6.7-gentoo-r1)" "6"
+ test_equality "$(KV_minor 2.4.18-rc1)" "4"
+}
+
+KV_micro_TEST()
+{
+ test_equality "$(KV_micro 2.6.0)" "0"
+ test_equality "$(KV_micro 2.5.63-mm8)" "63"
+ test_equality "$(KV_micro 2.2.0-foo1)" "0"
+}
+
+KV_to_int_TEST()
+{
+ test_equality "$(KV_to_int 2.6.16)" "132624"
+}
diff --git a/paludis/repositories/e/ebuild/list_functions.bash b/paludis/repositories/e/ebuild/list_functions.bash
new file mode 100644
index 000000000..d34ba64eb
--- /dev/null
+++ b/paludis/repositories/e/ebuild/list_functions.bash
@@ -0,0 +1,70 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+use()
+{
+ useq "${1}"
+}
+
+usev()
+{
+ if useq "${1}" ; then
+ echo "${1#!}"
+ return 0
+ else
+ return 1
+ fi
+}
+
+useq()
+{
+ if [[ "${1:0:1}" == "!" ]] ; then
+ ! hasq "${1#!}" "${USE}"
+ else
+ hasq "${1}" "${USE}"
+ fi
+}
+
+has()
+{
+ hasq "${@}"
+}
+
+hasv()
+{
+ if hasq "${@}" ; then
+ echo "${1}"
+ return 0
+ else
+ return 1
+ fi
+}
+
+hasq()
+{
+ local x= want="$1"
+ shift
+ for x in $@ ; do
+ [[ "${x}" == "${want}" ]] && return 0
+ done
+ return 1
+}
diff --git a/paludis/repositories/e/ebuild/list_functions_TEST.bash b/paludis/repositories/e/ebuild/list_functions_TEST.bash
new file mode 100644
index 000000000..c3ba14fbb
--- /dev/null
+++ b/paludis/repositories/e/ebuild/list_functions_TEST.bash
@@ -0,0 +1,74 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+use_TEST()
+{
+ export USE="foo bar"
+
+ use foo ; test_return_code
+ use bar ; test_return_code
+ ! use baz ; test_return_code
+ ! use foofoo ; test_return_code
+ ! use fo ; test_return_code
+
+ ! use !foo ; test_return_code
+ ! use !bar ; test_return_code
+ use !baz ; test_return_code
+ use !foofoo ; test_return_code
+ use !fo ; test_return_code
+}
+
+usev_TEST()
+{
+ export USE="foo bar"
+ usev foo 1>/dev/null ; test_return_code
+ test_equality "$(usev foo)" "foo"
+
+ usev bar 1>/dev/null ; test_return_code
+ test_equality "$(usev bar)" "bar"
+
+ ! usev baz 1>/dev/null ; test_return_code
+ test_equality "$(usev baz)" ""
+
+ ! usev !foo 1>/dev/null ; test_return_code
+ test_equality "$(usev !foo)" ""
+
+ ! usev !bar 1>/dev/null ; test_return_code
+ test_equality "$(usev !bar)" ""
+
+ ! usev baz 1>/dev/null ; test_return_code
+ test_equality "$(usev !baz)" "baz"
+}
+
+useq_TEST()
+{
+ export USE="foo bar"
+
+ useq foo ; test_return_code
+ useq bar ; test_return_code
+ ! useq baz ; test_return_code
+ ! useq foofoo ; test_return_code
+ ! useq fo ; test_return_code
+
+ ! useq !foo ; test_return_code
+ ! useq !bar ; test_return_code
+ useq !baz ; test_return_code
+ useq !foofoo ; test_return_code
+ useq !fo ; test_return_code
+}
+
diff --git a/paludis/repositories/e/ebuild/merge.cc b/paludis/repositories/e/ebuild/merge.cc
new file mode 100644
index 000000000..77e78bf03
--- /dev/null
+++ b/paludis/repositories/e/ebuild/merge.cc
@@ -0,0 +1,451 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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 "merge_common.hh"
+
+#include <paludis/digests/md5.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/fd_output_stream.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/pstream.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/fd_holder.hh>
+#include <paludis/selinux/security_context.hh>
+
+#include <algorithm>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <iterator>
+#include <string>
+#include <vector>
+
+#include <cstdlib>
+#include <errno.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "config.h"
+
+using namespace paludis;
+using namespace merge;
+
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::ifstream;
+using std::ofstream;
+using std::istreambuf_iterator;
+using std::ostreambuf_iterator;
+
+namespace
+{
+ int exit_status;
+
+ FSEntry
+ make_config_protect_name(const FSEntry & name, const FSEntry & file_to_install)
+ {
+ int n(0);
+ std::string file_to_install_name(stringify(file_to_install));
+
+ ifstream our_md5_file(file_to_install_name.c_str());
+ if (! our_md5_file)
+ throw Failure("Could not get md5 for '" + file_to_install_name + "'");
+ MD5 our_md5(our_md5_file);
+
+ FSEntry result(name);
+ std::string result_name(stringify(name));
+ while (true)
+ {
+ if (! result.exists())
+ return result;
+ else if (result.is_regular_file())
+ {
+ ifstream other_md5_file(result_name.c_str());
+ if (! other_md5_file)
+ throw Failure("Could not get md5 for '" + result_name + "'");
+ MD5 other_md5(other_md5_file);
+
+ if (our_md5.hexsum() == other_md5.hexsum())
+ return result;
+ }
+
+ std::stringstream s;
+ s << std::setw(4) << std::setfill('0') << std::right << n++;
+ result = FSEntry(stringify(name.dirname() / ("._cfg" + s.str() + "_"
+ + name.basename())));
+ result_name = stringify(result);
+ }
+ }
+
+ void
+ do_dir(const FSEntry & root, const FSEntry & src_dir,
+ const FSEntry & dst_dir, ofstream * const contents)
+ {
+ std::string root_str(stringify(root)), dst_dir_str(stringify(dst_dir.dirname()));
+
+ Context context("Installing directory in root '" + root_str + "' from '"
+ + stringify(src_dir) + "' to '" + stringify(dst_dir) + "':");
+
+ if (root_str == "/")
+ root_str.clear();
+ if (0 != dst_dir_str.compare(0, root_str.length(), root_str))
+ throw Failure("do_dir confused: '" + root_str + "' '" + dst_dir_str + "'");
+ if (dst_dir_str == "/")
+ dst_dir_str.clear();
+
+ cout << ">>> " << std::setw(5) << std::left << "[dir]" << " " <<
+ dst_dir_str.substr(root_str.length()) << "/" << dst_dir.basename();
+
+ if (dst_dir.is_directory())
+ {
+ cout << " <dir>" << endl;
+ }
+ else if (dst_dir.is_symbolic_link() && dst_dir.realpath().is_directory())
+ {
+ Log::get_instance()->message(ll_qa, lc_no_context, "Expected '" + stringify(dst_dir) +
+ "' to be a directory or non-existent, but found a symlink to a directory");
+ cout << " <sym -> dir>" << endl;
+ }
+ else if (dst_dir.exists())
+ {
+ cout << " <obj>" << endl;
+ throw Failure("Expected '" + stringify(dst_dir) +
+ "' to be a directory or non-existent, but found a file");
+ }
+ else
+ {
+ cout << " <new>" << endl;
+
+ mode_t mode(src_dir.permissions());
+
+//#ifdef HAVE_SELINUX
+ tr1::shared_ptr<FSCreateCon> createcon;
+ if (MatchPathCon::get_instance()->good())
+ {
+ FSCreateCon *p = new FSCreateCon(MatchPathCon::get_instance()->match(dst_dir_str.substr(root_str.length()),
+ mode));
+ createcon.reset(p);
+ }
+//#endif
+
+ FSEntry dst_dir_copy(dst_dir);
+ dst_dir_copy.mkdir(mode);
+ dst_dir_copy.chown(src_dir.owner(), src_dir.group());
+ /* the chmod is needed to pick up fancy set*id bits */
+ dst_dir_copy.chmod(src_dir.permissions());
+ }
+
+ *contents << "dir " << dst_dir_str.substr(root_str.length()) << "/" <<
+ dst_dir.basename() << endl;
+ }
+
+ void
+ copy_file_contents(int input_fd, int fd)
+ {
+ char buf[4096];
+ ssize_t count;
+ while ((count = read(input_fd, buf, 4096)) > 0)
+ write(fd, buf, count);
+ }
+
+ void
+ do_obj(const FSEntry & root, const FSEntry & src,
+ const FSEntry & dst, ofstream * const contents)
+ {
+ std::string root_str(stringify(root)), dst_dir_str(stringify(dst.dirname())),
+ src_str(stringify(src));
+
+ Context context("Installing object in root '" + root_str + "' from '"
+ + stringify(src) + "' to '" + stringify(dst) + "':");
+
+ if (root_str == "/")
+ root_str.clear();
+ if (0 != dst_dir_str.compare(0, root_str.length(), root_str))
+ throw Failure("do_obj confused: '" + root_str + "' '" + dst_dir_str + "'");
+ if (dst_dir_str == "/")
+ dst_dir_str.clear();
+
+ cout << ">>> " << std::setw(5) << std::left << "[obj]" << " " <<
+ dst_dir_str.substr(root_str.length()) << "/" << dst.basename();
+
+ if (dst.is_directory())
+ {
+ cout << " <dir>" << endl;
+ throw Failure("Cannot overwrite directory '" + stringify(dst) + "' with a file");
+ }
+ else
+ {
+ FSEntry real_dst(dst);
+
+ FDHolder input_fd(::open(src_str.c_str(), O_RDONLY), false);
+ if (-1 == input_fd)
+ throw Failure("Cannot read '" + src_str + "'");
+
+ if (dst.exists())
+ {
+ if (is_config_protected(root, dst))
+ {
+ real_dst = make_config_protect_name(dst, src);
+ if (dst != real_dst)
+ cout << " -> " << real_dst << endl;
+ else
+ cout << endl;
+ }
+ else
+ {
+ if (dst.is_regular_file())
+ {
+ cout << " <obj>" << endl;
+
+ mode_t mode(dst.permissions());
+ if ((mode & S_ISUID) || (mode & S_ISGID))
+ {
+ mode &= 0400;
+ FSEntry(dst).chmod(mode);
+ }
+ FSEntry(dst).unlink();
+ }
+ else if (dst.is_symbolic_link())
+ {
+ cout << " <sym>" << endl;
+ FSEntry(dst).unlink();
+ }
+ else
+ {
+ cout << " <?""?""?>" << endl;
+ FSEntry(dst).unlink();
+ }
+ }
+ }
+ else
+ cout << " <new>" << endl;
+
+ /* FDHolder must be destroyed before we do the md5 thing, or the
+ * disk write may not have synced. */
+ {
+//#ifdef HAVE_SELINUX
+ tr1::shared_ptr<FSCreateCon> createcon;
+ if (MatchPathCon::get_instance()->good())
+ createcon.reset(new
+ FSCreateCon(MatchPathCon::get_instance()->match(dst_dir_str.substr(root_str.length()) + "/"
+ + dst.basename(), src.permissions())));
+//#endif
+ FDHolder fd(::open(stringify(real_dst).c_str(), O_WRONLY | O_CREAT, src.permissions()));
+ if (-1 == fd)
+ throw Failure("Cannot open '" + stringify(real_dst) + "' for write");
+
+ if (0 != ::fchown(fd, src.owner(), src.group()))
+ throw Failure("Cannot fchown '" + stringify(real_dst) + "': " +
+ stringify(::strerror(errno)));
+
+ /* the chmod is needed for set*id bits, which are dropped by
+ * umask in the ::open */
+ if (0 != ::fchmod(fd, src.permissions()))
+ throw Failure("Cannot fchmod '" + stringify(real_dst) + "': " +
+ stringify(::strerror(errno)));
+
+ copy_file_contents(input_fd, fd);
+ }
+
+ ifstream dst_file(stringify(dst).c_str());
+ if (! dst_file)
+ throw Failure("Could not get md5 for '" + stringify(dst_file) + "'");
+ MD5 md5(dst_file);
+
+ *contents << "obj " << dst_dir_str.substr(root_str.length()) << "/" <<
+ dst.basename() << " " << md5.hexsum() << " " <<
+ FSEntry(stringify(dst)).mtime() << endl;
+ }
+ }
+
+ void
+ do_sym(const FSEntry & root, const FSEntry & src,
+ const FSEntry & dst, ofstream * const contents)
+ {
+ std::string root_str(stringify(root)), dst_dir_str(stringify(dst.dirname()));
+
+ Context context("Installing symlink in root '" + root_str + "' from '"
+ + stringify(src) + "' to '" + stringify(dst) + "':");
+
+ if (root_str == "/")
+ root_str.clear();
+ if (0 != dst_dir_str.compare(0, root_str.length(), root_str))
+ throw Failure("do_sym confused: '" + root_str + "' '" + dst_dir_str + "'");
+ if (dst_dir_str == "/")
+ dst_dir_str.clear();
+
+ cout << ">>> " << std::setw(5) << std::left << "[sym]" << " " <<
+ dst_dir_str.substr(root_str.length()) << "/" << dst.basename();
+
+ if (dst.exists())
+ {
+ if (dst.is_directory())
+ throw Failure("Can't overwrite directory '" + stringify(dst) +
+ "' with symlink to '" + src.readlink() + "'");
+ else if (dst.is_symbolic_link())
+ {
+ cout << " <sym>" << endl;
+ FSEntry(dst).unlink();
+ }
+ else
+ {
+ cout << " <obj>" << endl;
+ mode_t mode(dst.permissions());
+ if ((mode & S_ISUID) || (mode & S_ISGID))
+ {
+ mode &= 0400;
+ FSEntry(dst).chmod(mode);
+ }
+ FSEntry(dst).unlink();
+ }
+ }
+ else
+ cout << " <new>" << endl;
+
+//#ifdef HAVE_SELINUX
+ // permissions() on a symlink does weird things, but matchpathcon only cares about the file type,
+ // so just pass S_IFLNK.
+ tr1::shared_ptr<FSCreateCon> createcon;
+ if (MatchPathCon::get_instance()->good())
+ createcon.reset(new
+ FSCreateCon(MatchPathCon::get_instance()->match(dst_dir_str.substr(root_str.length()) + "/"
+ + dst.basename(), S_IFLNK)));
+//#endif
+
+ if (0 != ::symlink(src.readlink().c_str(), stringify(dst).c_str()))
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Couldn't create symlink '"
+ + src.readlink() + "' at '" + stringify(dst) + "'");
+ exit_status |= 2;
+ }
+
+ *contents << "sym " << dst_dir_str.substr(root_str.length()) << "/" <<
+ dst.basename() << " -> " << dst.readlink() << " " <<
+ FSEntry(stringify(dst)).mtime() << endl;
+ }
+
+ void
+ merge_this(const FSEntry & root, const FSEntry & src_dir, const FSEntry & dst_dir,
+ ofstream * const contents)
+ {
+ Context context("Merging under root '" + stringify(root) + "' from '"
+ + stringify(src_dir) + "' to '" + stringify(dst_dir) + "':");
+
+ if (! root.is_directory())
+ throw Failure("merge_this called with bad root '" + stringify(root) + "'");
+ if (! src_dir.is_directory())
+ throw Failure("merge_this called with bad src_dir '" + stringify(src_dir) + "'");
+ if (! dst_dir.is_directory())
+ throw Failure("merge_this called with bad dst_dir '" + stringify(dst_dir) + "'");
+
+ for (DirIterator d(src_dir, false), d_end ; d != d_end ; ++d)
+ {
+ if (d->is_regular_file())
+ do_obj(root, src_dir / d->basename(), dst_dir / d->basename(), contents);
+ else if (d->is_symbolic_link())
+ do_sym(root, src_dir / d->basename(), dst_dir / d->basename(), contents);
+ else if (d->is_directory())
+ {
+ do_dir(root, src_dir / d->basename(), dst_dir / d->basename(), contents);
+ merge_this(root, (src_dir / d->basename()).realpath(), (dst_dir / d->basename()).realpath(), contents);
+ }
+ else
+ throw Failure("Don't know how to merge '" + stringify(*d) + "'");
+ }
+ }
+}
+
+int
+main(int argc, char * argv[])
+{
+ Context context("In main program:");
+
+//#ifdef HAVE_SELINUX
+ // If the MatchPathCon initialisation fails, don't attempt to match contexts when merging.
+ if (! MatchPathCon::get_instance()->good())
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "matchpathcon_init failed; not setting security contexts");
+//#endif
+
+ exit_status = 0;
+ try
+ {
+ if (argc != 4)
+ throw Failure("Usage: " + stringify(argv[0]) + " src dst contents");
+
+ Log::get_instance()->set_program_name(argv[0]);
+ std::string log_level(getenv_with_default("PALUDIS_EBUILD_LOG_LEVEL", "qa"));
+
+ if (log_level == "debug")
+ Log::get_instance()->set_log_level(ll_debug);
+ else if (log_level == "qa")
+ Log::get_instance()->set_log_level(ll_qa);
+ else if (log_level == "warning")
+ Log::get_instance()->set_log_level(ll_warning);
+ else if (log_level == "silent")
+ Log::get_instance()->set_log_level(ll_silent);
+ else
+ throw Failure("bad value for log level");
+
+ Log::get_instance()->message(ll_debug, lc_no_context,
+ "CONFIG_PROTECT is " + getenv_with_default("CONFIG_PROTECT", "(unset)"));
+ Log::get_instance()->message(ll_debug, lc_no_context,
+ "CONFIG_PROTECT_MASK is " + getenv_with_default("CONFIG_PROTECT_MASK", "(unset)"));
+
+ FSEntry src(argv[1]), dst(argv[2]), contents(argv[3]);
+
+ if (! ((src = src.realpath())).is_directory())
+ throw Failure(stringify(argv[1]) + ": not a directory");
+ if (! ((dst = dst.realpath())).is_directory())
+ throw Failure(stringify(argv[2]) + ": not a directory");
+
+ ofstream contents_file(stringify(contents).c_str());
+ if (! contents_file)
+ throw Failure(stringify(contents) + ": not writeable");
+
+ ::umask(0000);
+ merge_this(dst, src, dst, &contents_file);
+ return exit_status;
+ }
+ catch (const Failure & f)
+ {
+ cerr << argv[0] << ": fatal error: " << f.message << endl;
+ return EXIT_FAILURE;
+ }
+ catch (const Exception & e)
+ {
+ cerr << argv[0] << ": fatal error:" << endl
+ << " * " << e.backtrace("\n * ") << e.message()
+ << " (" << e.what() << ")" << endl;
+ return EXIT_FAILURE;
+ }
+ catch (const std::exception & e)
+ {
+ cerr << argv[0] << ": fatal error: " << e.what() << endl;
+ return EXIT_FAILURE;
+ }
+}
+
diff --git a/paludis/repositories/e/ebuild/merge_TEST.bash b/paludis/repositories/e/ebuild/merge_TEST.bash
new file mode 100644
index 000000000..23156255b
--- /dev/null
+++ b/paludis/repositories/e/ebuild/merge_TEST.bash
@@ -0,0 +1,223 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+merge_empty_TEST()
+{
+ ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/merge "merge_TEST_dir/empty_src" \
+ "merge_TEST_dir/empty_dst" \
+ "merge_TEST_dir/empty_contents" 1>/dev/null
+ test_return_code
+}
+
+merge_files_TEST()
+{
+ ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/merge "merge_TEST_dir/files_src" \
+ "merge_TEST_dir/files_dst" \
+ "merge_TEST_dir/files_contents" 1>/dev/null
+ test_return_code
+
+ [[ -f "merge_TEST_dir/files_dst/one" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/files_dst/one)" "contents of one"
+
+ [[ -f "merge_TEST_dir/files_dst/two" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/files_dst/two)" "contents of two"
+}
+
+merge_dirs_TEST()
+{
+ ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/merge "merge_TEST_dir/dirs_src" \
+ "merge_TEST_dir/dirs_dst" \
+ "merge_TEST_dir/dirs_contents" 1>/dev/null
+ test_return_code
+
+ [[ -d "merge_TEST_dir/dirs_dst/dir_one" ]] ; test_return_code
+ [[ -d "merge_TEST_dir/dirs_dst/dir_two" ]] ; test_return_code
+ [[ -d "merge_TEST_dir/dirs_dst/dir_two/dir_three" ]] ; test_return_code
+
+ [[ -f "merge_TEST_dir/dirs_dst/dir_one/one" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/dirs_dst/dir_one/one)" "contents of one"
+
+ [[ -f "merge_TEST_dir/dirs_dst/dir_two/two" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/dirs_dst/dir_two/two)" "contents of two"
+
+ [[ -f "merge_TEST_dir/dirs_dst/dir_two/dir_three/three" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/dirs_dst/dir_two/dir_three/three)" "contents of three"
+}
+
+merge_dirs_over_TEST()
+{
+ ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/merge "merge_TEST_dir/dirs_over_src" \
+ "merge_TEST_dir/dirs_over_dst" \
+ "merge_TEST_dir/dirs_over_contents" 1>/dev/null
+ test_return_code
+
+ [[ -d "merge_TEST_dir/dirs_over_dst/dir_one/" ]] ; test_return_code
+ [[ -d "merge_TEST_dir/dirs_over_dst/dir_two/" ]] ; test_return_code
+ [[ -d "merge_TEST_dir/dirs_over_dst/dir_two/dir_three/" ]] ; test_return_code
+
+ [[ -f "merge_TEST_dir/dirs_over_dst/dir_one/one" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/dirs_over_dst/dir_one/one)" "contents of one"
+
+ [[ -f "merge_TEST_dir/dirs_over_dst/dir_two/two" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/dirs_over_dst/dir_two/two)" "contents of two"
+
+ [[ -f "merge_TEST_dir/dirs_over_dst/dir_two/dir_three/three" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/dirs_over_dst/dir_two/dir_three/three)" "contents of three"
+}
+
+merge_links_TEST()
+{
+ ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/merge "merge_TEST_dir/links_src" \
+ "merge_TEST_dir/links_dst" \
+ "merge_TEST_dir/links_contents" 1>/dev/null
+ test_return_code
+
+ [[ -f "merge_TEST_dir/links_dst/one" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/links_dst/one)" "contents of one"
+
+ [[ -f "merge_TEST_dir/links_dst/two" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/links_dst/two)" "contents of two"
+
+ [[ -f "merge_TEST_dir/links_dst/link_to_two" ]] ; test_return_code
+ [[ -L "merge_TEST_dir/links_dst/link_to_two" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/links_dst/link_to_two)" "contents of two"
+}
+
+merge_links_over_TEST()
+{
+ ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/merge "merge_TEST_dir/links_over_src" \
+ "merge_TEST_dir/links_over_dst" \
+ "merge_TEST_dir/links_over_contents" 1>/dev/null
+ test_return_code
+
+ [[ -f "merge_TEST_dir/links_over_dst/one" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/links_over_dst/one)" "contents of one"
+
+ [[ -f "merge_TEST_dir/links_over_dst/two" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/links_over_dst/two)" "contents of two"
+
+ [[ -f "merge_TEST_dir/links_over_dst/link_to_two" ]] ; test_return_code
+ [[ -L "merge_TEST_dir/links_over_dst/link_to_two" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/links_over_dst/link_to_two)" "contents of two"
+
+ [[ -f "merge_TEST_dir/links_over_dst/link_to_three" ]] ; test_return_code
+ [[ -L "merge_TEST_dir/links_over_dst/link_to_three" ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/links_over_dst/link_to_three)" "contents of three"
+}
+
+merge_links_over_dir_TEST()
+{
+ ! ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/merge "merge_TEST_dir/links_over_dir_src" \
+ "merge_TEST_dir/links_over_dir_dst" \
+ "merge_TEST_dir/links_over_dir_contents" &>/dev/null
+ test_return_code
+}
+
+merge_config_protect_TEST()
+{
+ export CONFIG_PROTECT=/dir
+
+ ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/merge "merge_TEST_dir/config_pro_src" \
+ "merge_TEST_dir/config_pro_dst" \
+ "merge_TEST_dir/config_pro_contents" 1>/dev/null
+ test_return_code
+
+ echo -n "[one]"
+
+ [[ -f merge_TEST_dir/config_pro_dst/dir/one ]] ; test_return_code
+ [[ -f merge_TEST_dir/config_pro_dst/dir/._cfg0000_one ]] ; test_return_code
+ ! [[ -f merge_TEST_dir/config_pro_dst/dir/._cfg0001_one ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/config_pro_dst/dir/one)" "i am a fish"
+ test_equality "$(< merge_TEST_dir/config_pro_dst/dir/._cfg0000_one)" "contents of one"
+
+ echo -n "[two]"
+
+ [[ -f merge_TEST_dir/config_pro_dst/dir/two ]] ; test_return_code
+ ! [[ -f merge_TEST_dir/config_pro_dst/dir/._cfg0000_two ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/config_pro_dst/dir/two)" "contents of two"
+
+ echo -n "[three]"
+
+ [[ -f merge_TEST_dir/config_pro_dst/dir/three ]] ; test_return_code
+ [[ -f merge_TEST_dir/config_pro_dst/dir/._cfg0000_three ]] ; test_return_code
+ [[ -f merge_TEST_dir/config_pro_dst/dir/._cfg0001_three ]] ; test_return_code
+ [[ -f merge_TEST_dir/config_pro_dst/dir/._cfg0002_three ]] ; test_return_code
+ ! [[ -f merge_TEST_dir/config_pro_dst/dir/._cfg0003_three ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/config_pro_dst/dir/three)" "i am a fish"
+ test_equality "$(< merge_TEST_dir/config_pro_dst/dir/._cfg0000_three)" "i am a dish"
+ test_equality "$(< merge_TEST_dir/config_pro_dst/dir/._cfg0001_three)" "i am a fist"
+ test_equality "$(< merge_TEST_dir/config_pro_dst/dir/._cfg0002_three)" "contents of three"
+
+ echo -n "[four]"
+
+ [[ -f merge_TEST_dir/config_pro_dst/dir/four ]] ; test_return_code
+ [[ -f merge_TEST_dir/config_pro_dst/dir/._cfg0000_four ]] ; test_return_code
+ [[ -f merge_TEST_dir/config_pro_dst/dir/._cfg0001_four ]] ; test_return_code
+ ! [[ -f merge_TEST_dir/config_pro_dst/dir/._cfg0002_four ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/config_pro_dst/dir/four)" "i am a fish"
+ test_equality "$(< merge_TEST_dir/config_pro_dst/dir/._cfg0000_four)" "contents of four"
+ test_equality "$(< merge_TEST_dir/config_pro_dst/dir/._cfg0001_four)" "i am a fist"
+}
+
+merge_config_protect_noroot_TEST()
+{
+ export CONFIG_PROTECT=$(${PALUDIS_EBUILD_DIR}/utils/canonicalise `pwd` )/merge_TEST_dir/noroot_dst/dir
+
+ ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/merge "merge_TEST_dir/config_pro_noroot_src" \
+ "/" \
+ "merge_TEST_dir/config_pro_slash_root_contents" 1>/dev/null
+ test_return_code
+
+ echo -n "[one]"
+
+ [[ -f merge_TEST_dir/noroot_dst/dir/one ]] ; test_return_code
+ [[ -f merge_TEST_dir/noroot_dst/dir/._cfg0000_one ]] ; test_return_code
+ ! [[ -f merge_TEST_dir/noroot_dst/dir/._cfg0001_one ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/noroot_dst/dir/one)" "i am a fish"
+ test_equality "$(< merge_TEST_dir/noroot_dst/dir/._cfg0000_one)" "contents of one"
+
+ echo -n "[two]"
+
+ [[ -f merge_TEST_dir/noroot_dst/dir/two ]] ; test_return_code
+ ! [[ -f merge_TEST_dir/noroot_dst/dir/._cfg0000_two ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/noroot_dst/dir/two)" "contents of two"
+
+ echo -n "[three]"
+
+ [[ -f merge_TEST_dir/noroot_dst/dir/three ]] ; test_return_code
+ [[ -f merge_TEST_dir/noroot_dst/dir/._cfg0000_three ]] ; test_return_code
+ [[ -f merge_TEST_dir/noroot_dst/dir/._cfg0001_three ]] ; test_return_code
+ [[ -f merge_TEST_dir/noroot_dst/dir/._cfg0002_three ]] ; test_return_code
+ ! [[ -f merge_TEST_dir/noroot_dst/dir/._cfg0003_three ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/noroot_dst/dir/three)" "i am a fish"
+ test_equality "$(< merge_TEST_dir/noroot_dst/dir/._cfg0000_three)" "i am a dish"
+ test_equality "$(< merge_TEST_dir/noroot_dst/dir/._cfg0001_three)" "i am a fist"
+ test_equality "$(< merge_TEST_dir/noroot_dst/dir/._cfg0002_three)" "contents of three"
+
+ echo -n "[four]"
+
+ [[ -f merge_TEST_dir/noroot_dst/dir/four ]] ; test_return_code
+ [[ -f merge_TEST_dir/noroot_dst/dir/._cfg0000_four ]] ; test_return_code
+ [[ -f merge_TEST_dir/noroot_dst/dir/._cfg0001_four ]] ; test_return_code
+ ! [[ -f merge_TEST_dir/noroot_dst/dir/._cfg0002_four ]] ; test_return_code
+ test_equality "$(< merge_TEST_dir/noroot_dst/dir/four)" "i am a fish"
+ test_equality "$(< merge_TEST_dir/noroot_dst/dir/._cfg0000_four)" "contents of four"
+ test_equality "$(< merge_TEST_dir/noroot_dst/dir/._cfg0001_four)" "i am a fist"
+
+}
+
diff --git a/paludis/repositories/e/ebuild/merge_TEST_cleanup.sh b/paludis/repositories/e/ebuild/merge_TEST_cleanup.sh
new file mode 100755
index 000000000..4b40b8f65
--- /dev/null
+++ b/paludis/repositories/e/ebuild/merge_TEST_cleanup.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d merge_TEST_dir ] ; then
+ rm -fr merge_TEST_dir
+else
+ true
+fi
+
+
diff --git a/paludis/repositories/e/ebuild/merge_TEST_setup.sh b/paludis/repositories/e/ebuild/merge_TEST_setup.sh
new file mode 100755
index 000000000..4af857d16
--- /dev/null
+++ b/paludis/repositories/e/ebuild/merge_TEST_setup.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir -p merge_TEST_dir/{empty_src,empty_dst} || exit 2
+
+mkdir -p merge_TEST_dir/{files_src,files_dst} || exit 2
+echo "contents of one" > merge_TEST_dir/files_src/one
+echo "contents of two" > merge_TEST_dir/files_src/two
+
+mkdir -p merge_TEST_dir/{dirs_src/{dir_one,dir_two/dir_three},dirs_dst} || exit 3
+echo "contents of one" > merge_TEST_dir/dirs_src/dir_one/one
+echo "contents of two" > merge_TEST_dir/dirs_src/dir_two/two
+echo "contents of three" > merge_TEST_dir/dirs_src/dir_two/dir_three/three
+
+mkdir -p merge_TEST_dir/{dirs_over_src/{dir_one,dir_two/dir_three},dirs_over_dst} || exit 4
+mkdir -p merge_TEST_dir/dirs_over_dst/{one,real}
+ln -s real merge_TEST_dir/dirs_over_dst/two
+echo "contents of one" > merge_TEST_dir/dirs_over_src/dir_one/one
+echo "contents of two" > merge_TEST_dir/dirs_over_src/dir_two/two
+echo "contents of three" > merge_TEST_dir/dirs_over_src/dir_two/dir_three/three
+
+mkdir -p merge_TEST_dir/{links_src,links_dst} || exit 5
+echo "contents of one" > merge_TEST_dir/links_src/one
+echo "contents of two" > merge_TEST_dir/links_src/two
+ln -s two merge_TEST_dir/links_src/link_to_two
+
+mkdir -p merge_TEST_dir/{links_over_src,links_over_dst} || exit 5
+echo "contents of one" > merge_TEST_dir/links_over_src/one
+echo "contents of two" > merge_TEST_dir/links_over_src/two
+echo "contents of three" > merge_TEST_dir/links_over_src/three
+ln -s two merge_TEST_dir/links_over_src/link_to_two
+ln -s three merge_TEST_dir/links_over_src/link_to_three
+echo "existing file" > merge_TEST_dir/link_to_two
+ln -s ../ merge_TEST_dir/links_over_dst/link_to_three
+
+mkdir -p merge_TEST_dir/{links_over_dir_src,links_over_dir_dst} || exit 5
+echo "contents of one" > merge_TEST_dir/links_over_dir_src/one
+echo "contents of two" > merge_TEST_dir/links_over_dir_src/two
+echo "contents of three" > merge_TEST_dir/links_over_dir_src/three
+ln -s two merge_TEST_dir/links_over_dir_src/link_to_two
+ln -s three merge_TEST_dir/links_over_dir_src/link_to_three
+mkdir merge_TEST_dir/links_over_dir_dst/link_to_two
+echo "existing file" > merge_TEST_dir/links_over_dir_dst/link_to_three
+
+mkdir -p merge_TEST_dir/{config_pro_src/dir,config_pro_dst/dir} || exit 6
+echo "contents of one" > merge_TEST_dir/config_pro_src/dir/one
+echo "contents of two" > merge_TEST_dir/config_pro_src/dir/two
+echo "contents of three" > merge_TEST_dir/config_pro_src/dir/three
+echo "contents of four" > merge_TEST_dir/config_pro_src/dir/four
+echo "i am a fish" > merge_TEST_dir/config_pro_dst/dir/one
+echo "contents of two" > merge_TEST_dir/config_pro_dst/dir/two
+echo "i am a fish" > merge_TEST_dir/config_pro_dst/dir/three
+echo "i am a dish" > merge_TEST_dir/config_pro_dst/dir/._cfg0000_three
+echo "i am a fist" > merge_TEST_dir/config_pro_dst/dir/._cfg0001_three
+echo "i am a fish" > merge_TEST_dir/config_pro_dst/dir/four
+echo "contents of four" > merge_TEST_dir/config_pro_dst/dir/._cfg0000_four
+echo "i am a fist" > merge_TEST_dir/config_pro_dst/dir/._cfg0001_four
+
+d=merge_TEST_dir/config_pro_noroot_src/$(${PALUDIS_EBUILD_DIR}/utils/canonicalise `pwd` )/merge_TEST_dir/noroot_dst/dir
+mkdir -p "${d}" || exit 7
+mkdir -p merge_TEST_dir/noroot_dst/dir || exit 7
+echo "contents of one" > ${d}/one
+echo "contents of two" > ${d}/two
+echo "contents of three" > ${d}/three
+echo "contents of four" > ${d}/four
+echo "i am a fish" > merge_TEST_dir/noroot_dst/dir/one
+echo "contents of two" > merge_TEST_dir/noroot_dst/dir/two
+echo "i am a fish" > merge_TEST_dir/noroot_dst/dir/three
+echo "i am a dish" > merge_TEST_dir/noroot_dst/dir/._cfg0000_three
+echo "i am a fist" > merge_TEST_dir/noroot_dst/dir/._cfg0001_three
+echo "i am a fish" > merge_TEST_dir/noroot_dst/dir/four
+echo "contents of four" > merge_TEST_dir/noroot_dst/dir/._cfg0000_four
+echo "i am a fist" > merge_TEST_dir/noroot_dst/dir/._cfg0001_four
+
diff --git a/paludis/repositories/e/ebuild/merge_common.cc b/paludis/repositories/e/ebuild/merge_common.cc
new file mode 100644
index 000000000..27b9e11ef
--- /dev/null
+++ b/paludis/repositories/e/ebuild/merge_common.cc
@@ -0,0 +1,99 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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 "merge_common.hh"
+
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/pstream.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/tokeniser.hh>
+
+#include <algorithm>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <iterator>
+#include <string>
+#include <vector>
+
+#include <cstdlib>
+#include <errno.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+using namespace paludis;
+
+std::vector<std::string>
+merge::get_config_var(const std::string & var)
+{
+ std::vector<std::string> result, preresult;
+ WhitespaceTokeniser::get_instance()->tokenise(getenv_with_default(var, ""),
+ std::back_inserter(preresult));
+ result.reserve(preresult.size());
+
+ for (std::vector<std::string>::const_iterator i(preresult.begin()), i_end(preresult.end()) ;
+ i != i_end ; ++i)
+ {
+ if (i->empty())
+ continue;
+ if ("-*" == *i)
+ result.clear();
+ else if ('-' == i->at(0))
+ result.erase(std::remove(result.begin(), result.end(), i->substr(1)), result.end());
+ else
+ result.push_back(*i);
+ }
+ return result;
+}
+
+bool
+merge::is_config_protected(const FSEntry & root, const FSEntry & file)
+{
+ static std::vector<std::string> cfg_pro(get_config_var("CONFIG_PROTECT")),
+ cfg_pro_mask(get_config_var("CONFIG_PROTECT_MASK"));
+
+ std::string file_str(stringify(file)), root_str(stringify(root));
+ if (0 != file_str.compare(0, root_str.length(), root_str))
+ throw Failure("is_config_protected confused: '" + root_str + "' '" + file_str + "'");
+ file_str.erase(0, root_str.length());
+ if (file_str.empty())
+ file_str = "/";
+ if ('/' != file_str.at(0))
+ file_str = "/" + file_str;
+
+ bool result(false);
+ for (std::vector<std::string>::const_iterator c(cfg_pro.begin()),
+ c_end(cfg_pro.end()) ; c != c_end && ! result ; ++c)
+ if (0 == fnmatch((*c + "/*").c_str(), file_str.c_str(), 0))
+ result = true;
+
+ for (std::vector<std::string>::const_iterator c(cfg_pro_mask.begin()),
+ c_end(cfg_pro_mask.end()) ; c != c_end && result ; ++c)
+ if (0 == fnmatch((*c + "/*").c_str(), file_str.c_str(), 0))
+ result = false;
+
+ return result;
+}
+
diff --git a/paludis/repositories/e/ebuild/merge_common.hh b/paludis/repositories/e/ebuild/merge_common.hh
new file mode 100644
index 000000000..3ab1399c9
--- /dev/null
+++ b/paludis/repositories/e/ebuild/merge_common.hh
@@ -0,0 +1,50 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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_EBUILD_UTILS_MERGE_COMMON_HH
+#define PALUDIS_GUARD_EBUILD_UTILS_MERGE_COMMON_HH 1
+
+#include <string>
+#include <vector>
+
+namespace paludis
+{
+ class FSEntry;
+}
+
+namespace merge
+{
+ struct Failure
+ {
+ std::string message;
+
+ Failure(const std::string & m) :
+ message(m)
+ {
+ }
+ };
+
+ std::vector<std::string>
+ get_config_var(const std::string & var);
+
+ bool
+ is_config_protected(const paludis::FSEntry & root, const paludis::FSEntry & file);
+}
+
+#endif
diff --git a/paludis/repositories/e/ebuild/multilib_functions.bash b/paludis/repositories/e/ebuild/multilib_functions.bash
new file mode 100644
index 000000000..f6569334e
--- /dev/null
+++ b/paludis/repositories/e/ebuild/multilib_functions.bash
@@ -0,0 +1,66 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+# Default values. Those used on a non-multilib profile.
+export MULTILIB_ABIS=${MULTILIB_ABIS:-"default"}
+export DEFAULT_ABI=${DEFAULT_ABI:-"default"}
+export CFLAGS_default
+export LDFLAGS_default
+export CHOST_default=${CHOST_default:-${CHOST}}
+export CTARGET_default=${CTARGET_default:-${CTARGET:-${CHOST_default}}}
+export LIBDIR_default=${CONF_LIBDIR:-"lib"}
+export CDEFINE_default
+
+
+ebuild_get_libdir() {
+ local CONF_LIBDIR
+ if [[ -n "${CONF_LIBDIR_OVERRIDE}" ]]; then
+ echo ${CONF_LIBDIR_OVERRIDE}
+ else
+ ebuild_get_abi_LIBDIR
+ fi
+}
+
+ebuild_get_abi_var() {
+ local flag=$1
+ local abi
+ if [[ $# -gt 1 ]]; then
+ abi=${2}
+ elif [[ -n "${ABI}" ]]; then
+ abi=${ABI}
+ elif [[ -n "${DEFAULT_ABI}" ]]; then
+ abi=${DEFAULT_ABI}
+ else
+ abi="default"
+ fi
+
+ local var="${flag}_${abi}"
+ echo ${!var}
+}
+
+ebuild_get_abi_CFLAGS() { ebuild_get_abi_var CFLAGS "$@"; }
+ebuild_get_abi_LDFLAGS() { ebuild_get_abi_var LDFLAGS "$@"; }
+ebuild_get_abi_CHOST() { ebuild_get_abi_var CHOST "$@"; }
+ebuild_get_abi_CTARGET() { ebuild_get_abi_var CTARGET "$@"; }
+ebuild_get_abi_FAKE_TARGETS() { ebuild_get_abi_var FAKE_TARGETS "$@"; }
+ebuild_get_abi_CDEFINE() { ebuild_get_abi_var CDEFINE "$@"; }
+ebuild_get_abi_LIBDIR() { ebuild_get_abi_var LIBDIR "$@"; }
diff --git a/paludis/repositories/e/ebuild/pkg_config.bash b/paludis/repositories/e/ebuild/pkg_config.bash
new file mode 100644
index 000000000..f0bb49ab4
--- /dev/null
+++ b/paludis/repositories/e/ebuild/pkg_config.bash
@@ -0,0 +1,58 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+pkg_config()
+{
+ eerror "No configuration function is defined"
+}
+
+ebuild_f_config()
+{
+ local old_sandbox_write="${SANDBOX_WRITE}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}${ROOT%/}/"
+
+ if hasq "config" ${RESTRICT} ; then
+ ebuild_section "Skipping pkg_config (RESTRICT)"
+ elif hasq "config" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping pkg_config (SKIP_FUNCTIONS)"
+ else
+ if [[ $(type -t pre_pkg_config ) == "function" ]] ; then
+ ebuild_section "Starting pre_pkg_config"
+ pre_pkg_config
+ ebuild_section "Done pre_pkg_config"
+ fi
+
+ ebuild_section "Starting pkg_config"
+ pkg_config
+ ebuild_section "Done pkg_config"
+
+ if [[ $(type -t post_pkg_config ) == "function" ]] ; then
+ ebuild_section "Starting post_pkg_config"
+ post_pkg_config
+ ebuild_section "Done post_pkg_config"
+ fi
+ fi
+
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${old_sandbox_write}"
+ true
+}
+
diff --git a/paludis/repositories/e/ebuild/pkg_nofetch.bash b/paludis/repositories/e/ebuild/pkg_nofetch.bash
new file mode 100644
index 000000000..09c179125
--- /dev/null
+++ b/paludis/repositories/e/ebuild/pkg_nofetch.bash
@@ -0,0 +1,62 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+pkg_nofetch()
+{
+ [[ -z "${A}" ]] && return
+
+ local f g=
+ for f in ${A} ; do
+ [[ -f "${DISTDIR}/${A}" ]] && continue
+ if [[ -z "${g}" ]] ; then
+ echo "The following files could not be fetched automatically for ${PN}:"
+ g=no
+ fi
+ echo "* ${f}"
+ done
+}
+
+ebuild_f_nofetch()
+{
+ local old_sandbox_write="${SANDBOX_WRITE}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}${DISTDIR}"
+ if hasq "nofetch" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping pkg_nofetch (SKIP_FUNCTIONS)"
+ else
+ local a f=
+ for a in ${A} ; do
+ [[ -f "${DISTDIR}/${a}" ]] && continue
+ f=yes
+ done
+
+ if [[ -z "${f}" ]] ; then
+ ebuild_section "Skipping pkg_nofetch (fully fetched already)"
+ else
+ ebuild_section "Starting pkg_nofetch"
+ pkg_nofetch
+ ebuild_section "Done pkg_nofetch"
+ die "Manual fetching is required"
+ fi
+ fi
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${old_sandbox_write}"
+ true
+}
diff --git a/paludis/repositories/e/ebuild/pkg_postinst.bash b/paludis/repositories/e/ebuild/pkg_postinst.bash
new file mode 100644
index 000000000..9eb7c6c8f
--- /dev/null
+++ b/paludis/repositories/e/ebuild/pkg_postinst.bash
@@ -0,0 +1,58 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+pkg_postinst()
+{
+ :
+}
+
+ebuild_f_postinst()
+{
+ local old_sandbox_write="${SANDBOX_WRITE}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}${ROOT%/}/"
+
+ if hasq "postinst" ${RESTRICT} ; then
+ ebuild_section "Skipping pkg_postinst (RESTRICT)"
+ elif hasq "postinst" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping pkg_postinst (SKIP_FUNCTIONS)"
+ else
+ if [[ $(type -t pre_pkg_postinst ) == "function" ]] ; then
+ ebuild_section "Starting pre_pkg_postinst"
+ pre_pkg_postinst
+ ebuild_section "Done pre_pkg_postinst"
+ fi
+
+ ebuild_section "Starting pkg_postinst"
+ pkg_postinst
+ ebuild_section "Done pkg_postinst"
+
+ if [[ $(type -t post_pkg_postinst ) == "function" ]] ; then
+ ebuild_section "Starting post_pkg_postinst"
+ post_pkg_postinst
+ ebuild_section "Done post_pkg_postinst"
+ fi
+ fi
+
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${old_sandbox_write}"
+ true
+}
+
diff --git a/paludis/repositories/e/ebuild/pkg_postrm.bash b/paludis/repositories/e/ebuild/pkg_postrm.bash
new file mode 100644
index 000000000..9fc7855ac
--- /dev/null
+++ b/paludis/repositories/e/ebuild/pkg_postrm.bash
@@ -0,0 +1,59 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+pkg_postrm()
+{
+ :
+}
+
+ebuild_f_postrm()
+{
+ local old_sandbox_write="${SANDBOX_WRITE}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}${ROOT%/}/"
+
+ if hasq "postrm" ${RESTRICT} ; then
+ ebuild_section "Skipping pkg_postrm (RESTRICT)"
+ elif hasq "postrm" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping pkg_postrm (SKIP_FUNCTIONS)"
+ else
+ if [[ $(type -t pre_pkg_postrm ) == "function" ]] ; then
+ ebuild_section "Starting pre_pkg_postrm"
+ pre_pkg_postrm
+ ebuild_section "Done pre_pkg_postrm"
+ fi
+
+ ebuild_section "Starting pkg_postrm"
+ pkg_postrm
+ ebuild_section "Done pkg_postrm"
+
+ if [[ $(type -t post_pkg_postrm ) == "function" ]] ; then
+ ebuild_section "Starting post_pkg_postrm"
+ post_pkg_postrm
+ ebuild_section "Done post_pkg_postrm"
+ fi
+ fi
+
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${old_sandbox_write}"
+ true
+}
+
+
diff --git a/paludis/repositories/e/ebuild/pkg_preinst.bash b/paludis/repositories/e/ebuild/pkg_preinst.bash
new file mode 100644
index 000000000..70a346154
--- /dev/null
+++ b/paludis/repositories/e/ebuild/pkg_preinst.bash
@@ -0,0 +1,58 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+pkg_preinst()
+{
+ :
+}
+
+ebuild_f_preinst()
+{
+ local old_sandbox_write="${SANDBOX_WRITE}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}${ROOT%/}/"
+
+ if hasq "preinst" ${RESTRICT} ; then
+ ebuild_section "Skipping pkg_preinst (RESTRICT)"
+ elif hasq "preinst" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping pkg_preinst (SKIP_FUNCTIONS)"
+ else
+ if [[ $(type -t pre_pkg_preinst ) == "function" ]] ; then
+ ebuild_section "Starting pre_pkg_preinst"
+ pre_pkg_preinst
+ ebuild_section "Done pre_pkg_preinst"
+ fi
+
+ ebuild_section "Starting pkg_preinst"
+ pkg_preinst
+ ebuild_section "Done pkg_preinst"
+
+ if [[ $(type -t post_pkg_preinst ) == "function" ]] ; then
+ ebuild_section "Starting post_pkg_preinst"
+ post_pkg_preinst
+ ebuild_section "Done post_pkg_preinst"
+ fi
+ fi
+
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${old_sandbox_write}"
+ true
+}
+
diff --git a/paludis/repositories/e/ebuild/pkg_prerm.bash b/paludis/repositories/e/ebuild/pkg_prerm.bash
new file mode 100644
index 000000000..ca28d79f1
--- /dev/null
+++ b/paludis/repositories/e/ebuild/pkg_prerm.bash
@@ -0,0 +1,58 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+pkg_prerm()
+{
+ :
+}
+
+ebuild_f_prerm()
+{
+ local old_sandbox_write="${SANDBOX_WRITE}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}${ROOT%/}/"
+
+ if hasq "prerm" ${RESTRICT} ; then
+ ebuild_section "Skipping pkg_prerm (RESTRICT)"
+ elif hasq "prerm" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping pkg_prerm (SKIP_FUNCTIONS)"
+ else
+ if [[ $(type -t pre_pkg_prerm ) == "function" ]] ; then
+ ebuild_section "Starting pre_pkg_prerm"
+ pre_pkg_prerm
+ ebuild_section "Done pre_pkg_prerm"
+ fi
+
+ ebuild_section "Starting pkg_prerm"
+ pkg_prerm
+ ebuild_section "Done pkg_prerm"
+
+ if [[ $(type -t post_pkg_prerm ) == "function" ]] ; then
+ ebuild_section "Starting post_pkg_prerm"
+ post_pkg_prerm
+ ebuild_section "Done post_pkg_prerm"
+ fi
+ fi
+
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${old_sandbox_write}"
+ true
+}
+
diff --git a/paludis/repositories/e/ebuild/pkg_pretend.bash b/paludis/repositories/e/ebuild/pkg_pretend.bash
new file mode 100644
index 000000000..ee2f63b0e
--- /dev/null
+++ b/paludis/repositories/e/ebuild/pkg_pretend.bash
@@ -0,0 +1,47 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+pkg_pretend()
+{
+ :
+}
+
+ebuild_f_pretend()
+{
+ if hasq "pretend" ${RESTRICT} ; then
+ ebuild_section "Skipping pkg_pretend (RESTRICT)"
+ elif hasq "pretend" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping pkg_pretend (SKIP_FUNCTIONS)"
+ else
+ echo
+ if [[ $(type -t pre_pkg_pretend ) == "function" ]] ; then
+ pre_pkg_pretend
+ fi
+
+ pkg_pretend
+
+ if [[ $(type -t post_pkg_pretend ) == "function" ]] ; then
+ post_pkg_pretend
+ fi
+ echo
+ fi
+
+ true
+}
+
+
diff --git a/paludis/repositories/e/ebuild/pkg_setup.bash b/paludis/repositories/e/ebuild/pkg_setup.bash
new file mode 100644
index 000000000..51b83a492
--- /dev/null
+++ b/paludis/repositories/e/ebuild/pkg_setup.bash
@@ -0,0 +1,58 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+pkg_setup()
+{
+ :
+}
+
+ebuild_f_setup()
+{
+ local old_sandbox_write="${SANDBOX_WRITE}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}${ROOT%/}/"
+
+ if hasq "setup" ${RESTRICT} ; then
+ ebuild_section "Skipping pkg_setup (RESTRICT)"
+ elif hasq "setup" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping pkg_setup (SKIP_FUNCTIONS)"
+ else
+ if [[ $(type -t pre_pkg_setup ) == "function" ]] ; then
+ ebuild_section "Starting pre_pkg_setup"
+ pre_pkg_setup
+ ebuild_section "Done pre_pkg_setup"
+ fi
+
+ ebuild_section "Starting pkg_setup"
+ pkg_setup
+ ebuild_section "Done pkg_setup"
+
+ if [[ $(type -t post_pkg_setup ) == "function" ]] ; then
+ ebuild_section "Starting post_pkg_setup"
+ post_pkg_setup
+ ebuild_section "Done post_pkg_setup"
+ fi
+ fi
+
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_WRITE="${old_sandbox_write}"
+ true
+}
+
diff --git a/paludis/repositories/e/ebuild/portage_stubs.bash b/paludis/repositories/e/ebuild/portage_stubs.bash
new file mode 100644
index 000000000..5fc68401a
--- /dev/null
+++ b/paludis/repositories/e/ebuild/portage_stubs.bash
@@ -0,0 +1,86 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+has_version()
+{
+ ${PALUDIS_COMMAND} --has-version "$@"
+}
+
+portageq()
+{
+ # \todo Make this suck less...
+ if [[ "$1" == "has_version" ]] ; then
+ if [[ "$(canonicalise $2 )" != "$(canonicalise $ROOT )" ]] ; then
+ eerror "Error emulating 'portageq $@':"
+ die "portageq has_version emulation only works on current ROOT"
+ else
+ shift ; shift
+ has_version "$@"
+ fi
+ elif [[ "$1" == "best_version" ]] ; then
+ if [[ "$(canonicalise $2 )" != "$(canonicalise $ROOT )" ]] ; then
+ eerror "Error emulating 'portageq $@':"
+ die "portageq best_version emulation only works on current ROOT"
+ else
+ shift ; shift
+ best_version "$@"
+ fi
+ elif [[ "$1" == "vdb_path" ]] ; then
+ vdb_path
+ else
+ eerror "Error emulating 'portageq $@':"
+ die "portageq emulation for $1 not implemented"
+ fi
+}
+
+best_version()
+{
+ ${PALUDIS_COMMAND} --best-version "$@"
+}
+
+vdb_path()
+{
+ if ! ${PALUDIS_COMMAND} --configuration-variable installed location ; then
+ die "Could not find vdb_path"
+ fi
+}
+
+check_KV()
+{
+ die "check_KV not implemented"
+}
+
+debug-print()
+{
+ :
+}
+
+debug-print-function()
+{
+ :
+}
+
+debug-print-section()
+{
+ :
+}
+
diff --git a/paludis/repositories/e/ebuild/run_test.bash b/paludis/repositories/e/ebuild/run_test.bash
new file mode 100755
index 000000000..b5587b9d1
--- /dev/null
+++ b/paludis/repositories/e/ebuild/run_test.bash
@@ -0,0 +1,47 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+shopt -s expand_aliases
+shopt -s extglob
+set +o posix
+
+export TEST_STATUS=
+export PALUDIS_IN_TEST_FRAMEWORK="yes"
+
+test_return_code()
+{
+ local r="$?"
+ if [[ "0" == "${r}" ]] ; then
+ echo -n "."
+ else
+ echo -n "!{retcode: ${r}}"
+ export local_test_status="fail"
+ export TEST_STATUS="fail"
+ fi
+}
+
+test_equality()
+{
+ if [[ "${1}" == "${2}" ]] ; then
+ echo -n "."
+ else
+ echo -n "!{'${1}' not equal to '${2}'}"
+ export local_test_status="fail"
+ export TEST_STATUS="fail"
+ fi
+}
+
+echo "Test program ${1}:"
+source "$(dirname ${1} )/ebuild.bash" || exit 200
+source "${1}" || exit 200
+
+for testname in $(set | grep '_TEST *() *$' ) ; do
+ [[ ${testname/()} != ${testname} ]] && continue
+ echo -n "* ${testname%_TEST}: "
+ export local_test_status=""
+ ${testname}
+ [[ -z "$local_test_status" ]] && echo " OK" || echo " FAIL"
+done
+
+[[ -z "$TEST_STATUS" ]]
+
diff --git a/paludis/repositories/e/ebuild/sandbox.bash b/paludis/repositories/e/ebuild/sandbox.bash
new file mode 100644
index 000000000..cd504ae08
--- /dev/null
+++ b/paludis/repositories/e/ebuild/sandbox.bash
@@ -0,0 +1,42 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+addread()
+{
+ export SANDBOX_READ="${SANDBOX_READ+${SANDBOX_READ}:}${1}"
+}
+
+addwrite()
+{
+ export SANDBOX_WRITE="${SANDBOX_WRITE+${SANDBOX_WRITE}:}${1}"
+}
+
+adddeny()
+{
+ export SANDBOX_DENY="${SANDBOX_DENY+${SANDBOX_DENY}:}${1}"
+}
+
+addpredict()
+{
+ export SANDBOX_PREDICT="${SANDBOX_PREDICT+${SANDBOX_PREDICT}:}${1}"
+}
+
diff --git a/paludis/repositories/e/ebuild/src_compile.bash b/paludis/repositories/e/ebuild/src_compile.bash
new file mode 100644
index 000000000..85a48e478
--- /dev/null
+++ b/paludis/repositories/e/ebuild/src_compile.bash
@@ -0,0 +1,61 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+src_compile()
+{
+ [[ -x ./configure ]] && econf
+ if [[ -f Makefile ]] || [[ -f makefile ]] || [[ -f GNUmakefile ]] ; then
+ emake || die "emake failed"
+ fi
+}
+
+ebuild_f_compile()
+{
+ if [[ -d "${S}" ]] ; then
+ cd "${S}" || die "cd to \${S} (\"${S}\") failed"
+ elif [[ -d "${WORKDIR}" ]] ; then
+ cd "${WORKDIR}" || die "cd to \${WORKDIR} (\"${WORKDIR}\") failed"
+ fi
+
+ if hasq "compile" ${RESTRICT} ; then
+ ebuild_section "Skipping src_compile (RESTRICT)"
+ elif hasq "compile" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping src_compile (SKIP_FUNCTIONS)"
+ else
+ if [[ $(type -t pre_src_compile ) == "function" ]] ; then
+ ebuild_section "Starting pre_src_compile"
+ pre_src_compile
+ ebuild_section "Done pre_src_compile"
+ fi
+
+ ebuild_section "Starting src_compile"
+ src_compile
+ ebuild_section "Done src_compile"
+
+ if [[ $(type -t post_src_compile ) == "function" ]] ; then
+ ebuild_section "Starting post_src_compile"
+ post_src_compile
+ ebuild_section "Done post_src_compile"
+ fi
+ fi
+}
+
diff --git a/paludis/repositories/e/ebuild/src_install.bash b/paludis/repositories/e/ebuild/src_install.bash
new file mode 100644
index 000000000..f0c2f9d64
--- /dev/null
+++ b/paludis/repositories/e/ebuild/src_install.bash
@@ -0,0 +1,58 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+src_install()
+{
+ :
+}
+
+ebuild_f_install()
+{
+ if [[ -d "${S}" ]] ; then
+ cd "${S}" || die "cd to \${S} (\"${S}\") failed"
+ elif [[ -d "${WORKDIR}" ]] ; then
+ cd "${WORKDIR}" || die "cd to \${WORKDIR} (\"${WORKDIR}\") failed"
+ fi
+
+ if hasq "install" ${RESTRICT} ; then
+ ebuild_section "Skipping src_install (RESTRICT)"
+ elif hasq "install" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping src_install (SKIP_FUNCTIONS)"
+ else
+ if [[ $(type -t pre_src_install ) == "function" ]] ; then
+ ebuild_section "Starting pre_src_install"
+ pre_src_install
+ ebuild_section "Done pre_src_install"
+ fi
+
+ ebuild_section "Starting src_install"
+ src_install
+ ebuild_section "Done src_install"
+
+ if [[ $(type -t post_src_install ) == "function" ]] ; then
+ ebuild_section "Starting post_src_install"
+ post_src_install
+ ebuild_section "Done post_src_install"
+ fi
+ fi
+}
+
diff --git a/paludis/repositories/e/ebuild/src_test.bash b/paludis/repositories/e/ebuild/src_test.bash
new file mode 100644
index 000000000..17ad3414c
--- /dev/null
+++ b/paludis/repositories/e/ebuild/src_test.bash
@@ -0,0 +1,86 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+src_test()
+{
+ if [[ -f Makefile ]] || [[ -f GNUmakefile ]] || [[ -f makefile ]] ; then
+ echo "Makefile found, looking for potential test targets"
+ if make -j1 -n check ; then
+ echo "Found check target"
+ emake -j1 check || die "make check failed"
+ elif make -j1 -n test ; then
+ echo "Found test target"
+ emake -j1 test || die "make test failed"
+ else
+ echo "No check or test target, skipping tests"
+ fi
+ else
+ echo "No Makefile, skipping tests"
+ fi
+}
+
+ebuild_f_test()
+{
+ local old_sandbox_predict="${SANDBOX_PREDICT}"
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_PREDICT="${SANDBOX_PREDICT+${SANDBOX_PREDICT}:}/"
+
+ local save_PALUDIS_EXTRA_DIE_MESSAGE="${PALUDIS_EXTRA_DIE_MESSAGE}"
+ export PALUDIS_EXTRA_DIE_MESSAGE="
+!!! This package failed inside the test phase. You should read
+!!! http://paludis.pioto.org/faq.html
+!!! for more information on packages with test phase failures.
+"
+
+ if [[ -d "${S}" ]] ; then
+ cd "${S}" || die "cd to \${S} (\"${S}\") failed"
+ elif [[ -d "${WORKDIR}" ]] ; then
+ cd "${WORKDIR}" || die "cd to \${WORKDIR} (\"${WORKDIR}\") failed"
+ fi
+
+ if hasq "test" ${RESTRICT} ; then
+ ebuild_section "Skipping src_test (RESTRICT)"
+ elif hasq "test" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping src_test (SKIP_FUNCTIONS)"
+ else
+ if [[ $(type -t pre_src_test ) == "function" ]] ; then
+ ebuild_section "Starting pre_src_test"
+ pre_src_test
+ ebuild_section "Done pre_src_test"
+ fi
+
+ ebuild_section "Starting src_test"
+ src_test
+ ebuild_section "Done src_test"
+
+ if [[ $(type -t post_src_test ) == "function" ]] ; then
+ ebuild_section "Starting post_src_test"
+ post_src_test
+ ebuild_section "Done post_src_test"
+ fi
+ fi
+
+ export PALUDIS_EXTRA_DIE_MESSAGE="${save_PALUDIS_EXTRA_DIE_MESSAGE}"
+
+ [[ -z "${PALUDIS_DO_NOTHING_SANDBOXY}" ]] && SANDBOX_PREDICT="${old_sandbox_predict}"
+ true
+}
+
diff --git a/paludis/repositories/e/ebuild/src_unpack.bash b/paludis/repositories/e/ebuild/src_unpack.bash
new file mode 100644
index 000000000..02ce83eee
--- /dev/null
+++ b/paludis/repositories/e/ebuild/src_unpack.bash
@@ -0,0 +1,54 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+src_unpack()
+{
+ [[ -n "${A}" ]] && unpack ${A}
+}
+
+ebuild_f_unpack()
+{
+ cd ${WORKDIR} || die "cd to \${WORKDIR} (\"${WORKDIR}\") failed"
+
+ if hasq "unpack" ${RESTRICT} ; then
+ ebuild_section "Skipping src_unpack (RESTRICT)"
+ elif hasq "unpack" ${SKIP_FUNCTIONS} ; then
+ ebuild_section "Skipping src_unpack (SKIP_FUNCTIONS)"
+ else
+ if [[ $(type -t pre_src_unpack ) == "function" ]] ; then
+ ebuild_section "Starting pre_src_unpack"
+ pre_src_unpack
+ ebuild_section "Done pre_src_unpack"
+ fi
+
+ ebuild_section "Starting src_unpack"
+ src_unpack
+ ebuild_section "Done src_unpack"
+
+ if [[ $(type -t post_src_unpack ) == "function" ]] ; then
+ ebuild_section "Starting post_src_unpack"
+ post_src_unpack
+ ebuild_section "Done post_src_unpack"
+ fi
+ fi
+}
+
diff --git a/paludis/repositories/e/ebuild/unmerge.cc b/paludis/repositories/e/ebuild/unmerge.cc
new file mode 100644
index 000000000..367b42c65
--- /dev/null
+++ b/paludis/repositories/e/ebuild/unmerge.cc
@@ -0,0 +1,320 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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 "merge_common.hh"
+
+#include <paludis/digests/md5.hh>
+
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/pstream.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/tokeniser.hh>
+
+#include <algorithm>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <iterator>
+#include <string>
+#include <vector>
+#include <list>
+
+#include <cstdlib>
+#include <errno.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+using namespace paludis;
+using namespace merge;
+
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::ifstream;
+
+namespace
+{
+ int exit_status;
+
+ template <typename Iter_>
+ void unmerge_contents(const FSEntry & root, const Iter_ begin, const Iter_ end)
+ {
+ using std::istreambuf_iterator;
+
+ for (Iter_ cur(begin) ; cur != end ; ++cur)
+ {
+ std::vector<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(*cur, std::back_inserter(tokens));
+ if (tokens.empty())
+ continue;
+
+ if ("obj" == tokens.at(0))
+ {
+ while (tokens.size() > 4)
+ {
+ if (std::string::npos != tokens.at(4).find('='))
+ break;
+
+ tokens.at(1).append(" " + tokens.at(2));
+ for (unsigned i = 2 ; i < tokens.size() - 1 ; ++i)
+ tokens.at(i) = tokens.at(i + 1);
+ tokens.pop_back();
+ }
+
+ if (tokens.size() != 4)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Malformed VDB entry '" + *cur + "'");
+ exit_status |= 4;
+ }
+ else if (! (root / tokens.at(1)).is_regular_file())
+ cout << "--- [!type] " << tokens.at(1) << endl;
+ else if (stringify((root / tokens.at(1)).mtime()) != tokens.at(3))
+ cout << "--- [!time] " << tokens.at(1) << endl;
+ else
+ {
+ ifstream md5_file(stringify(root / tokens.at(1)).c_str());
+ if (! md5_file)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Couldn't get md5 for '" + stringify(root / tokens.at(1)) + "'");
+ cout << "--- [!md5?] " << tokens.at(1) << endl;
+ }
+ else if (MD5(md5_file).hexsum() != tokens.at(2))
+ cout << "--- [!md5 ] " << tokens.at(1) << endl;
+ else if (is_config_protected(root, root / tokens.at(1)))
+ cout << "--- [cfgpr] " << tokens.at(1) << endl;
+ else
+ {
+ cout << "<<< " << tokens.at(1) << endl;
+
+ mode_t mode((root / tokens.at(1)).permissions());
+ if ((mode & S_ISUID) || (mode & S_ISGID))
+ {
+ mode &= 0400;
+ (root / tokens.at(1)).chmod(mode);
+ }
+ (root / tokens.at(1)).unlink();
+ }
+ }
+ }
+ else if ("sym" == tokens.at(0))
+ {
+ while (tokens.size() > 5)
+ {
+ if (std::string::npos != tokens.at(2).find('='))
+ break;
+
+ if (tokens.at(2) == "->")
+ break;
+
+ tokens.at(1).append(" " + tokens.at(2));
+ for (unsigned i = 2 ; i < tokens.size() - 1; ++i)
+ tokens.at(i) = tokens.at(i + 1);
+ tokens.pop_back();
+ }
+
+ while (tokens.size() > 5)
+ {
+ if (std::string::npos != tokens.at(2).find('='))
+ break;
+
+ if (tokens.at(4) == "->")
+ break;
+
+ tokens.at(3).append(" " + tokens.at(4));
+ for (unsigned i = 4 ; i < tokens.size() - 1; ++i)
+ tokens.at(i) = tokens.at(i + 1);
+ tokens.pop_back();
+ }
+
+ if (tokens.size() != 5)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Malformed VDB entry '" + *cur + "'");
+ exit_status |= 4;
+ }
+ else if (! (root / tokens.at(1)).is_symbolic_link())
+ cout << "--- [!type] " << tokens.at(1) << endl;
+ else if (stringify((root / tokens.at(1)).mtime()) != tokens.at(4))
+ cout << "--- [!time] " << tokens.at(1) << endl;
+ else if ((root / tokens.at(1)).readlink() != tokens.at(3))
+ cout << "--- [!dest] " << tokens.at(1) << endl;
+ else
+ {
+ cout << "<<< " << tokens.at(1) << endl;
+ (root / tokens.at(1)).unlink();
+ }
+ }
+ else if ("misc" == tokens.at(0))
+ {
+ }
+ else if ("fif" == tokens.at(0) || "dev" == tokens.at(0))
+ {
+ while (tokens.size() > 2)
+ {
+ if (std::string::npos != tokens.at(2).find('='))
+ break;
+
+ tokens.at(1).append(" " + tokens.at(2));
+ for (unsigned i = 2 ; i < tokens.size() - 1; ++i)
+ tokens.at(i) = tokens.at(i + 1);
+ tokens.pop_back();
+ }
+
+ if (tokens.size() != 2)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Malformed VDB entry '" + *cur + "'");
+ exit_status |= 8;
+ }
+ else if ("fif" == tokens.at(0) && ! (root / tokens.at(1)).is_fifo())
+ cout << "--- [!type] " << tokens.at(1) << endl;
+ else if ("dev" == tokens.at(0) && ! (root / tokens.at(1)).is_device())
+ cout << "--- [!type] " << tokens.at(1) << endl;
+ else
+ {
+ cout << "<<< " << tokens.at(1) << endl;
+ (root / tokens.at(1)).unlink();
+ }
+ }
+ else if ("dir" == tokens.at(0))
+ /* nothing */ ;
+ else
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Skipping unknown VDB entry '" + *cur + "'");
+ exit_status |= 2;
+ }
+ }
+ }
+
+ template <typename Iter_>
+ void unmerge_directories(const FSEntry & root, const Iter_ begin, const Iter_ end)
+ {
+ using std::istreambuf_iterator;
+
+ for (Iter_ cur(begin) ; cur != end ; ++cur)
+ {
+ std::vector<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(*cur, std::back_inserter(tokens));
+ if (tokens.empty())
+ continue;
+
+ if ("dir" == tokens.at(0))
+ {
+ while (tokens.size() > 2)
+ {
+ if (std::string::npos != tokens.at(2).find('='))
+ break;
+
+ tokens.at(1).append(" " + tokens.at(2));
+ for (unsigned i = 2 ; i < tokens.size() - 1; ++i)
+ tokens.at(i) = tokens.at(i + 1);
+ tokens.pop_back();
+ }
+
+ if (tokens.size() != 2)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Malformed VDB entry '" + *cur + "'");
+ exit_status |= 8;
+ }
+ else if (! (root / tokens.at(1)).is_directory())
+ cout << "--- [!type] " << tokens.at(1) << endl;
+ else if (DirIterator((root / tokens.at(1)), false) != DirIterator())
+ cout << "--- [!empt] " << tokens.at(1) << endl;
+ else
+ {
+ cout << "<<< " << tokens.at(1) << endl;
+ (root / tokens.at(1)).rmdir();
+ }
+ }
+ }
+ }
+}
+
+int
+main(int argc, char * argv[])
+{
+ Context context("In main program:");
+ exit_status = 0;
+ try
+ {
+ if (argc != 3)
+ throw Failure("Usage: " + stringify(argv[0]) + " root contents");
+
+ Log::get_instance()->set_program_name(argv[0]);
+ std::string log_level(getenv_with_default("PALUDIS_EBUILD_LOG_LEVEL", "qa"));
+
+ if (log_level == "debug")
+ Log::get_instance()->set_log_level(ll_debug);
+ else if (log_level == "qa")
+ Log::get_instance()->set_log_level(ll_qa);
+ else if (log_level == "warning")
+ Log::get_instance()->set_log_level(ll_warning);
+ else if (log_level == "silent")
+ Log::get_instance()->set_log_level(ll_silent);
+ else
+ throw Failure("bad value for log level");
+
+ FSEntry root(argv[1]), contents(argv[2]);
+
+ if (! ((root = root.realpath())).is_directory())
+ throw Failure(stringify(argv[1]) + ": not a directory");
+
+ ifstream contents_file(stringify(contents).c_str());
+ if (! contents_file)
+ throw Failure(stringify(contents) + ": not readable");
+
+ std::list<std::string> lines;
+ std::string line;
+ while (std::getline(contents_file, line))
+ lines.push_back(line);
+
+ unmerge_contents(root, lines.begin(), lines.end());
+ unmerge_directories(root, lines.rbegin(), lines.rend());
+ return exit_status;
+ }
+ catch (const Failure & f)
+ {
+ cerr << argv[0] << ": fatal error: " << f.message << endl;
+ return EXIT_FAILURE;
+ }
+ catch (const Exception & e)
+ {
+ cerr << argv[0] << ": fatal error:" << endl
+ << " * " << e.backtrace("\n * ") << e.message()
+ << " (" << e.what() << ")" << endl;
+ return EXIT_FAILURE;
+ }
+ catch (const std::exception & e)
+ {
+ cerr << argv[0] << ": fatal error: " << e.what() << endl;
+ return EXIT_FAILURE;
+ }
+}
+
+
diff --git a/paludis/repositories/e/ebuild/unmerge_TEST.bash b/paludis/repositories/e/ebuild/unmerge_TEST.bash
new file mode 100644
index 000000000..fa006824b
--- /dev/null
+++ b/paludis/repositories/e/ebuild/unmerge_TEST.bash
@@ -0,0 +1,94 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+unmerge_empty_TEST()
+{
+ ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/merge "unmerge_TEST_dir/empty_src" \
+ "unmerge_TEST_dir/empty_dst" \
+ "unmerge_TEST_dir/empty_contents" 1>/dev/null
+ test_return_code
+
+ ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/unmerge "unmerge_TEST_dir/empty_dst" \
+ "unmerge_TEST_dir/empty_contents" 1>/dev/null
+ test_return_code
+
+ ok=
+ for a in unmerge_TEST_dir/empty_dst/* ; do
+ [[ -e "$a" ]] || continue
+ test_equality "$a" ""
+ ok=no
+ done
+ test_equality "$ok" ""
+}
+
+unmerge_files_TEST()
+{
+ ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/merge "unmerge_TEST_dir/files_src" \
+ "unmerge_TEST_dir/files_dst" \
+ "unmerge_TEST_dir/files_contents" 1>/dev/null
+ test_return_code
+
+ ok=
+ for a in unmerge_TEST_dir/files_dst/* ; do
+ [[ -e "$a" ]] || continue
+ ok=yes
+ break
+ done
+ test_equality "$ok" "yes"
+
+ ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/unmerge "unmerge_TEST_dir/files_dst" \
+ "unmerge_TEST_dir/files_contents" 1>/dev/null
+ test_return_code
+
+ ok=
+ for a in unmerge_TEST_dir/files_dst/* ; do
+ [[ -e "$a" ]] || continue
+ test_equality "$a" ""
+ ok=no
+ done
+ test_equality "$ok" ""
+}
+
+unmerge_spaces_TEST()
+{
+ ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/merge "unmerge_TEST_dir/spaces_src" \
+ "unmerge_TEST_dir/spaces_dst" \
+ "unmerge_TEST_dir/spaces_contents"
+ test_return_code
+
+ ok=
+ for a in unmerge_TEST_dir/spaces_dst/* ; do
+ [[ -e "$a" ]] || continue
+ ok=yes
+ break
+ done
+ test_equality "$ok" "yes"
+
+ ${TOP_BUILD_DIR}/paludis/repositories/e/ebuild/unmerge "unmerge_TEST_dir/spaces_dst" \
+ "unmerge_TEST_dir/spaces_contents"
+ test_return_code
+
+ ok=
+ for a in unmerge_TEST_dir/spaces_dst/* ; do
+ [[ -e "$a" ]] || continue
+ test_equality "$a" ""
+ ok=no
+ done
+ test_equality "$ok" ""
+}
+
diff --git a/paludis/repositories/e/ebuild/unmerge_TEST_cleanup.sh b/paludis/repositories/e/ebuild/unmerge_TEST_cleanup.sh
new file mode 100755
index 000000000..e0f01b607
--- /dev/null
+++ b/paludis/repositories/e/ebuild/unmerge_TEST_cleanup.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d unmerge_TEST_dir ] ; then
+ rm -fr unmerge_TEST_dir
+else
+ true
+fi
+
+
+
diff --git a/paludis/repositories/e/ebuild/unmerge_TEST_setup.sh b/paludis/repositories/e/ebuild/unmerge_TEST_setup.sh
new file mode 100755
index 000000000..33643aa89
--- /dev/null
+++ b/paludis/repositories/e/ebuild/unmerge_TEST_setup.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir -p unmerge_TEST_dir/{empty_src,empty_dst} || exit 2
+
+mkdir -p unmerge_TEST_dir/{files_src,files_dst} || exit 3
+echo "file one" > unmerge_TEST_dir/files_src/one
+echo "file two" > unmerge_TEST_dir/files_src/two
+
+mkdir -p unmerge_TEST_dir/{spaces_src,spaces_dst} || exit 4
+echo "file one" > unmerge_TEST_dir/spaces_src/"file one"
+mkdir -p unmerge_TEST_dir/spaces_src/"dir two"
+echo "file two" > unmerge_TEST_dir/spaces_src/"dir two"/"file two"
+ln -s "link three" unmerge_TEST_dir/spaces_src/"link three"
+
diff --git a/paludis/repositories/e/ebuild/usage_error.bash b/paludis/repositories/e/ebuild/usage_error.bash
new file mode 100644
index 000000000..0af5b2d47
--- /dev/null
+++ b/paludis/repositories/e/ebuild/usage_error.bash
@@ -0,0 +1,31 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+ebuild_f_usage_error()
+{
+ if [[ -z ${1} ]] ; then
+ die "Usage error"
+ else
+ die "Usage error: ${1}"
+ fi
+}
+
diff --git a/paludis/repositories/e/ebuild/utils/Makefile.am b/paludis/repositories/e/ebuild/utils/Makefile.am
new file mode 100644
index 000000000..681d0c319
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/Makefile.am
@@ -0,0 +1,93 @@
+MAINTAINERCLEANFILES = Makefile.in
+SUBDIRS = . exheres-0
+
+libexecprogdir = $(libexecdir)/paludis/utils
+
+libexecprog_SCRIPTS = \
+ canonicalise \
+ dobin \
+ doconfd \
+ dodir \
+ dodoc \
+ doenvd \
+ doexe \
+ dohard \
+ dohtml \
+ doinfo \
+ doinitd \
+ doins \
+ dolib \
+ dolib.a \
+ dolib.so \
+ doman \
+ domo \
+ donewins \
+ dosbin \
+ dosed \
+ dosym \
+ dounpack \
+ emake \
+ fowners \
+ fperms \
+ getmtime \
+ getfsize \
+ newbin \
+ newconfd \
+ newdoc \
+ newenvd \
+ newexe \
+ newinitd \
+ newins \
+ newlib.a \
+ newlib.so \
+ newman \
+ newsbin \
+ prepall \
+ prepallstrip \
+ prepstrip \
+ prepallman \
+ prepman \
+ prepallinfo \
+ prepinfo \
+ prepdocs \
+ prepalldocs
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@
+
+TESTS_ENVIRONMENT = env \
+ PALUDIS_EBUILD_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise \
+ $(top_srcdir)/paludis/repositories/e/ebuild/`" \
+ TOP_BUILD_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/`" \
+ PALUDIS_EBUILD_LOG_LEVEL="silent" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ bash $(top_srcdir)/paludis/repositories/e/ebuild/utils/run_test.bash
+
+TESTS = dobin_TEST.bash getfsize_TEST.bash
+
+prep_scripts = prepall prepallstrip prepallman prepallinfo prepstrip prepman prepinfo prepdocs prepalldocs
+
+EXTRA_DIST = $(libexecprog_SCRIPTS) $(check_SCRIPTS) run_test.bash \
+ newlib.so.in newlib.a.in dolib.so.in dolib.a.in prep.in $(TESTS)
+
+CLEANFILES = *~ newlib.so newlib.a dolib.so dolib.a $(prep_scripts)
+
+newlib.a : newlib.a.in
+ cat $? > $@
+
+newlib.so : newlib.so.in
+ cat $? > $@
+
+dolib.so : dolib.so.in
+ cat $? > $@
+
+dolib.a : dolib.a.in
+ cat $? > $@
+
+$(prep_scripts) : prep.in
+ cat $? > $@
+
+check_PROGRAMS =
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
diff --git a/paludis/repositories/e/ebuild/utils/canonicalise b/paludis/repositories/e/ebuild/utils/canonicalise
new file mode 100755
index 000000000..b186eba65
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/canonicalise
@@ -0,0 +1,6 @@
+#!/bin/bash
+case $(uname -s) in
+ FreeBSD) realpath "$@" ;;
+ *) readlink -f "$@" ;;
+esac
+
diff --git a/paludis/repositories/e/ebuild/utils/dobin b/paludis/repositories/e/ebuild/utils/dobin
new file mode 100755
index 000000000..506f50f0f
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/dobin
@@ -0,0 +1,48 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon dobin from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+if [[ ! -d ${D} ]]; then
+ echo "${0}: \${D} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -lt 1 ]]; then
+ echo "${0}: at least one argument needed" >&2
+ exit 1
+fi
+
+if [[ ! -d "${D}${DESTTREE}/bin" ]]; then
+ install -d "${D}${DESTTREE}/bin" || exit 3
+fi
+
+ret=0
+for x in "$@" ; do
+ if [[ -x "${x}" ]]; then
+ install "${x}" "${D}${DESTTREE}/bin" || ret=2
+ else
+ echo ">>> ${0}: making ${x} executable..."
+ install -m0755 -o root -g 0 "${x}" "${D}${DESTTREE}/bin" || ret=2
+ fi
+done
+
+exit ${ret}
diff --git a/paludis/repositories/e/ebuild/utils/dobin_TEST.bash b/paludis/repositories/e/ebuild/utils/dobin_TEST.bash
new file mode 100644
index 000000000..1af77004f
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/dobin_TEST.bash
@@ -0,0 +1,70 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+source ${PALUDIS_EBUILD_DIR}/install_functions.bash
+
+dobin_TEST()
+{
+ mkdir -p dobin_TEST_dir/src dobin_TEST_dir/dst ; test_return_code
+
+ echo "one contents" > dobin_TEST_dir/src/one ; test_return_code
+ chmod +x dobin_TEST_dir/src/one ; test_return_code
+
+ echo "two contents" > dobin_TEST_dir/src/two ; test_return_code
+ chmod +x dobin_TEST_dir/src/two ; test_return_code
+
+ echo "three contents" > dobin_TEST_dir/src/three ; test_return_code
+ chmod +x dobin_TEST_dir/src/three ; test_return_code
+
+ export D=dobin_TEST_dir/dst
+ ${PALUDIS_EBUILD_DIR}/utils/dobin dobin_TEST_dir/src/one &>/dev/null ; test_return_code
+ ${PALUDIS_EBUILD_DIR}/utils/dobin dobin_TEST_dir/src/two dobin_TEST_dir/src/three &>/dev/null ; test_return_code
+
+ [[ -f dobin_TEST_dir/dst/usr/bin/one ]] ; test_return_code
+ [[ -f dobin_TEST_dir/dst/usr/bin/two ]] ; test_return_code
+ [[ -f dobin_TEST_dir/dst/usr/bin/three ]] ; test_return_code
+
+ test_equality "$(< dobin_TEST_dir/dst/usr/bin/one)" "one contents"
+ test_equality "$(< dobin_TEST_dir/dst/usr/bin/two)" "two contents"
+ test_equality "$(< dobin_TEST_dir/dst/usr/bin/three)" "three contents"
+
+ rm -fr dobin_TEST_dir
+}
+
+dobin_fail_TEST()
+{
+ mkdir -p dobin_TEST_dir/src dobin_TEST_dir/dst ; test_return_code
+ echo "one contents" > dobin_TEST_dir/src/one ; test_return_code
+ echo "two contents" > dobin_TEST_dir/src/two ; test_return_code
+ echo "three contents" > dobin_TEST_dir/src/three ; test_return_code
+
+ export D=dobin_TEST_dir/dst
+ ! ${PALUDIS_EBUILD_DIR}/utils/dobin dobin_TEST_dir/src/four &>/dev/null ; test_return_code
+ ! ${PALUDIS_EBUILD_DIR}/utils/dobin dobin_TEST_dir/src/one dobin_TEST_dir/src/seven &>/dev/null ; test_return_code
+ ! ${PALUDIS_EBUILD_DIR}/utils/dobin dobin_TEST_dir/src/eight dobin_TEST_dir/src/one &>/dev/null ; test_return_code
+
+ [[ -f dobin_TEST_dir/dst/usr/bin/one ]] ; test_return_code
+ ! [[ -f dobin_TEST_dir/dst/usr/bin/four ]] ; test_return_code
+ ! [[ -f dobin_TEST_dir/dst/usr/bin/five ]] ; test_return_code
+ ! [[ -f dobin_TEST_dir/dst/usr/bin/six ]] ; test_return_code
+
+ test_equality "$(< dobin_TEST_dir/dst/usr/bin/one)" "one contents"
+
+ rm -fr dobin_TEST_dir
+}
+
diff --git a/paludis/repositories/e/ebuild/utils/doconfd b/paludis/repositories/e/ebuild/utils/doconfd
new file mode 100644
index 000000000..37c453cc9
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/doconfd
@@ -0,0 +1,32 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon doconfd from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [ ${#} -lt 1 ]; then
+ echo "${0}: at least one argument needed" >&2
+ exit 1
+fi
+
+INSDESTTREE=/etc/conf.d/
+doins "$@" || exit 2
diff --git a/paludis/repositories/e/ebuild/utils/dodir b/paludis/repositories/e/ebuild/utils/dodir
new file mode 100644
index 000000000..52b7c2090
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/dodir
@@ -0,0 +1,34 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon dodir from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+if [[ ! -d ${D} ]]; then
+ echo "${0}: \${D} not valid; aborting" >&2
+ exit 247
+fi
+
+ret=0
+for x in "$@"; do
+ install -d ${DIROPTIONS} "${D}${x}" || ret=2
+done
+
+exit ${ret}
diff --git a/paludis/repositories/e/ebuild/utils/dodoc b/paludis/repositories/e/ebuild/utils/dodoc
new file mode 100644
index 000000000..edd6b6525
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/dodoc
@@ -0,0 +1,50 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon dodoc from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+if [[ ! -d ${D} ]]; then
+ echo "${0}: \${D} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ $# -lt 1 ]]; then
+ echo "${0}: at least one argument needed" >&2
+ exit 1
+fi
+
+dir="${D}usr/share/doc/${PF}/${DOCDESTTREE}"
+if [[ ! -d "${dir}" ]]; then
+ install -d "${dir}" || exit 3
+fi
+
+ret=0
+
+for x in "$@"; do
+ if [[ -s "${x}" ]]; then
+ install -m0644 "${x}" "${dir}"
+ elif [[ ! -e "${x}" ]]; then
+ echo "${0}: ${x} does not exist" >&2
+ ret=2
+ fi
+done
+
+exit ${ret}
diff --git a/paludis/repositories/e/ebuild/utils/doenvd b/paludis/repositories/e/ebuild/utils/doenvd
new file mode 100644
index 000000000..7299776f9
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/doenvd
@@ -0,0 +1,32 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon doenvd from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ${#} -lt 1 ]]; then
+ echo "${0}: at least one argument needed" >&2
+ exit 1
+fi
+
+export INSDESTTREE=/etc/env.d/
+doins "$@"
diff --git a/paludis/repositories/e/ebuild/utils/doexe b/paludis/repositories/e/ebuild/utils/doexe
new file mode 100644
index 000000000..a67166b09
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/doexe
@@ -0,0 +1,58 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon doexe from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+if [[ ! -d ${D} ]]; then
+ echo "${0}: \${D} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ! -d ${T} ]]; then
+ echo "${0}: \${T} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -lt 1 ]]; then
+ echo "${0}: at least one argument needed"
+ exit 1
+fi
+
+if [[ ! -d "${D}${EXEDESTTREE}" ]]; then
+ install -d "${D}${EXEDESTTREE}" || exit 3
+fi
+
+ret=0
+
+for x in "$@"; do
+ if [[ -L ${x} ]]; then
+ cp "${x}" "${T}"
+ mysrc="${T}/$(/usr/bin/basename "${x}")"
+ elif [[ -d ${x} ]]; then
+ echo "${0}: skipping directory ${x}" >&2
+ continue
+ else
+ mysrc="${x}"
+ fi
+ install ${EXEOPTIONS} "${mysrc}" "${D}${EXEDESTTREE}" || ret=2
+done
+
+exit ${ret}
diff --git a/paludis/repositories/e/ebuild/utils/dohard b/paludis/repositories/e/ebuild/utils/dohard
new file mode 100644
index 000000000..b0758e5ae
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/dohard
@@ -0,0 +1,34 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon dohard from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+if [[ ! -d ${D} ]]; then
+ echo "${0}: \${D} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -ne 2 ]]; then
+ echo "${0}: exactly two arguments needed" >&2
+ exit 1
+fi
+
+ln -f "${D}${1}" "${D}${2}"
diff --git a/paludis/repositories/e/ebuild/utils/dohtml b/paludis/repositories/e/ebuild/utils/dohtml
new file mode 100644
index 000000000..09743c9ce
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/dohtml
@@ -0,0 +1,122 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon dohtml from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+source ${PALUDIS_EBUILD_DIR}/list_functions.bash
+
+if [[ ! -d ${D} ]]; then
+ echo "${0}: \${D} not valid; aborting" >&2
+ exit 247
+fi
+
+allowed_exts="png gif html htm jpg css jps"
+disallowed_dirs=""
+allowed_files=""
+recurse=0
+args=( )
+
+split_names() {
+ list=$1
+ if [[ ${list} == *,* ]]; then
+ echo -n "${list%%,*} "
+ split_names ${list#*,}
+ else
+ echo ${list}
+ fi
+}
+
+parse_args() {
+ while [[ ${#} -gt 0 ]]; do
+ case $1 in
+ -r)
+ recurse=1 ;;
+ -V)
+ verbose=1 ;;
+ -A)
+ allowed_exts="${allowed_exts} $(split_names $2)"
+ shift
+ ;;
+ -a)
+ allowed_exts="$(split_names $2)"
+ shift
+ ;;
+ -f)
+ allowed_files="$(split_names $2)"
+ shift
+ ;;
+ -x)
+ disallowed_dirs="$(split_names $2)"
+ shift
+ ;;
+ *)
+ args=( "${args[@]}" "$1" ) ;;
+ esac
+ shift
+ done
+}
+
+install_file() {
+ local bn=${1}
+ local dn=${2}
+ local prefix=${3}
+ local ret=0
+
+ path=${bn}
+ [[ -n ${prefix} ]] && path="${prefix}/${path}"
+ [[ -n ${dn} ]] && path="${dn}/${path}"
+
+ [[ -z ${DOCDESTTREE} ]] && DOCDESTTREE="html"
+
+ dir="${D}usr/share/doc/${PF}/${DOCDESTTREE}/${prefix}"
+
+ if [[ -f ${path} ]]; then
+ ext="$(basename ${path})"
+ ext="${ext##*.}"
+ if ([[ -n ${ext} ]] && has $ext $allowed_exts) || has $bn $allowed_files
+ then
+ [[ ! -d ${dir} ]] && install -d "${dir}"
+ echo "install -m0644 ${path} ${dir}"
+ install -m0644 "${path}" "${dir}/${bn}"
+ fi
+ elif [[ $recurse == 1 && -d ${path} ]] &&
+ ! has "${bn}" ${disallowed_dirs}; then
+ for f in ${path}/*; do
+ pfx=${bn}
+ [[ -n ${prefix} ]] && pfx="${prefix}/${pfx}"
+ install_file "$(basename "${f}")" "${dn}" "${pfx}"
+ (( ret += $? ))
+ done
+ else
+ (( ++ret ))
+ fi
+ return ${ret}
+}
+
+parse_args "$@"
+
+retval=0
+for i in "${args[@]}"; do
+ install_file "$(basename "${i}")" "$(dirname "${i}")"
+ (( retval += $? ))
+done
+
+exit $retval
diff --git a/paludis/repositories/e/ebuild/utils/doinfo b/paludis/repositories/e/ebuild/utils/doinfo
new file mode 100644
index 000000000..df3040ea0
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/doinfo
@@ -0,0 +1,50 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon doinfo from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+if [[ ! -d ${D} ]]; then
+ echo "${0}: \${D} not valid; aborting" >&2
+ exit 1
+fi
+
+if [[ ${#} -lt 1 ]]; then
+ echo "${0}: at least one argument needed" >&2
+ exit 1
+fi
+
+if [[ ! -d "${D}usr/share/info" ]]; then
+ install -d "${D}usr/share/info" || exit 3
+fi
+
+ret=0
+
+for x in "$@"; do
+ if [[ -e "${x}" ]]; then
+ install -m0644 "${x}" "${D}usr/share/info"
+ else
+ echo "${0}: ${x} does not exist"
+ ret=2
+ fi
+done
+
+exit ${ret}
+
diff --git a/paludis/repositories/e/ebuild/utils/doinitd b/paludis/repositories/e/ebuild/utils/doinitd
new file mode 100644
index 000000000..8fc7080da
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/doinitd
@@ -0,0 +1,32 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon doinitd from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ${#} -lt 1 ]]; then
+ echo "${0}: at least one argument needed" >&2
+ exit 1
+fi
+
+EXEDESTTREE=/etc/init.d
+doexe "$@"
diff --git a/paludis/repositories/e/ebuild/utils/doins b/paludis/repositories/e/ebuild/utils/doins
new file mode 100644
index 000000000..2d70f5acf
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/doins
@@ -0,0 +1,89 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon doins from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ! -d ${D} ]]; then
+ echo "${0}: \${D} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ! -d ${T} ]]; then
+ echo "${0}: \${T} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -lt 1 ]]; then
+ echo "${0}: at least one argument needed" >&2
+ exit 1
+fi
+
+if [[ ${1} == "-r" ]]; then
+ DOINSRECUR=y
+ shift
+else
+ DOINSRECUR=n
+fi
+
+if [[ -z "${INSDEPTH}" ]]; then
+ declare -i INSDEPTH=0
+fi
+
+if [[ ${INSDESTTREE} == ${D}* ]]; then
+ echo "-------------------------------------------------------" >&2
+ echo "You should not use \${D} with helpers." >&2
+ echo " --> ${INSDESTTREE}" >&2
+ echo "-------------------------------------------------------" >&2
+ exit 248
+fi
+
+if [[ ! -d "${D}${INSDESTTREE}" ]]; then
+ dodir "${INSDESTTREE}"
+fi
+
+ret=0
+
+for x in "$@"; do
+ if [[ -L ${x} ]]; then
+ cp "${x}" "${T}"
+ mysrc="${T}/$(basename "${x}")"
+ elif [[ -d ${x} ]]; then
+ if [[ ${DOINSRECUR} == "n" ]]; then
+ continue
+ fi
+
+ mydir="${INSDESTTREE}/$(basename "${x}")"
+ find "${x}" -mindepth 1 -maxdepth 1 -exec \
+ env \
+ INSDESTTREE="${mydir}" \
+ INSDEPTH=$((INSDEPTH+1)) \
+ ${0} -r {} \;
+ continue
+ else
+ mysrc="${x}"
+ fi
+
+ install ${INSOPTIONS} "${mysrc}" "${D}${INSDESTTREE}" || ret=2
+done
+
+exit ${ret}
diff --git a/paludis/repositories/e/ebuild/utils/dolib b/paludis/repositories/e/ebuild/utils/dolib
new file mode 100644
index 000000000..c35b20245
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/dolib
@@ -0,0 +1,62 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon dolib from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+if [[ ! -d ${D} ]]; then
+ echo "${0}: \${D} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ! -d ${PALUDIS_EBUILD_MODULES_DIR} ]]; then
+ echo "${0}: \${PALUDIS_EBUILD_MODULES_DIR} not valid; aborting" >&2
+ exit 1
+fi
+
+source "${PALUDIS_EBUILD_MODULES_DIR}/multilib_functions.bash"
+
+libdir="${D}${DESTTREE}/$(ebuild_get_libdir)"
+
+if [[ ${#} -lt 1 ]]; then
+ echo "${0}: at least one argument needed"
+ exit 1
+fi
+
+if [[ ! -d ${libdir} ]]; then
+ install -d "${libdir}" || exit 3
+fi
+
+ret=0
+
+for x in "$@"; do
+ if [[ -e ${x} ]]; then
+ if [[ ! -L ${x} ]]; then
+ install ${LIBOPTIONS} "${x}" "${libdir}" || ret=2
+ else
+ ln -s "$(readlink "${x}")" "${libdir}/$(basename "${x}")" || ret=2
+ fi
+ else
+ echo "${0}: ${x} does not exist"
+ ret=2
+ fi
+done
+
+exit ${ret}
diff --git a/paludis/repositories/e/ebuild/utils/dolib.a.in b/paludis/repositories/e/ebuild/utils/dolib.a.in
new file mode 100644
index 000000000..e766554dd
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/dolib.a.in
@@ -0,0 +1,27 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon dolib.a from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+LIBOPTIONS="-m0644" dolib "$@"
+
diff --git a/paludis/repositories/e/ebuild/utils/dolib.so.in b/paludis/repositories/e/ebuild/utils/dolib.so.in
new file mode 100644
index 000000000..d4dcb4a46
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/dolib.so.in
@@ -0,0 +1,26 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon dolib.so from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+LIBOPTIONS="-m0755" dolib "$@"
diff --git a/paludis/repositories/e/ebuild/utils/doman b/paludis/repositories/e/ebuild/utils/doman
new file mode 100644
index 000000000..ff5435627
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/doman
@@ -0,0 +1,75 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon doman from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+if [[ ! -d ${D} ]]; then
+ echo "${0}: \${D} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -lt 1 ]]; then
+ echo "${0}: at least one argument needed" >&2
+ exit 1
+fi
+
+BASE="/usr/share"
+i18n=""
+
+for x in "$@"; do
+ if [[ ${x:0:6} == "-i18n=" ]]; then
+ i18n="${x:6}/"
+ continue
+ fi
+ if [[ ${x} == .keep ]]; then
+ continue
+ fi
+
+ suffix=${x##*.}
+
+ if [[ ${suffix} == "gz" ]]; then
+ realname=${x%.*}
+ suffix=${realname##*.}
+ else
+ realname=${x}
+ fi
+
+ mandir="${i18n}man${suffix:0:1}"
+ match='man[0-9n](|f|p|pm)$'
+
+ if [[ ${mandir} =~ ${match} ]]; then
+ if [[ -s ${x} ]]; then
+ if [[ ! -d "${D}${BASE}/man/${mandir}" ]]; then
+ install -d "${D}${BASE}/man/${mandir}"
+ fi
+
+ install -m0644 "${x}" "${D}${BASE}/man/${mandir}" || ret=2
+ else
+ echo "${0}: ${x} does not exist" >&2
+ ret=2
+ fi
+ else
+ echo "${0}: '${x}' is probably not a man page; skipping" >&2
+ ret=2
+ fi
+done
+
+exit ${ret}
diff --git a/paludis/repositories/e/ebuild/utils/domo b/paludis/repositories/e/ebuild/utils/domo
new file mode 100644
index 000000000..b7a0dd413
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/domo
@@ -0,0 +1,54 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon domo from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+if [[ ! -d ${D} ]]; then
+ echo "${0}: \${D} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -lt 1 ]]; then
+ echo "${0}: at least one argument needed" >&2
+ exit 1
+fi
+
+if [[ ! -d "${D}${DESTTREE}/share/locale" ]]; then
+ install -d "${D}${DESTTREE}/share/locale" || exit 3
+fi
+
+ret=0
+
+for x in "$@"; do
+ if [[ -e ${x} ]]; then
+ mytiny="$(basename "${x}")"
+ mydir="${D}${DESTTREE}/share/local/${mytiny%.*}/LC_MESSAGES"
+ if [[ ! -d ${mydir} ]]; then
+ install -d "${mydir}"
+ fi
+ install -m0644 "${x}" "${mydir}/${MOPREFIX}.mo" || ret=2
+ else
+ echo "${0}: ${x} does not exist" >&2
+ ret=2
+ fi
+done
+
+exit ${ret}
diff --git a/paludis/repositories/e/ebuild/utils/donewins b/paludis/repositories/e/ebuild/utils/donewins
new file mode 100644
index 000000000..90f037799
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/donewins
@@ -0,0 +1,40 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon donewins from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ! -d ${T} ]]; then
+ echo "${0}: \${T} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -ne 2 ]]; then
+ echo "${0}: exactly two arguments needed." >&2
+ exit 1
+fi
+
+ebuild_notice "qa" "${0} is retarded. Don't use it; use newins instead."
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+doins "${T}/${2}"
diff --git a/paludis/repositories/e/ebuild/utils/dosbin b/paludis/repositories/e/ebuild/utils/dosbin
new file mode 100644
index 000000000..25c625801
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/dosbin
@@ -0,0 +1,45 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon dosbin from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+if [[ ! -d ${D} ]]; then
+ echo "${0}: \${D} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -lt 1 ]]; then
+ echo "${0}: at least one argument needed" >&2
+ exit 1
+fi
+
+if [[ ! -d "${D}${DESTTREE}/sbin" ]]; then
+ install -d "${D}${DESTTREE}/sbin" || exit 3
+fi
+
+for x in "$@"; do
+ if [[ -x ${x} ]]; then
+ install -m0755 "${x}" "${D}${DESTTREE}/sbin" || exit 2
+ else
+ echo ">>> dosbin: making ${x} executable..."
+ install -m0755 -o root -g 0 "${x}" "${D}${DESTTREE}/sbin" || exit 2
+ fi
+done
diff --git a/paludis/repositories/e/ebuild/utils/dosed b/paludis/repositories/e/ebuild/utils/dosed
new file mode 100644
index 000000000..ca9dc0429
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/dosed
@@ -0,0 +1,52 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon dosed from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+if [[ ! -d ${D} ]]; then
+ echo "${0}: \${D} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -lt 1 ]]; then
+ echo "${0}: at least one argument needed" >&2
+ exit 1
+fi
+
+mysed="s:${D}::g"
+
+ret=0
+
+for x in "$@"; do
+ y="${D}${x}"
+ if [[ -e ${y} ]]; then
+ if [[ -f "${y}" ]]; then
+ sed -i -e "${mysed}" "${y}" || ret=2
+ else
+ echo "${0}: ${y} is not a regular file"
+ ret=2
+ fi
+ else
+ mysed="${x}"
+ fi
+done
+
+exit ${ret}
diff --git a/paludis/repositories/e/ebuild/utils/dosym b/paludis/repositories/e/ebuild/utils/dosym
new file mode 100644
index 000000000..818ef1aaa
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/dosym
@@ -0,0 +1,42 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon dosym from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+source ${PALUDIS_EBUILD_DIR}/echo_functions.bash
+
+if [[ ! -d ${D} ]]; then
+ echo "${0}: \${D} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -ne 2 ]]; then
+ echo "${0}: exactly two arguments needed" >&2
+ exit 1
+fi
+
+if [[ ! -d $(dirname "${D}$2") ]]; then
+ ebuild_notice "qa" "$0: target directory ${D}$2 does not exist; creating. Please fix the ebuild to create it explicitly."
+ dodir $(dirname $2)
+fi
+
+ln -snf "${1}" "${D}${2}"
diff --git a/paludis/repositories/e/ebuild/utils/dounpack b/paludis/repositories/e/ebuild/utils/dounpack
new file mode 100755
index 000000000..8de948caf
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/dounpack
@@ -0,0 +1,132 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+die()
+{
+ echo "dounpack: error: $@" 1>&2
+ exit 123
+}
+
+unpack_one()
+{
+ [[ -z "$1" ]] && die "Bad argument for unpack_one"
+ [[ -e "$1" ]] || die "${1} doesn't exist"
+
+ if [[ -n "${UNPACKONLY}" ]] ; then
+ case "${x}" in
+ *.tar.bz2|*.tbz2)
+ ;;
+
+ *)
+ die "Can't use --only with ${x}"
+ ;;
+ esac
+ fi
+
+ case "${x}" in
+ *.tar)
+ echo tar xf "${1}" --no-same-owner "${TAR_OPTIONS[@]}" 1>&2
+ tar xf "${1}" --no-same-owner "${TAR_OPTIONS[@]}" || die "Couldn't unpack ${1}"
+ ;;
+
+ *.tar.gz|*.tgz|*.tar.Z)
+ echo tar zxf "${1}" --no-same-owner "${TAR_OPTIONS[@]}" 1>&2
+ tar zxf "${1}" --no-same-owner "${TAR_OPTIONS[@]}" || die "Couldn't unpack ${1}"
+ ;;
+
+ *.tar.bz2|*.tbz2)
+ echo tar jxf "${1}" --no-same-owner "${TAR_OPTIONS[@]}" ${UNPACKONLY} 1>&2
+ tar jxf "${1}" --no-same-owner "${TAR_OPTIONS[@]}" ${UNPACKONLY} || die "Couldn't unpack ${1}"
+ ;;
+
+ *.zip|*.ZIP|*.jar)
+ echo unzip -qo "${1}" 1>&2
+ unzip -qo "${1}" || die "Couldn't unpack ${1}"
+ ;;
+
+ *.gz|*.Z|*.z)
+ echo gzip -dc "${1}" > ${UNPACKTODIR}/$(basename "${1%.*}" ) 1>&2
+ gzip -dc "${1}" > ${UNPACKTODIR}/$(basename "${1%.*}" ) || die "Couldn't unpack ${1}"
+ ;;
+
+ *.bz2)
+ echo bzip2 -dc "${1}" > ${UNPACKTODIR}/$(basename "${1%.*}" ) 1>&2
+ bzip2 -dc "${1}" > ${UNPACKTODIR}/$(basename "${1%.*}" ) || die "Couldn't unpack ${1}"
+ ;;
+
+ *.rar|*.RAR)
+ echo unrar x -idq "${1}" 1>&2
+ unrar x -idq "${1}" || die "Couldn't unpack ${1}"
+ ;;
+
+ *.LHa|*.LHA|*.lha|*.lzh)
+ echo lha xqf "${1}" 1>&2
+ lha xqf "${1}" || die "Couldn't unpack ${1}"
+ ;;
+
+ *.a|*.deb)
+ echo ar x "${1}" 1>&2
+ ar x "${1}" 1>&2
+ ;;
+
+ *)
+ echo "Skipping unpack for ${1}"
+ ;;
+ esac
+
+}
+
+export UNPACKFROMDIR="${DISTDIR}"
+export UNPACKTODIR="${PWD}"
+
+if [[ "${1}" == "--binary" ]] ; then
+ export UNPACKFROMDIR="${PKGDIR}"
+ export UNPACKTODIR="${IMAGE}"
+ shift
+fi
+
+unset UNPACKONLY
+if [[ "${1}" == "--only" ]] ; then
+ shift
+ export UNPACKONLY="${1}"
+ shift
+fi
+
+TAR_OPTIONS=( )
+while [[ "${1}" == --tar-option=* ]] ; do
+ TAR_OPTIONS[${#TAR_OPTIONS[@]}]="${1#*=}"
+ shift
+done
+
+[[ -z "$@" ]] && die "No arguments given to unpack"
+
+for x in "$@" ; do
+ x=$(echo $x )
+ echo ">>> Unpacking ${x} to ${UNPACKTODIR}"
+ [[ "${x:0:2}" == "./" ]] || x="${UNPACKFROMDIR}/${x}"
+ mkdir -p ${UNPACKTODIR}
+ cd ${UNPACKTODIR}
+ unpack_one "${x}"
+done
+
+
diff --git a/paludis/repositories/e/ebuild/utils/emake b/paludis/repositories/e/ebuild/utils/emake
new file mode 100755
index 000000000..57ffa4ca4
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/emake
@@ -0,0 +1,22 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+echo ${EMAKE_WRAPPER} ${MAKE:-make} ${MAKEOPTS} ${EXTRA_EMAKE} "$@" 1>&2
+${EMAKE_WRAPPER} ${MAKE:-make} ${MAKEOPTS} ${EXTRA_EMAKE} "$@"
+
diff --git a/paludis/repositories/e/ebuild/utils/exheres-0/Makefile.am b/paludis/repositories/e/ebuild/utils/exheres-0/Makefile.am
new file mode 100644
index 000000000..f0f99f450
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/exheres-0/Makefile.am
@@ -0,0 +1,49 @@
+MAINTAINERCLEANFILES = Makefile.in
+SUBDIRS = .
+
+libexecprogdir = $(libexecdir)/paludis/utils/exheres-0
+
+libexecprog_SCRIPTS = \
+ dohard \
+ dosed \
+ donewins \
+ prepall \
+ prepallstrip \
+ prepstrip \
+ prepallman \
+ prepman \
+ prepallinfo \
+ prepinfo \
+ prepdocs \
+ prepalldocs \
+ banned_in_eapi_exheres-0
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@
+
+TESTS_ENVIRONMENT = env \
+ PALUDIS_UTILITY_PATH_SUFFIXES="exheres-0" \
+ PALUDIS_EBUILD_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise \
+ $(top_srcdir)/paludis/repositories/e/ebuild/`" \
+ TOP_BUILD_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/`" \
+ PALUDIS_EBUILD_LOG_LEVEL="silent" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ bash $(top_srcdir)/paludis/repositories/e/ebuild/utils/run_test.bash
+
+TESTS =
+
+EXTRA_DIST = $(libexecprog_SCRIPTS) $(check_SCRIPTS) \
+ banned_in_eapi_exheres-0 $(TESTS)
+
+bannedscripts = prepall prepallstrip prepstrip prepallman prepman prepallinfo \
+ prepinfo prepdocs prepalldocs dohard donewins dosed
+
+CLEANFILES = *~ $(bannedscripts)
+
+$(bannedscripts) : banned_in_eapi_exheres-0
+ cat $? > $@
+
+check_PROGRAMS =
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
diff --git a/paludis/repositories/e/ebuild/utils/exheres-0/banned_in_eapi_exheres-0 b/paludis/repositories/e/ebuild/utils/exheres-0/banned_in_eapi_exheres-0
new file mode 100755
index 000000000..937c70cd9
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/exheres-0/banned_in_eapi_exheres-0
@@ -0,0 +1,25 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+COLOUR_RED=$'\e[31;01m'
+COLOUR_NORMAL=$'\e[0m'
+
+echo "${COLOUR_RED}!!! Ebuild bug: '$(basename ${0} )' banned in EAPI exheres-0${COLOUR_NORMAL}"
+exit 123
+
diff --git a/paludis/repositories/e/ebuild/utils/fowners b/paludis/repositories/e/ebuild/utils/fowners
new file mode 100644
index 000000000..4eb208c6e
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/fowners
@@ -0,0 +1,24 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon fowners from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+chown "${@/#\//${D}/}"
diff --git a/paludis/repositories/e/ebuild/utils/fperms b/paludis/repositories/e/ebuild/utils/fperms
new file mode 100644
index 000000000..04c5db7eb
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/fperms
@@ -0,0 +1,24 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon fperms from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+chmod "${@/#\//${D}/}"
diff --git a/paludis/repositories/e/ebuild/utils/getfsize b/paludis/repositories/e/ebuild/utils/getfsize
new file mode 100755
index 000000000..38a271b00
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/getfsize
@@ -0,0 +1,5 @@
+#!/bin/bash
+case $(uname -s) in
+ FreeBSD) stat -f '%z' "$@" ;;
+ *) stat -c '%s' "$@" ;;
+esac
diff --git a/paludis/repositories/e/ebuild/utils/getfsize_TEST.bash b/paludis/repositories/e/ebuild/utils/getfsize_TEST.bash
new file mode 100755
index 000000000..3688bdf4c
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/getfsize_TEST.bash
@@ -0,0 +1,44 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+getfsize_TEST()
+{
+ mkdir -p getfsize_TEST_dir ; test_return_code
+
+ echo -n "12345" > getfsize_TEST_dir/five
+ echo "12345" > getfsize_TEST_dir/six
+
+ ${PALUDIS_EBUILD_DIR}/utils/getfsize getfsize_TEST_dir/five >/dev/null ; test_return_code
+ ${PALUDIS_EBUILD_DIR}/utils/getfsize getfsize_TEST_dir/six >/dev/null ; test_return_code
+
+ [[ $(${PALUDIS_EBUILD_DIR}/utils/getfsize getfsize_TEST_dir/five ) == "5" ]] ; test_return_code
+ [[ $(${PALUDIS_EBUILD_DIR}/utils/getfsize getfsize_TEST_dir/six ) == "6" ]] ; test_return_code
+
+ rm -fr getfsize_TEST_dir
+}
+
+getfsize_fail_TEST()
+{
+ mkdir -p getfsize_TEST_dir ; test_return_code
+
+ ! ${PALUDIS_EBUILD_DIR}/utils/getfsize getfsize_TEST_dir/seven 2>/dev/null ; test_return_code
+
+ rm -fr getfsize_TEST_dir
+}
+
+
diff --git a/paludis/repositories/e/ebuild/utils/getmtime b/paludis/repositories/e/ebuild/utils/getmtime
new file mode 100755
index 000000000..88a74b21f
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/getmtime
@@ -0,0 +1,5 @@
+#!/bin/bash
+case $(uname -s) in
+ FreeBSD) stat -f '%m' "$@" ;;
+ *) stat -c '%Y' "$@" ;;
+esac
diff --git a/paludis/repositories/e/ebuild/utils/newbin b/paludis/repositories/e/ebuild/utils/newbin
new file mode 100644
index 000000000..21792c697
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/newbin
@@ -0,0 +1,38 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon newbin from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ! -d ${T} ]]; then
+ echo "${0}: \${T} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -ne 2 ]]; then
+ echo "${0}: exactly two arguments needed" >&2
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+dobin "${T}/${2}"
diff --git a/paludis/repositories/e/ebuild/utils/newconfd b/paludis/repositories/e/ebuild/utils/newconfd
new file mode 100644
index 000000000..77838656c
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/newconfd
@@ -0,0 +1,38 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon newconfd from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ! -d ${T} ]]; then
+ echo "${0}: \${T} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -ne 2 ]]; then
+ echo "${0}: exactly two arguments needed" >&2
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+doconfd "${T}/${2}"
diff --git a/paludis/repositories/e/ebuild/utils/newdoc b/paludis/repositories/e/ebuild/utils/newdoc
new file mode 100644
index 000000000..b4cb50700
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/newdoc
@@ -0,0 +1,38 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon newdoc from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ! -d ${T} ]]; then
+ echo "${0}: \${T} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -ne 2 ]]; then
+ echo "${0}: exactly two arguments needed" >&2
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+dodoc "${T}/${2}"
diff --git a/paludis/repositories/e/ebuild/utils/newenvd b/paludis/repositories/e/ebuild/utils/newenvd
new file mode 100644
index 000000000..76f0a7f5e
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/newenvd
@@ -0,0 +1,38 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon newenvd from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ! -d ${T} ]]; then
+ echo "${0}: \${T} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -ne 2 ]]; then
+ echo "${0}: exactly two arguments needed" >&2
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+doenvd "${T}/${2}"
diff --git a/paludis/repositories/e/ebuild/utils/newexe b/paludis/repositories/e/ebuild/utils/newexe
new file mode 100644
index 000000000..9a5cb35df
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/newexe
@@ -0,0 +1,38 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon newexe from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ! -d ${T} ]]; then
+ echo "${0}: \${T} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -ne 2 ]]; then
+ echo "${0}: exactly two arguments needed" >&2
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+doexe "${T}/${2}"
diff --git a/paludis/repositories/e/ebuild/utils/newinitd b/paludis/repositories/e/ebuild/utils/newinitd
new file mode 100644
index 000000000..01ca12b2d
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/newinitd
@@ -0,0 +1,38 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon newinitd from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ! -d ${T} ]]; then
+ echo "${0}: \${T} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -ne 2 ]]; then
+ echo "${0}: exactly two arguments needed" >&2
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+doinitd "${T}/${2}"
diff --git a/paludis/repositories/e/ebuild/utils/newins b/paludis/repositories/e/ebuild/utils/newins
new file mode 100644
index 000000000..2b692adb6
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/newins
@@ -0,0 +1,38 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon newins from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ! -d ${T} ]]; then
+ echo "${0}: \${T} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -ne 2 ]]; then
+ echo "${0}: exactly two arguments needed" >&2
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+doins "${T}/${2}"
diff --git a/paludis/repositories/e/ebuild/utils/newlib.a.in b/paludis/repositories/e/ebuild/utils/newlib.a.in
new file mode 100644
index 000000000..415a0571c
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/newlib.a.in
@@ -0,0 +1,38 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon newlib.a from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ! -d ${T} ]]; then
+ echo "${0}: \${T} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -ne 2 ]]; then
+ echo "${0}: exactly two arguments needed" >&2
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+dolib.a "${T}/${2}"
diff --git a/paludis/repositories/e/ebuild/utils/newlib.so.in b/paludis/repositories/e/ebuild/utils/newlib.so.in
new file mode 100644
index 000000000..0701351d8
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/newlib.so.in
@@ -0,0 +1,38 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon newlib.so from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ! -d ${T} ]]; then
+ echo "${0}: \${T} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -ne 2 ]]; then
+ echo "${0}: exactly two arguments needed" >&2
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+dolib.so "${T}/${2}"
diff --git a/paludis/repositories/e/ebuild/utils/newman b/paludis/repositories/e/ebuild/utils/newman
new file mode 100644
index 000000000..0dab5fc16
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/newman
@@ -0,0 +1,38 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon newman from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ! -d ${T} ]]; then
+ echo "${0}: \${T} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -ne 2 ]]; then
+ echo "${0}: exactly two arguments needed" >&2
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+doman "${T}/${2}"
diff --git a/paludis/repositories/e/ebuild/utils/newsbin b/paludis/repositories/e/ebuild/utils/newsbin
new file mode 100644
index 000000000..da94577f7
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/newsbin
@@ -0,0 +1,38 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# Based in part upon newsbin from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+export PATH="${PALUDIS_EBUILD_DIR:+${PALUDIS_EBUILD_DIR}/utils:}${PATH}"
+
+if [[ ! -d ${T} ]]; then
+ echo "${0}: \${T} not valid; aborting" >&2
+ exit 247
+fi
+
+if [[ ${#} -ne 2 ]]; then
+ echo "${0}: exactly two arguments needed" >&2
+ exit 1
+fi
+
+rm -rf "${T}/${2}"
+cp "${1}" "${T}/${2}"
+dosbin "${T}/${2}"
diff --git a/paludis/repositories/e/ebuild/utils/prep.in b/paludis/repositories/e/ebuild/utils/prep.in
new file mode 100644
index 000000000..fcb64959d
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/prep.in
@@ -0,0 +1,21 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Stephen Bennett <spb@gentoo.org>
+#
+# This file is part of the Paludis package manager. Paludis is free software;
+# you can redistribute it and/or modify it under the terms of the GNU General
+# Public License as published by the Free Software Foundation; either version
+# 2 of the License, or (at your option) any later version.
+#
+# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place, Suite 330, Boston, MA 02111-1307 USA
+
+ebuild_notice "qa" "Ebuilds shouldn't be calling $0 manually."
+
diff --git a/paludis/repositories/e/ebuild/utils/run_test.bash b/paludis/repositories/e/ebuild/utils/run_test.bash
new file mode 100644
index 000000000..1f9db4e38
--- /dev/null
+++ b/paludis/repositories/e/ebuild/utils/run_test.bash
@@ -0,0 +1,62 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+shopt -s expand_aliases
+shopt -s extglob
+set +o posix
+
+export TEST_STATUS=
+export PALUDIS_IN_TEST_FRAMEWORK="yes"
+
+test_return_code()
+{
+ local r="$?"
+ if [[ "0" == "${r}" ]] ; then
+ echo -n "."
+ else
+ echo -n "!{retcode: ${r}}"
+ export local_test_status="fail"
+ export TEST_STATUS="fail"
+ fi
+}
+
+test_equality()
+{
+ if [[ "${1}" == "${2}" ]] ; then
+ echo -n "."
+ else
+ echo -n "!{'${1}' not equal to '${2}'}"
+ export local_test_status="fail"
+ export TEST_STATUS="fail"
+ fi
+}
+
+if test -f "$TEST_SCRIPT_DIR""${1%.bash}"_"setup.sh" ; then
+ echo ">>> setup for test ${1%.bash}"
+ if ! "$TEST_SCRIPT_DIR""${1%.bash}"_"setup.sh" ; then
+ echo ">>> exiting with error for test ${1%.bash}"
+ exit 255
+ fi
+fi
+
+echo "Test program ${1%.bash}:"
+source "${1}" || exit 200
+
+for testname in $(set | grep '_TEST *() *$' ) ; do
+ [[ ${testname/()} != ${testname} ]] && continue
+ echo -n "* ${testname%_TEST}: "
+ export local_test_status=""
+ ${testname}
+ [[ -z "$local_test_status" ]] && echo " OK" || echo " FAIL"
+done
+
+if test -f "$TEST_SCRIPT_DIR""${1%.bash}"_"cleanup.sh" ; then
+ echo ">>> cleanup for test ${1%.bash}"
+ if ! "$TEST_SCRIPT_DIR""${1%.bash}"_"cleanup.sh" ; then
+ echo ">>> exiting with error for test ${1%.bash}"
+ exit 255
+ fi
+fi
+
+[[ -z "$TEST_STATUS" ]]
+
diff --git a/paludis/repositories/e/ebuild/work_around_broken_utilities.bash.in b/paludis/repositories/e/ebuild/work_around_broken_utilities.bash.in
new file mode 100644
index 000000000..cb97656b6
--- /dev/null
+++ b/paludis/repositories/e/ebuild/work_around_broken_utilities.bash.in
@@ -0,0 +1,26 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006 Timothy Redaelli <drizzt@gentoo.org>
+#
+# Based in part upon ebuild.sh from Portage, which is Copyright 1995-2005
+# Gentoo Foundation and distributed under the terms of the GNU General
+# Public License v2.
+#
+# 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
+
+@NEED_SED_WRAPPER_TRUE@alias sed=gsed
+@NEED_AWK_WRAPPER_TRUE@alias awk=gawk
+@NEED_MAKE_WRAPPER_TRUE@alias make=gmake
+@NEED_PATCH_WRAPPER_TRUE@alias patch=gpatch
diff --git a/paludis/repositories/e/ebuild/write_vdb_entry.bash b/paludis/repositories/e/ebuild/write_vdb_entry.bash
new file mode 100755
index 000000000..b7591d05a
--- /dev/null
+++ b/paludis/repositories/e/ebuild/write_vdb_entry.bash
@@ -0,0 +1,100 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+#
+# 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
+
+unalias -a
+set +C
+unset GZIP BZIP BZIP2 CDPATH GREP_OPTIONS GREP_COLOR GLOBIGNORE
+eval unset LANG ${!LC_*}
+
+shopt -s expand_aliases
+shopt -s extglob
+
+if [[ -n "${PALUDIS_EBUILD_DIR_FALLBACK}" ]] ; then
+ export PATH="${PALUDIS_EBUILD_DIR_FALLBACK}/utils:${PATH}"
+fi
+export PATH="${PALUDIS_EBUILD_DIR}/utils:${PATH}"
+EBUILD_MODULES_DIR=$(canonicalise $(dirname $0 ) )
+if ! [[ -d ${EBUILD_MODULES_DIR} ]] ; then
+ echo "${EBUILD_MODULES_DIR} is not a directory" 1>&2
+ exit 123
+fi
+export PALUDIS_EBUILD_MODULES_DIR="${EBUILD_MODULES_DIR}"
+
+ebuild_load_module()
+{
+ if ! source "${EBUILD_MODULES_DIR}/${1}.bash" ; then
+ type die && die "Error loading module ${1}"
+ echo "Error loading module ${1}" 1>&2
+ exit 123
+ fi
+}
+
+ebuild_load_module die_functions
+ebuild_load_module echo_functions
+ebuild_load_module work_around_broken_utilities
+
+export PALUDIS_HOME="$(canonicalise ${PALUDIS_HOME:-${HOME}} )"
+
+main()
+{
+ local vdbdir="${1}" envfile="${2}"
+
+ if ! [[ -d "${vdbdir}" ]] ; then
+ echo "!!! vdbdir \"${vdbdir}\" is not a directory"
+ exit 1
+ fi
+
+ ebuild_section "Writing VDB entry to '${vdbdir}'..."
+
+ source ${envfile}
+
+ ebuild_section "Writing VDB entry keys ..."
+
+ local v VDB_FORMAT="paludis-2" COUNTER="$(date +%s )"
+ for v in CATEGORY CHOST COUNTER DEPEND DESCRIPTION EAPI \
+ FEATURES HOMEPAGE INHERITED IUSE KEYWORDS LICENSE PDEPEND PF \
+ PROVIDE RDEPEND SLOT SRC_URI USE CONFIG_PROTECT CONFIG_PROTECT_MASK \
+ VDB_FORMAT PKGMANAGER ; do
+ if ! echo "${!v}" > "${vdbdir}"/${v} ; then
+ echo "!!! vdb write ${v} failed"
+ exit 1
+ fi
+ done
+
+ for v in ASFLAGS CBUILD CC CFLAGS CHOST CTARGET CXX CXXFLAGS \
+ EXTRA_ECONF EXTRA_EINSTALL EXTRA_EMAKE LDFLAGS LIBCXXFLAGS \
+ REPOSITORY ; do
+ [[ -z "${!v}" ]] && continue
+ if ! echo "${!v}" > "${vdbdir}"/${v} ; then
+ echo "!!! vdb write ${v} failed"
+ exit 1
+ fi
+ done
+
+ ebuild_section "Generating saved ebuild and environment..."
+
+ [[ -f "${EBUILD}" ]] && cp "${EBUILD}" ${vdbdir}/
+ sed -e 's:^declare -rx:declare -x:' < ${envfile} | bzip2 > ${vdbdir}/environment.bz2
+
+ ebuild_section "Finished writing VDB entry"
+
+ true
+}
+
+main $@
+
diff --git a/paludis/repositories/e/ebuild_entries.cc b/paludis/repositories/e/ebuild_entries.cc
new file mode 100644
index 000000000..48ccff5d8
--- /dev/null
+++ b/paludis/repositories/e/ebuild_entries.cc
@@ -0,0 +1,688 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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/e/ebuild_entries.hh>
+#include <paludis/repositories/e/ebuild_flat_metadata_cache.hh>
+#include <paludis/repositories/e/portage_repository.hh>
+#include <paludis/repositories/e/ebuild.hh>
+#include <paludis/repositories/e/eapi_phase.hh>
+#include <paludis/repositories/e/ebuild_id.hh>
+
+#include <paludis/eapi.hh>
+#include <paludis/dep_spec_flattener.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_id.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/portage_dep_parser.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/tr1_functional.hh>
+
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+
+#include <fstream>
+#include <list>
+#include <set>
+#include <sys/types.h>
+#include <grp.h>
+#include <functional>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+namespace paludis
+{
+ /**
+ * Implementation data for EbuildEntries.
+ *
+ * \ingroup grpportagerepository
+ */
+ template<>
+ struct Implementation<EbuildEntries>
+ {
+ const Environment * const environment;
+ PortageRepository * const portage_repository;
+ const PortageRepositoryParams params;
+
+ tr1::shared_ptr<EclassMtimes> eclass_mtimes;
+ time_t master_mtime;
+
+ Implementation(const Environment * const e, PortageRepository * const p,
+ const PortageRepositoryParams & k) :
+ environment(e),
+ portage_repository(p),
+ params(k),
+ eclass_mtimes(new EclassMtimes(k.eclassdirs)),
+ master_mtime(0)
+ {
+ FSEntry m(k.location / "metadata" / "timestamp");
+ if (m.exists())
+ master_mtime = m.mtime();
+ }
+ };
+}
+
+EbuildEntries::EbuildEntries(
+ const Environment * const e, PortageRepository * const p, const PortageRepositoryParams & k) :
+ PrivateImplementationPattern<EbuildEntries>(new Implementation<EbuildEntries>(e, p, k))
+{
+}
+
+EbuildEntries::~EbuildEntries()
+{
+}
+
+const tr1::shared_ptr<const PackageID>
+EbuildEntries::make_id(const QualifiedPackageName & q, const VersionSpec & v, const FSEntry & f,
+ const std::string & guessed_eapi) const
+{
+ Context context("When creating ID for '" + stringify(q) + "-" + stringify(v) + "' from '" + stringify(f) + "':");
+
+ tr1::shared_ptr<EbuildID> result(new EbuildID(q, v, _imp->params.environment,
+ _imp->portage_repository->shared_from_this(), f, guessed_eapi,
+ _imp->master_mtime, _imp->eclass_mtimes));
+ return result;
+}
+
+namespace
+{
+ class AAFinder :
+ private InstantiationPolicy<AAFinder, instantiation_method::NonCopyableTag>,
+ public ConstVisitor<URISpecTree>,
+ public ConstVisitor<URISpecTree>::VisitConstSequence<AAFinder, AllDepSpec>,
+ public ConstVisitor<URISpecTree>::VisitConstSequence<AAFinder, UseDepSpec>
+ {
+ private:
+ mutable std::list<const URIDepSpec *> _specs;
+
+ public:
+ void visit_leaf(const URIDepSpec & a)
+ {
+ _specs.push_back(&a);
+ }
+
+ typedef std::list<const URIDepSpec *>::const_iterator Iterator;
+
+ Iterator begin()
+ {
+ return _specs.begin();
+ }
+
+ Iterator end() const
+ {
+ return _specs.end();
+ }
+ };
+
+}
+
+namespace
+{
+ FSEntry
+ get_root(tr1::shared_ptr<const DestinationsCollection> destinations)
+ {
+ if (destinations)
+ for (DestinationsCollection::Iterator d(destinations->begin()), d_end(destinations->end()) ;
+ d != d_end ; ++d)
+ if ((*d)->installed_interface)
+ return (*d)->installed_interface->root();
+
+ return FSEntry("/");
+ }
+
+ std::string make_use(const Environment * const env,
+ const PackageID & id,
+ tr1::shared_ptr<const PortageRepositoryProfile> profile)
+ {
+ std::string use;
+
+ if (id.iuse_key())
+ for (IUseFlagCollection::Iterator i(id.iuse_key()->value()->begin()),
+ i_end(id.iuse_key()->value()->end()) ; i != i_end ; ++i)
+ if (env->query_use(i->flag, id))
+ use += stringify(i->flag) + " ";
+
+ if (id.eapi()->supported)
+ if (id.eapi()->supported->ebuild_options->want_arch_var)
+ use += profile->environment_variable("ARCH") + " ";
+
+ return use;
+ }
+
+ tr1::shared_ptr<AssociativeCollection<std::string, std::string> >
+ make_expand(const Environment * const env,
+ const PackageID & e,
+ tr1::shared_ptr<const PortageRepositoryProfile> profile,
+ std::string & use)
+ {
+ tr1::shared_ptr<AssociativeCollection<std::string, std::string> > expand_vars(
+ new AssociativeCollection<std::string, std::string>::Concrete);
+
+ for (PortageRepositoryProfile::UseExpandIterator x(profile->begin_use_expand()),
+ x_end(profile->end_use_expand()) ; x != x_end ; ++x)
+ {
+ std::string lower_x;
+ std::transform(x->data().begin(), x->data().end(), std::back_inserter(lower_x), &::tolower);
+
+ expand_vars->insert(stringify(*x), "");
+
+ /* possible values from profile */
+ std::set<UseFlagName> possible_values;
+ WhitespaceTokeniser::get_instance()->tokenise(profile->environment_variable(stringify(*x)),
+ create_inserter<UseFlagName>(std::inserter(possible_values, possible_values.end())));
+
+ /* possible values from environment */
+ tr1::shared_ptr<const UseFlagNameCollection> possible_values_from_env(
+ env->known_use_expand_names(*x, e));
+ for (UseFlagNameCollection::Iterator i(possible_values_from_env->begin()),
+ i_end(possible_values_from_env->end()) ; i != i_end ; ++i)
+ possible_values.insert(UseFlagName(stringify(*i).substr(lower_x.length() + 1)));
+
+ for (std::set<UseFlagName>::const_iterator u(possible_values.begin()), u_end(possible_values.end()) ;
+ u != u_end ; ++u)
+ {
+ if (! env->query_use(UseFlagName(lower_x + "_" + stringify(*u)), e))
+ continue;
+
+ if (! e.eapi()->supported->ebuild_options->require_use_expand_in_iuse)
+ use.append(lower_x + "_" + stringify(*u) + " ");
+
+ std::string value;
+ AssociativeCollection<std::string, std::string>::Iterator i(expand_vars->find(stringify(*x)));
+ if (expand_vars->end() != i)
+ {
+ value = i->second;
+ if (! value.empty())
+ value.append(" ");
+ expand_vars->erase(i);
+ }
+ value.append(stringify(*u));
+ expand_vars->insert(stringify(*x), value);
+ }
+ }
+
+ return expand_vars;
+ }
+}
+
+void
+EbuildEntries::install(const tr1::shared_ptr<const PackageID> & id,
+ const InstallOptions & o, tr1::shared_ptr<const PortageRepositoryProfile> p) const
+{
+ using namespace tr1::placeholders;
+
+ Context context("When installing '" + stringify(*id) + "':");
+
+ bool fetch_restrict(false), no_mirror(false), userpriv_restrict;
+ {
+ DepSpecFlattener restricts(_imp->params.environment, id);
+ if (id->restrict_key())
+ id->restrict_key()->value()->accept(restricts);
+
+ fetch_restrict =
+ restricts.end() != std::find_if(restricts.begin(), restricts.end(),
+ tr1::bind(std::equal_to<std::string>(), tr1::bind(tr1::mem_fn(&StringDepSpec::text), _1), "fetch")) ||
+ restricts.end() != std::find_if(restricts.begin(), restricts.end(),
+ tr1::bind(std::equal_to<std::string>(), tr1::bind(tr1::mem_fn(&StringDepSpec::text), _1), "nofetch"));
+
+ userpriv_restrict =
+ restricts.end() != std::find_if(restricts.begin(), restricts.end(),
+ tr1::bind(std::equal_to<std::string>(), tr1::bind(tr1::mem_fn(&StringDepSpec::text), _1), "userpriv")) ||
+ restricts.end() != std::find_if(restricts.begin(), restricts.end(),
+ tr1::bind(std::equal_to<std::string>(), tr1::bind(tr1::mem_fn(&StringDepSpec::text), _1), "nouserpriv"));
+
+ no_mirror =
+ restricts.end() != std::find_if(restricts.begin(), restricts.end(),
+ tr1::bind(std::equal_to<std::string>(), tr1::bind(tr1::mem_fn(&StringDepSpec::text), _1), "mirror")) ||
+ restricts.end() != std::find_if(restricts.begin(), restricts.end(),
+ tr1::bind(std::equal_to<std::string>(), tr1::bind(tr1::mem_fn(&StringDepSpec::text), _1), "nomirror"));
+ }
+
+ std::string archives, all_archives, flat_src_uri;
+ {
+ std::set<std::string> already_in_archives;
+
+ /* make A and FLAT_SRC_URI */
+ DepSpecFlattener f(_imp->params.environment, id);
+ if (id->src_uri_key())
+ id->src_uri_key()->value()->accept(f);
+
+ for (DepSpecFlattener::Iterator i(f.begin()), i_end(f.end()) ; i != i_end ; ++i)
+ {
+ const tr1::shared_ptr<const URIDepSpec> spec(tr1::static_pointer_cast<const URIDepSpec>(*i));
+ if (! spec->renamed_url_suffix().empty())
+ throw PackageInstallActionError("Can't install '" + stringify(*id) + "' since it uses SRC_URI arrow components");
+
+ std::string::size_type pos(spec->original_url().rfind('/'));
+ if (std::string::npos == pos)
+ {
+ if (already_in_archives.end() == already_in_archives.find(spec->original_url()))
+ {
+ archives.append(spec->original_url());
+ already_in_archives.insert(spec->original_url());
+ }
+ }
+ else
+ {
+ if (already_in_archives.end() == already_in_archives.find(spec->original_url().substr(pos + 1)))
+ {
+ archives.append(spec->original_url().substr(pos + 1));
+ already_in_archives.insert(spec->original_url().substr(pos + 1));
+ }
+ }
+ archives.append(" ");
+
+ /* add * mirror entries */
+ tr1::shared_ptr<const MirrorsCollection> star_mirrors(_imp->params.environment->mirrors("*"));
+ for (MirrorsCollection::Iterator m(star_mirrors->begin()), m_end(star_mirrors->end()) ; m != m_end ; ++m)
+ flat_src_uri.append(*m + "/" + spec->original_url().substr(pos + 1) + " ");
+
+ if (0 == spec->original_url().compare(0, 9, "mirror://"))
+ {
+ std::string mirror(spec->original_url().substr(9));
+ std::string::size_type spos(mirror.find('/'));
+
+ if (std::string::npos == spos)
+ throw PackageInstallActionError("Can't install '" + stringify(*id) + "' since SRC_URI is broken");
+
+ tr1::shared_ptr<const MirrorsCollection> mirrors(_imp->params.environment->mirrors(mirror.substr(0, spos)));
+ if (! _imp->portage_repository->is_mirror(mirror.substr(0, spos)) &&
+ mirrors->empty())
+ throw PackageInstallActionError("Can't install '" + stringify(*id) +
+ "' since SRC_URI references unknown mirror:// '" +
+ mirror.substr(0, spos) + "'");
+
+ for (MirrorsCollection::Iterator m(mirrors->begin()), m_end(mirrors->end()) ; m != m_end ; ++m)
+ flat_src_uri.append(*m + "/" + mirror.substr(spos + 1) + " ");
+
+ for (RepositoryMirrorsInterface::MirrorsIterator
+ m(_imp->portage_repository->begin_mirrors(mirror.substr(0, spos))),
+ m_end(_imp->portage_repository->end_mirrors(mirror.substr(0, spos))) ;
+ m != m_end ; ++m)
+ flat_src_uri.append(m->second + "/" + mirror.substr(spos + 1) + " ");
+ }
+ else
+ flat_src_uri.append(spec->original_url());
+ flat_src_uri.append(" ");
+
+ /* add mirror://gentoo/ entries */
+ std::string master_mirror(strip_trailing_string(stringify(_imp->portage_repository->name()), "x-"));
+ if (! no_mirror && _imp->portage_repository->is_mirror(master_mirror))
+ {
+ tr1::shared_ptr<const MirrorsCollection> repo_mirrors(_imp->params.environment->mirrors(master_mirror));
+
+ for (MirrorsCollection::Iterator m(repo_mirrors->begin()), m_end(repo_mirrors->end()) ; m != m_end ; ++m)
+ flat_src_uri.append(*m + "/" + spec->original_url().substr(pos + 1) + " ");
+
+ for (RepositoryMirrorsInterface::MirrorsIterator
+ m(_imp->portage_repository->begin_mirrors(master_mirror)),
+ m_end(_imp->portage_repository->end_mirrors(master_mirror)) ;
+ m != m_end ; ++m)
+ flat_src_uri.append(m->second + "/" + spec->original_url().substr(pos + 1) + " ");
+ }
+ }
+
+ /* make AA */
+ if (id->eapi()->supported->ebuild_options->want_aa_var)
+ {
+ AAFinder g;
+ if (id->src_uri_key())
+ id->src_uri_key()->value()->accept(g);
+ std::set<std::string> already_in_all_archives;
+
+ for (AAFinder::Iterator gg(g.begin()), gg_end(g.end()) ; gg != gg_end ; ++gg)
+ {
+ std::string::size_type pos((*gg)->text().rfind('/'));
+ if (std::string::npos == pos)
+ {
+ if (already_in_all_archives.end() == already_in_all_archives.find((*gg)->text()))
+ {
+ all_archives.append((*gg)->text());
+ already_in_all_archives.insert((*gg)->text());
+ }
+ }
+ else
+ {
+ if (already_in_all_archives.end() == already_in_all_archives.find((*gg)->text().substr(pos + 1)))
+ {
+ all_archives.append((*gg)->text().substr(pos + 1));
+ already_in_all_archives.insert((*gg)->text().substr(pos + 1));
+ }
+ }
+ all_archives.append(" ");
+ }
+ }
+ else
+ all_archives = "AA-not-set-for-this-EAPI";
+ }
+
+ /* Strip trailing space. Some ebuilds rely upon this. From kde-meta.eclass:
+ * [[ -n ${A/${TARBALL}/} ]] && unpack ${A/${TARBALL}/}
+ * Rather annoying.
+ */
+ archives = strip_trailing(archives, " ");
+ all_archives = strip_trailing(all_archives, " ");
+
+ /* make use */
+ std::string use(make_use(_imp->params.environment, *id, p));
+
+ /* add expand to use (iuse isn't reliable for use_expand things), and make the expand
+ * environment variables */
+ tr1::shared_ptr<AssociativeCollection<std::string, std::string> > expand_vars(make_expand(
+ _imp->params.environment, *id, p, use));
+
+ tr1::shared_ptr<const FSEntryCollection> exlibsdirs(_imp->portage_repository->layout()->exlibsdirs(id->name()));
+
+ /* fetch */
+ {
+ bool fetch_userpriv_ok(_imp->environment->reduced_gid() != getgid());
+ if (fetch_userpriv_ok)
+ {
+ FSEntry f(_imp->params.distdir);
+ Context c("When checking permissions on '" + stringify(f) + "' for userpriv:");
+
+ if (f.exists())
+ {
+ if (f.group() != _imp->environment->reduced_gid())
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Directory '" +
+ stringify(f) + "' owned by group '" +
+ stringify(get_group_name(f.group())) + "', not '" +
+ stringify(get_group_name(_imp->environment->reduced_gid())) +
+ "', so cannot enable userpriv");
+ fetch_userpriv_ok = false;
+ }
+ else if (! f.has_permission(fs_ug_group, fs_perm_write))
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Directory '" +
+ stringify(f) + "' does not group write permission," +
+ "cannot enable userpriv");
+ fetch_userpriv_ok = false;
+ }
+ }
+ }
+
+ EAPIPhases phases(fetch_restrict ?
+ id->eapi()->supported->ebuild_phases->ebuild_nofetch :
+ id->eapi()->supported->ebuild_phases->ebuild_fetch);
+
+ for (EAPIPhases::Iterator phase(phases.begin_phases()), phase_end(phases.end_phases()) ;
+ phase != phase_end ; ++phase)
+ {
+ EbuildCommandParams command_params(EbuildCommandParams::create()
+ .environment(_imp->params.environment)
+ .package_id(id)
+ .ebuild_dir(_imp->portage_repository->layout()->package_directory(id->name()))
+ .ebuild_file(_imp->portage_repository->layout()->package_file(*id))
+ .files_dir(_imp->portage_repository->layout()->package_directory(id->name()) / "files")
+ .eclassdirs(_imp->params.eclassdirs)
+ .exlibsdirs(exlibsdirs)
+ .portdir(_imp->params.master_repository ? _imp->params.master_repository->params().location :
+ _imp->params.location)
+ .distdir(_imp->params.distdir)
+ .commands(join(phase->begin_commands(), phase->end_commands(), " "))
+ .sandbox(phase->option("sandbox"))
+ .userpriv(phase->option("userpriv") && fetch_userpriv_ok)
+ .buildroot(_imp->params.buildroot));
+
+ EbuildFetchCommand fetch_cmd(command_params,
+ EbuildFetchCommandParams::create()
+ .a(archives)
+ .aa(all_archives)
+ .use(use)
+ .use_expand(join(p->begin_use_expand(), p->end_use_expand(), " "))
+ .expand_vars(expand_vars)
+ .flat_src_uri(flat_src_uri)
+ .root(o.destination->installed_interface ? stringify(o.destination->installed_interface->root()) : "/")
+ .profiles(_imp->params.profiles)
+ .safe_resume(o.safe_resume));
+
+ fetch_cmd();
+ }
+
+ if (o.fetch_only)
+ return;
+ }
+
+ bool userpriv_ok((! userpriv_restrict) && (_imp->environment->reduced_gid() != getgid()));
+ if (userpriv_ok)
+ {
+ FSEntry f(_imp->params.buildroot);
+ Context c("When checking permissions on '" + stringify(f) + "' for userpriv:");
+
+ if (f.exists())
+ {
+ if (f.group() != _imp->environment->reduced_gid())
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Directory '" +
+ stringify(f) + "' owned by group '" +
+ stringify(get_group_name(f.group())) + "', not '" +
+ stringify(get_group_name(_imp->environment->reduced_gid())) + "', cannot enable userpriv");
+ userpriv_ok = false;
+ }
+ else if (! f.has_permission(fs_ug_group, fs_perm_write))
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Directory '" +
+ stringify(f) + "' does not group write permission," +
+ "cannot enable userpriv");
+ userpriv_ok = false;
+ }
+ }
+ }
+
+ EAPIPhases phases(id->eapi()->supported->ebuild_phases->ebuild_install);
+ for (EAPIPhases::Iterator phase(phases.begin_phases()), phase_end(phases.end_phases()) ;
+ phase != phase_end ; ++phase)
+ {
+ if (phase->option("merge"))
+ {
+ if (! o.destination->destination_interface)
+ throw PackageInstallActionError("Can't install '" + stringify(*id)
+ + "' to destination '" + stringify(o.destination->name())
+ + "' because destination does not provide destination_interface");
+
+ o.destination->destination_interface->merge(
+ MergeOptions::create()
+ .package_id(id)
+ .image_dir(_imp->params.buildroot / stringify(id->name().category) / (stringify(id->name().package) + "-"
+ + stringify(id->version())) / "image")
+ .environment_file(_imp->params.buildroot / stringify(id->name().category) / (stringify(id->name().package) + "-"
+ + stringify(id->version())) / "temp" / "loadsaveenv")
+ );
+ }
+ else if ((! phase->option("prepost")) ||
+ (o.destination->destination_interface && o.destination->destination_interface->want_pre_post_phases()))
+ {
+ EbuildCommandParams command_params(EbuildCommandParams::create()
+ .environment(_imp->params.environment)
+ .package_id(id)
+ .ebuild_dir(_imp->portage_repository->layout()->package_directory(id->name()))
+ .ebuild_file(_imp->portage_repository->layout()->package_file(*id))
+ .files_dir(_imp->portage_repository->layout()->package_directory(id->name()) / "files")
+ .eclassdirs(_imp->params.eclassdirs)
+ .exlibsdirs(exlibsdirs)
+ .portdir(_imp->params.master_repository ? _imp->params.master_repository->params().location :
+ _imp->params.location)
+ .distdir(_imp->params.distdir)
+ .commands(join(phase->begin_commands(), phase->end_commands(), " "))
+ .sandbox(phase->option("sandbox"))
+ .userpriv(phase->option("userpriv") && userpriv_ok)
+ .buildroot(_imp->params.buildroot));
+
+ EbuildInstallCommandParams install_params(
+ EbuildInstallCommandParams::create()
+ .use(use)
+ .a(archives)
+ .aa(all_archives)
+ .use_expand(join(p->begin_use_expand(), p->end_use_expand(), " "))
+ .expand_vars(expand_vars)
+ .root(o.destination->installed_interface ? stringify(o.destination->installed_interface->root()) : "/")
+ .profiles(_imp->params.profiles)
+ .disable_cfgpro(o.no_config_protect)
+ .debug_build(o.debug_build)
+ .config_protect(_imp->portage_repository->profile_variable("CONFIG_PROTECT"))
+ .config_protect_mask(_imp->portage_repository->profile_variable("CONFIG_PROTECT_MASK"))
+ .loadsaveenv_dir(_imp->params.buildroot / stringify(id->name().category) / (
+ stringify(id->name().package) + "-" + stringify(id->version())) / "temp")
+ .slot(SlotName(id->slot())));
+
+ EbuildInstallCommand cmd(command_params, install_params);
+ cmd();
+ }
+ }
+}
+
+std::string
+EbuildEntries::get_environment_variable(const tr1::shared_ptr<const PackageID> & id,
+ const std::string & var, tr1::shared_ptr<const PortageRepositoryProfile>) const
+{
+ EAPIPhases phases(id->eapi()->supported->ebuild_phases->ebuild_variable);
+
+ int c(std::distance(phases.begin_phases(), phases.end_phases()));
+ if (1 != c)
+ throw EAPIConfigurationError("EAPI '" + id->eapi()->name + "' defines "
+ + (c == 0 ? "no" : stringify(c)) + " ebuild variable phases but expected exactly one");
+
+ tr1::shared_ptr<const FSEntryCollection> exlibsdirs(_imp->portage_repository->layout()->exlibsdirs(id->name()));
+
+ EbuildVariableCommand cmd(EbuildCommandParams::create()
+ .environment(_imp->params.environment)
+ .package_id(id)
+ .ebuild_dir(_imp->portage_repository->layout()->package_directory(id->name()))
+ .ebuild_file(_imp->portage_repository->layout()->package_file(*id))
+ .files_dir(_imp->portage_repository->layout()->package_directory(id->name()) / "files")
+ .eclassdirs(_imp->params.eclassdirs)
+ .exlibsdirs(exlibsdirs)
+ .portdir(_imp->params.master_repository ? _imp->params.master_repository->params().location :
+ _imp->params.location)
+ .distdir(_imp->params.distdir)
+ .sandbox(phases.begin_phases()->option("sandbox"))
+ .userpriv(phases.begin_phases()->option("userpriv"))
+ .commands(join(phases.begin_phases()->begin_commands(), phases.begin_phases()->end_commands(), " "))
+ .buildroot(_imp->params.buildroot),
+
+ var);
+
+ if (! cmd())
+ throw EnvironmentVariableActionError("Couldn't get environment variable '" +
+ stringify(var) + "' for package '" + stringify(*id) + "'");
+
+ return cmd.result();
+}
+
+tr1::shared_ptr<PortageRepositoryEntries>
+EbuildEntries::make_ebuild_entries(
+ const Environment * const e, PortageRepository * const r, const PortageRepositoryParams & p)
+{
+ return tr1::shared_ptr<PortageRepositoryEntries>(new EbuildEntries(e, r, p));
+}
+
+void
+EbuildEntries::merge(const MergeOptions &)
+{
+ throw InternalError(PALUDIS_HERE, "Cannot merge to PortageRepository with ebuild entries");
+}
+
+bool
+EbuildEntries::is_package_file(const QualifiedPackageName & n, const FSEntry & e) const
+{
+ if (_imp->portage_repository->layout()->eapi_ebuild_suffix())
+ return (0 == e.basename().compare(0, stringify(n.package).length() + 1, stringify(n.package) + "-")) &&
+ std::string::npos != e.basename().rfind('.') &&
+ e.basename().at(e.basename().length() - 1) != '~' &&
+ e.is_regular_file_or_symlink_to_regular_file();
+ else
+ return is_file_with_prefix_extension(e, stringify(n.package) + "-", ".ebuild", IsFileWithOptions());
+}
+
+VersionSpec
+EbuildEntries::extract_package_file_version(const QualifiedPackageName & n, const FSEntry & e) const
+{
+ Context context("When extracting version from '" + stringify(e) + "':");
+ if (_imp->portage_repository->layout()->eapi_ebuild_suffix())
+ {
+ std::string::size_type p(e.basename().rfind('.'));
+ return VersionSpec(strip_leading_string(e.basename().substr(0, p), stringify(n.package) + "-"));
+ }
+ else
+ return VersionSpec(strip_leading_string(strip_trailing_string(e.basename(), ".ebuild"), stringify(n.package) + "-"));
+}
+
+bool
+EbuildEntries::pretend(const tr1::shared_ptr<const PackageID> & id,
+ tr1::shared_ptr<const PortageRepositoryProfile> p) const
+{
+ using namespace tr1::placeholders;
+
+ Context context("When running pretend for '" + stringify(*id) + "':");
+
+ if (! id->eapi()->supported)
+ return true;
+ if (id->eapi()->supported->ebuild_phases->ebuild_pretend.empty())
+ return true;
+
+ std::string use(make_use(_imp->params.environment, *id, p));
+ tr1::shared_ptr<AssociativeCollection<std::string, std::string> > expand_vars(make_expand(
+ _imp->params.environment, *id, p, use));
+
+ tr1::shared_ptr<const FSEntryCollection> exlibsdirs(_imp->portage_repository->layout()->exlibsdirs(id->name()));
+
+ EAPIPhases phases(id->eapi()->supported->ebuild_phases->ebuild_pretend);
+ for (EAPIPhases::Iterator phase(phases.begin_phases()), phase_end(phases.end_phases()) ;
+ phase != phase_end ; ++phase)
+ {
+ EbuildCommandParams command_params(EbuildCommandParams::create()
+ .environment(_imp->params.environment)
+ .package_id(id)
+ .ebuild_dir(_imp->portage_repository->layout()->package_directory(id->name()))
+ .ebuild_file(_imp->portage_repository->layout()->package_file(*id))
+ .files_dir(_imp->portage_repository->layout()->package_directory(id->name()) / "files")
+ .eclassdirs(_imp->params.eclassdirs)
+ .exlibsdirs(exlibsdirs)
+ .portdir(_imp->params.master_repository ? _imp->params.master_repository->params().location :
+ _imp->params.location)
+ .distdir(_imp->params.distdir)
+ .userpriv(phase->option("userpriv"))
+ .sandbox(phase->option("sandbox"))
+ .commands(join(phase->begin_commands(), phase->end_commands(), " "))
+ .buildroot(_imp->params.buildroot));
+
+ EbuildPretendCommand pretend_cmd(command_params,
+ EbuildPretendCommandParams::create()
+ .use(use)
+ .use_expand(join(p->begin_use_expand(), p->end_use_expand(), " "))
+ .expand_vars(expand_vars)
+ .root(stringify(_imp->params.environment->root()))
+ .profiles(_imp->params.profiles));
+
+ if (! pretend_cmd())
+ return false;
+ }
+
+ return true;
+}
+
diff --git a/paludis/repositories/e/ebuild_entries.hh b/paludis/repositories/e/ebuild_entries.hh
new file mode 100644
index 000000000..fc4a5f007
--- /dev/null
+++ b/paludis/repositories/e/ebuild_entries.hh
@@ -0,0 +1,88 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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_PORTAGE_PORTAGE_REPOSITORY_EBUILD_METADATA_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_PORTAGE_REPOSITORY_EBUILD_METADATA_HH 1
+
+#include <paludis/repositories/e/portage_repository_entries.hh>
+#include <paludis/repositories/e/portage_repository_params.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+/** \file
+ * Declaration for the EbuildEntries class.
+ *
+ * \ingroup grpportagerepository
+ */
+
+namespace paludis
+{
+ class FSEntry;
+ class PortageRepository;
+
+ /**
+ * PortageRepositoryEntries handler for ebuilds.
+ *
+ * \ingroup grpportagerepository
+ */
+ class PALUDIS_VISIBLE EbuildEntries :
+ public PortageRepositoryEntries,
+ private PrivateImplementationPattern<EbuildEntries>
+ {
+ public:
+ /**
+ * Create an EbuildEntries instance.
+ */
+ static tr1::shared_ptr<PortageRepositoryEntries> make_ebuild_entries(const Environment * const,
+ PortageRepository * const, const PortageRepositoryParams &);
+
+ ///\name Basic operations
+ ///\{
+
+ EbuildEntries(const Environment * const,
+ PortageRepository * const portage_repository,
+ const PortageRepositoryParams &);
+
+ virtual ~EbuildEntries();
+
+ ///\}
+
+ virtual void merge(const MergeOptions &) PALUDIS_ATTRIBUTE((noreturn));
+
+ virtual bool is_package_file(const QualifiedPackageName &, const FSEntry &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual VersionSpec extract_package_file_version(const QualifiedPackageName &, const FSEntry &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual const tr1::shared_ptr<const PackageID> make_id(const QualifiedPackageName &, const VersionSpec &,
+ const FSEntry &, const std::string &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string get_environment_variable(const tr1::shared_ptr<const PackageID> &, const std::string & var,
+ tr1::shared_ptr<const PortageRepositoryProfile>) const;
+
+ virtual void install(const tr1::shared_ptr<const PackageID> &, const InstallOptions &,
+ tr1::shared_ptr<const PortageRepositoryProfile>) const;
+
+ virtual bool pretend(const tr1::shared_ptr<const PackageID> &,
+ tr1::shared_ptr<const PortageRepositoryProfile>) const;
+ };
+}
+
+#endif
diff --git a/paludis/repositories/e/ebuild_flat_metadata_cache.cc b/paludis/repositories/e/ebuild_flat_metadata_cache.cc
new file mode 100644
index 000000000..37315f1f4
--- /dev/null
+++ b/paludis/repositories/e/ebuild_flat_metadata_cache.cc
@@ -0,0 +1,207 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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 "ebuild_flat_metadata_cache.hh"
+#include <paludis/util/log.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/dep_spec_pretty_printer.hh>
+#include <paludis/eapi.hh>
+#include <fstream>
+#include <set>
+#include <list>
+#include <paludis/util/tr1_functional.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <functional>
+#include <algorithm>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+EbuildFlatMetadataCache::EbuildFlatMetadataCache(const FSEntry & f,
+ const FSEntry & e, time_t t, tr1::shared_ptr<const EclassMtimes> m, bool s) :
+ _filename(f),
+ _ebuild(e),
+ _master_mtime(t),
+ _eclass_mtimes(m),
+ _silent(s)
+{
+}
+
+bool
+EbuildFlatMetadataCache::load(const tr1::shared_ptr<const EbuildID> & id)
+{
+ using namespace tr1::placeholders;
+
+ Context context("When loading version metadata from '" + stringify(_filename) + "':");
+
+ std::ifstream cache(stringify(_filename).c_str());
+ std::string line;
+
+ if (cache)
+ {
+ std::getline(cache, line); id->load_build_depend("DEPEND", "Build depend", line);
+ std::getline(cache, line); id->load_run_depend("RDEPEND", "Run depend", line);
+ std::getline(cache, line); id->set_slot(SlotName(line));
+ std::getline(cache, line); id->load_src_uri("SRC_URI", "Source URI", line);
+ std::getline(cache, line); id->load_restrict("RESTRICT", "Restrictions", line);
+ std::getline(cache, line); id->load_homepage("HOMEPAGE", "Homepage", line);
+ std::getline(cache, line); id->load_license("LICENSE", "License", line);
+ std::getline(cache, line); id->load_short_description("DESCRIPTION", "Description", line);
+ std::getline(cache, line); id->load_keywords("KEYWORDS", "Keywords", line);
+ std::getline(cache, line); id->load_inherited("INHERITED", "Inherited", line);
+ std::getline(cache, line); id->load_iuse("IUSE", "Used USE flags", line);
+ std::getline(cache, line);
+ std::getline(cache, line); id->load_post_depend("PDEPEND", "Post depend", line);
+ std::getline(cache, line); id->load_provide("PROVIDE", "Provides", line);
+ std::getline(cache, line); id->set_eapi(line);
+
+ // check mtimes
+ time_t cache_time(std::max(_master_mtime, _filename.mtime()));
+ bool ok = _ebuild.mtime() <= cache_time &&
+ id->inherited_key()->value()->end() == std::find_if(id->inherited_key()->value()->begin(), id->inherited_key()->value()->end(),
+ tr1::bind(std::greater<time_t>(), tr1::bind(
+ tr1::mem_fn(&EclassMtimes::mtime), _eclass_mtimes.get(), _1), cache_time));
+
+ if (! ok)
+ Log::get_instance()->message(ll_warning, lc_no_context) << "Stale cache file at '"
+ << _filename << "'";
+ return ok;
+
+ return true;
+ }
+ else
+ {
+ Log::get_instance()->message(_silent ? ll_debug : ll_warning, lc_no_context,
+ "Couldn't use the cache file at '" + stringify(_filename) + "'");
+ return false;
+ }
+}
+
+namespace
+{
+ template <typename T_>
+ std::string normalise(const T_ & s)
+ {
+ std::list<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(stringify(s), std::back_inserter(tokens));
+ return join(tokens.begin(), tokens.end(), " ");
+ }
+
+ template <typename T_>
+ std::string flatten(const T_ & d)
+ {
+ DepSpecPrettyPrinter p(0, false);
+ d->accept(p);
+ return stringify(p);
+ }
+}
+
+void
+EbuildFlatMetadataCache::save(const tr1::shared_ptr<const EbuildID> & id)
+{
+ Context context("When saving version metadata to '" + stringify(_filename) + "':");
+
+ try
+ {
+ _filename.dirname().dirname().mkdir();
+ _filename.dirname().mkdir();
+ }
+ catch (const FSError &)
+ {
+ // let the 'if (cache)' handle the error
+ }
+ std::ofstream cache(stringify(_filename).c_str());
+
+ if (cache)
+ {
+ if (id->build_dependencies_key())
+ cache << flatten(id->build_dependencies_key()->value()) << std::endl;
+ else
+ cache << std::endl;
+
+ if (id->run_dependencies_key())
+ cache << flatten(id->run_dependencies_key()->value()) << std::endl;
+ else
+ cache << std::endl;
+
+ cache << normalise(id->slot()) << std::endl;
+
+ if (id->src_uri_key())
+ cache << flatten(id->src_uri_key()->value()) << std::endl;
+ else
+ cache << std::endl;
+
+ if (id->restrict_key())
+ cache << flatten(id->restrict_key()->value()) << std::endl;
+ else
+ cache << std::endl;
+
+ if (id->homepage_key())
+ cache << flatten(id->homepage_key()->value()) << std::endl;
+ else
+ cache << std::endl;
+
+ if (id->license_key())
+ cache << flatten(id->license_key()->value()) << std::endl;
+ else
+ cache << std::endl;
+
+ if (id->short_description_key())
+ cache << normalise(id->short_description_key()->value()) << std::endl;
+ else
+ cache << std::endl;
+
+ if (id->keywords_key())
+ cache << join(id->keywords_key()->value()->begin(), id->keywords_key()->value()->end(), " ") << std::endl;
+ else
+ cache << std::endl;
+
+ if (id->inherited_key())
+ cache << join(id->inherited_key()->value()->begin(), id->inherited_key()->value()->end(), " ") << std::endl;
+ else
+ cache << std::endl;
+
+ if (id->iuse_key())
+ cache << join(id->iuse_key()->value()->begin(), id->iuse_key()->value()->end(), " ") << std::endl;
+ else
+ cache << std::endl;
+
+ cache << std::endl;
+
+ if (id->post_dependencies_key())
+ cache << flatten(id->post_dependencies_key()->value()) << std::endl;
+ else
+ cache << std::endl;
+
+ if (id->provide_key())
+ cache << flatten(id->provide_key()->value()) << std::endl;
+ else
+ cache << std::endl;
+
+ cache << normalise(id->eapi()->name) << std::endl;
+ }
+ else
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context) << "Couldn't write cache file to '"
+ << _filename << "'";
+ }
+}
+
diff --git a/paludis/repositories/e/ebuild_flat_metadata_cache.hh b/paludis/repositories/e/ebuild_flat_metadata_cache.hh
new file mode 100644
index 000000000..2d2726548
--- /dev/null
+++ b/paludis/repositories/e/ebuild_flat_metadata_cache.hh
@@ -0,0 +1,70 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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_PORTAGE_EBUILD_FLAT_METADATA_CACHE_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_EBUILD_FLAT_METADATA_CACHE_HH 1
+
+#include <paludis/repositories/e/ebuild.hh>
+#include <paludis/repositories/e/ebuild_id.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/repositories/e/eclass_mtimes.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ /**
+ * Implements flat file metadata cache handling for a PortageRepository
+ * using EbuildEntries.
+ *
+ * \see EbuildEntries
+ * \see PortageRepository
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class EbuildFlatMetadataCache
+ {
+ private:
+ const FSEntry & _filename;
+ const FSEntry & _ebuild;
+ time_t _master_mtime;
+ tr1::shared_ptr<const EclassMtimes> _eclass_mtimes;
+ bool _silent;
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ EbuildFlatMetadataCache(const FSEntry & filename, const FSEntry & ebuild,
+ time_t master_mtime, tr1::shared_ptr<const EclassMtimes> eclass_mtimes, bool silent);
+
+ ///\}
+
+ ///\name Cache operations
+ ///\{
+
+ bool load(const tr1::shared_ptr<const EbuildID> &);
+ void save(const tr1::shared_ptr<const EbuildID> &);
+
+ ///\}
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/e/ebuild_id.cc b/paludis/repositories/e/ebuild_id.cc
new file mode 100644
index 000000000..1a82e90cc
--- /dev/null
+++ b/paludis/repositories/e/ebuild_id.cc
@@ -0,0 +1,551 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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/e/ebuild_id.hh>
+#include <paludis/repositories/e/ebuild_flat_metadata_cache.hh>
+#include <paludis/repositories/e/portage_repository.hh>
+#include <paludis/repositories/e/portage_repository_params.hh>
+#include <paludis/repositories/e/eapi_phase.hh>
+#include <paludis/repositories/e/e_key.hh>
+
+#include <paludis/name.hh>
+#include <paludis/version_spec.hh>
+#include <paludis/repository.hh>
+#include <paludis/distribution.hh>
+#include <paludis/eapi.hh>
+#include <paludis/environment.hh>
+
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+
+#include <iterator>
+#include <fstream>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+namespace
+{
+ std::string file_contents(const FSEntry & f)
+ {
+ Context c("When reading '" + stringify(f) + "':");
+ std::ifstream i(stringify(f).c_str());
+ if (! i)
+ throw ConfigurationError("Cannot open '" + stringify(f) + "' for read");
+
+ return std::string((std::istreambuf_iterator<char>(i)), std::istreambuf_iterator<char>());
+ }
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EbuildID>
+ {
+ const QualifiedPackageName name;
+ const VersionSpec version;
+ const Environment * const environment;
+ const tr1::shared_ptr<const PortageRepository> repository;
+ const FSEntry ebuild;
+ tr1::shared_ptr<const SlotName> slot;
+ mutable tr1::shared_ptr<const EAPI> eapi;
+ const std::string guessed_eapi;
+ const time_t master_mtime;
+ const tr1::shared_ptr<const EclassMtimes> eclass_mtimes;
+ mutable bool has_keys;
+
+ mutable tr1::shared_ptr<const EStringKey> short_description;
+ mutable tr1::shared_ptr<const EDependenciesKey> build_dependencies;
+ mutable tr1::shared_ptr<const EDependenciesKey> run_dependencies;
+ mutable tr1::shared_ptr<const EDependenciesKey> post_dependencies;
+ mutable tr1::shared_ptr<const EProvideKey> provide;
+ mutable tr1::shared_ptr<const ERestrictKey> restrictions;
+ mutable tr1::shared_ptr<const EURIKey> src_uri;
+ mutable tr1::shared_ptr<const EURIKey> homepage;
+ mutable tr1::shared_ptr<const ELicenseKey> license;
+ mutable tr1::shared_ptr<const EKeywordsKey> keywords;
+ mutable tr1::shared_ptr<const EIUseKey> iuse;
+ mutable tr1::shared_ptr<const EInheritedKey> inherited;
+
+ Implementation(const QualifiedPackageName & q, const VersionSpec & v,
+ const Environment * const e,
+ const tr1::shared_ptr<const PortageRepository> r, const FSEntry & f, const std::string & g,
+ const time_t t, const tr1::shared_ptr<const EclassMtimes> & m) :
+ name(q),
+ version(v),
+ environment(e),
+ repository(r),
+ ebuild(f),
+ guessed_eapi(g),
+ master_mtime(t),
+ eclass_mtimes(m),
+ has_keys(false)
+ {
+ }
+ };
+}
+
+EbuildID::EbuildID(const QualifiedPackageName & q, const VersionSpec & v,
+ const Environment * const e,
+ const tr1::shared_ptr<const PortageRepository> & r,
+ const FSEntry & f,
+ const std::string & g,
+ const time_t t,
+ const tr1::shared_ptr<const EclassMtimes> & m) :
+ PrivateImplementationPattern<EbuildID>(new Implementation<EbuildID>(q, v, e, r, f, g, t, m)),
+ _imp(PrivateImplementationPattern<EbuildID>::_imp.get())
+{
+}
+
+EbuildID::~EbuildID()
+{
+}
+
+void
+EbuildID::need_keys_added() const
+{
+ if (_imp->has_keys)
+ return;
+
+ _imp->has_keys = true;
+
+ Context context("When generating metadata for ID '" + canonical_form(idcf_full) + "':");
+
+ FSEntry cache_file(_imp->repository->params().cache);
+ cache_file /= stringify(name().category);
+ cache_file /= stringify(name().package) + "-" + stringify(version());
+
+ FSEntry write_cache_file(_imp->repository->params().write_cache);
+ write_cache_file /= stringify(repository()->name());
+ write_cache_file /= stringify(name().category);
+ write_cache_file /= stringify(name().package) + "-" + stringify(version());
+
+ bool ok(false);
+ if (_imp->repository->params().cache.basename() != "empty")
+ {
+ EbuildFlatMetadataCache metadata_cache(cache_file, _imp->ebuild, _imp->master_mtime, _imp->eclass_mtimes, false);
+ if (metadata_cache.load(shared_from_this()))
+ ok = true;
+ }
+
+ if ((! ok) && _imp->repository->params().write_cache.basename() != "empty")
+ {
+ EbuildFlatMetadataCache write_metadata_cache(write_cache_file, _imp->ebuild, _imp->master_mtime, _imp->eclass_mtimes, true);
+ if (write_metadata_cache.load(shared_from_this()))
+ ok = true;
+ else if (write_cache_file.exists())
+ {
+ try
+ {
+ write_cache_file.unlink();
+ }
+ catch (const FSError &)
+ {
+ // the attempt to write a fresh file will produce a
+ // warning, no need to be too noisy
+ }
+ }
+ }
+
+ if (! ok)
+ {
+ if (_imp->repository->params().cache.basename() != "empty")
+ Log::get_instance()->message(ll_qa, lc_no_context) << "No usable cache entry for '" + canonical_form(idcf_full);
+
+ std::string eapi_str(_imp->guessed_eapi);
+ if (eapi_str.empty())
+ eapi_str = _imp->repository->params().eapi_when_unknown;
+ _imp->eapi = EAPIData::get_instance()->eapi_from_string(eapi_str);
+
+ if (_imp->eapi->supported)
+ {
+ Log::get_instance()->message(ll_debug, lc_context) << "Generating metadata command for '"
+ << canonical_form(idcf_full) << "' using EAPI '" << _imp->eapi->name << "'";
+
+ EAPIPhases phases(_imp->eapi->supported->ebuild_phases->ebuild_metadata);
+
+ int count(std::distance(phases.begin_phases(), phases.end_phases()));
+ if (1 != count)
+ throw EAPIConfigurationError("EAPI '" + _imp->eapi->name + "' defines "
+ + (count == 0 ? "no" : stringify(count)) + " ebuild variable phases but expected exactly one");
+
+ EbuildMetadataCommand cmd(EbuildCommandParams::create()
+ .environment(_imp->environment)
+ .package_id(shared_from_this())
+ .ebuild_dir(_imp->repository->layout()->package_directory(name()))
+ .ebuild_file(_imp->ebuild)
+ .files_dir(_imp->repository->layout()->package_directory(name()) / "files")
+ .eclassdirs(_imp->repository->params().eclassdirs)
+ .exlibsdirs(_imp->repository->layout()->exlibsdirs(name()))
+ .portdir(_imp->repository->params().master_repository ? _imp->repository->params().master_repository->params().location :
+ _imp->repository->params().location)
+ .distdir(_imp->repository->params().distdir)
+ .buildroot(_imp->repository->params().buildroot)
+ .commands(join(phases.begin_phases()->begin_commands(), phases.begin_phases()->end_commands(), " "))
+ .sandbox(phases.begin_phases()->option("sandbox"))
+ .userpriv(phases.begin_phases()->option("userpriv")));
+
+ if (! cmd())
+ Log::get_instance()->message(ll_warning, lc_no_context) << "No usable metadata for '" +
+ stringify(canonical_form(idcf_full)) << "'";
+
+ cmd.load(shared_from_this());
+
+ Log::get_instance()->message(ll_debug, lc_context) << "Generated metadata for '"
+ << canonical_form(idcf_full) << "' has EAPI '" << _imp->eapi->name << "'";
+
+ if (_imp->repository->params().write_cache.basename() != "empty" && _imp->eapi->supported)
+ {
+ EbuildFlatMetadataCache metadata_cache(write_cache_file, _imp->ebuild, _imp->master_mtime,
+ _imp->eclass_mtimes, false);
+ metadata_cache.save(shared_from_this());
+ }
+ }
+ else
+ {
+ Log::get_instance()->message(ll_debug, lc_context) << "Can't run metadata command for '"
+ << canonical_form(idcf_full) << "' because EAPI '" << _imp->eapi->name << "' is unknown";
+ }
+ }
+}
+
+const std::string
+EbuildID::canonical_form(const PackageIDCanonicalForm f) const
+{
+ switch (f)
+ {
+ case idcf_full:
+ if (_imp->slot)
+ return stringify(name()) + "-" + stringify(version()) + ":" + stringify(*_imp->slot) +
+ "::" + stringify(repository()->name());
+
+ return stringify(name()) + "-" + stringify(version()) + "::" + stringify(repository()->name());
+
+ case idcf_no_version:
+ if (_imp->slot)
+ return stringify(name()) + ":" + stringify(*_imp->slot) +
+ "::" + stringify(repository()->name());
+
+ return stringify(name()) + "::" + stringify(repository()->name());
+
+ case idcf_version:
+ return stringify(version());
+
+ case last_idcf:
+ break;
+ }
+
+ throw InternalError(PALUDIS_HERE, "Bad PackageIDCanonicalForm");
+}
+
+const QualifiedPackageName
+EbuildID::name() const
+{
+ return _imp->name;
+}
+
+const VersionSpec
+EbuildID::version() const
+{
+ return _imp->version;
+}
+
+const SlotName
+EbuildID::slot() const
+{
+ if (_imp->slot)
+ return *_imp->slot;
+
+ need_keys_added();
+
+ return *_imp->slot;
+}
+
+const tr1::shared_ptr<const Repository>
+EbuildID::repository() const
+{
+ return _imp->repository;
+}
+
+const tr1::shared_ptr<const EAPI>
+EbuildID::eapi() const
+{
+ if (_imp->eapi)
+ return _imp->eapi;
+
+ need_keys_added();
+
+ return _imp->eapi;
+}
+
+const tr1::shared_ptr<const MetadataPackageIDKey>
+EbuildID::virtual_for_key() const
+{
+ return tr1::shared_ptr<const MetadataPackageIDKey>();
+}
+
+const tr1::shared_ptr<const MetadataCollectionKey<KeywordNameCollection> >
+EbuildID::keywords_key() const
+{
+ need_keys_added();
+ return _imp->keywords;
+}
+
+const tr1::shared_ptr<const MetadataCollectionKey<UseFlagNameCollection> >
+EbuildID::use_key() const
+{
+ return tr1::shared_ptr<const MetadataCollectionKey<UseFlagNameCollection> >();
+}
+
+const tr1::shared_ptr<const MetadataCollectionKey<IUseFlagCollection> >
+EbuildID::iuse_key() const
+{
+ need_keys_added();
+ return _imp->iuse;
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<LicenseSpecTree> >
+EbuildID::license_key() const
+{
+ need_keys_added();
+ return _imp->license;
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<ProvideSpecTree> >
+EbuildID::provide_key() const
+{
+ need_keys_added();
+ return _imp->provide;
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+EbuildID::build_dependencies_key() const
+{
+ need_keys_added();
+ return _imp->build_dependencies;
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+EbuildID::run_dependencies_key() const
+{
+ need_keys_added();
+ return _imp->run_dependencies;
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+EbuildID::post_dependencies_key() const
+{
+ need_keys_added();
+ return _imp->post_dependencies;
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+EbuildID::suggested_dependencies_key() const
+{
+ return tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >();
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<RestrictSpecTree> >
+EbuildID::restrict_key() const
+{
+ need_keys_added();
+ return _imp->restrictions;
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<URISpecTree> >
+EbuildID::src_uri_key() const
+{
+ need_keys_added();
+ return _imp->src_uri;
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<URISpecTree> >
+EbuildID::homepage_key() const
+{
+ need_keys_added();
+ return _imp->homepage;
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<URISpecTree> >
+EbuildID::bin_uri_key() const
+{
+ return tr1::shared_ptr<const MetadataSpecTreeKey<URISpecTree> >();
+}
+
+const tr1::shared_ptr<const MetadataStringKey>
+EbuildID::short_description_key() const
+{
+ need_keys_added();
+ return _imp->short_description;
+}
+
+const tr1::shared_ptr<const MetadataStringKey>
+EbuildID::long_description_key() const
+{
+ return tr1::shared_ptr<const MetadataStringKey>();
+}
+
+const tr1::shared_ptr<const MetadataContentsKey>
+EbuildID::contents_key() const
+{
+ return tr1::shared_ptr<const MetadataContentsKey>();
+}
+
+const tr1::shared_ptr<const MetadataTimeKey>
+EbuildID::installed_time_key() const
+{
+ return tr1::shared_ptr<const MetadataTimeKey>();
+}
+
+const tr1::shared_ptr<const MetadataStringKey>
+EbuildID::source_origin_key() const
+{
+ return tr1::shared_ptr<const MetadataStringKey>();
+}
+
+const tr1::shared_ptr<const MetadataStringKey>
+EbuildID::binary_origin_key() const
+{
+ return tr1::shared_ptr<const MetadataStringKey>();
+}
+
+const tr1::shared_ptr<const MetadataCollectionKey<InheritedCollection> >
+EbuildID::inherited_key() const
+{
+ return _imp->inherited;
+}
+
+bool
+EbuildID::arbitrary_less_than_comparison(const PackageID &) const
+{
+ return false;
+}
+
+std::size_t
+EbuildID::extra_hash_value() const
+{
+ return 0;
+}
+
+void
+EbuildID::set_eapi(const std::string & s) const
+{
+ _imp->eapi = EAPIData::get_instance()->eapi_from_string(s);
+}
+
+void
+EbuildID::set_slot(const SlotName & s) const
+{
+ _imp->slot.reset(new SlotName(s));
+}
+
+tr1::shared_ptr<const PortageRepository>
+EbuildID::portage_repository() const
+{
+ return _imp->repository;
+}
+
+void
+EbuildID::load_short_description(const std::string & r, const std::string & h, const std::string & v) const
+{
+ _imp->short_description.reset(new EStringKey(shared_from_this(), r, h, v, mkt_significant));
+ add_key(_imp->short_description);
+}
+
+void
+EbuildID::load_build_depend(const std::string & r, const std::string & h, const std::string & v) const
+{
+ _imp->build_dependencies.reset(new EDependenciesKey(shared_from_this(), r, h, v, mkt_dependencies));
+ add_key(_imp->build_dependencies);
+}
+
+void
+EbuildID::load_run_depend(const std::string & r, const std::string & h, const std::string & v) const
+{
+ _imp->run_dependencies.reset(new EDependenciesKey(shared_from_this(), r, h, v, mkt_dependencies));
+ add_key(_imp->run_dependencies);
+}
+
+void
+EbuildID::load_post_depend(const std::string & r, const std::string & h, const std::string & v) const
+{
+ _imp->post_dependencies.reset(new EDependenciesKey(shared_from_this(), r, h, v, mkt_dependencies));
+ add_key(_imp->post_dependencies);
+}
+
+void
+EbuildID::load_src_uri(const std::string & r, const std::string & h, const std::string & v) const
+{
+ _imp->src_uri.reset(new EURIKey(shared_from_this(), r, h, v, mkt_dependencies));
+ add_key(_imp->src_uri);
+}
+
+void
+EbuildID::load_homepage(const std::string & r, const std::string & h, const std::string & v) const
+{
+ _imp->homepage.reset(new EURIKey(shared_from_this(), r, h, v, mkt_significant));
+ add_key(_imp->homepage);
+}
+
+void
+EbuildID::load_license(const std::string & r, const std::string & h, const std::string & v) const
+{
+ _imp->license.reset(new ELicenseKey(shared_from_this(), r, h, v, mkt_normal));
+ add_key(_imp->license);
+}
+
+void
+EbuildID::load_restrict(const std::string & r, const std::string & h, const std::string & v) const
+{
+ _imp->restrictions.reset(new ERestrictKey(shared_from_this(), r, h, v, mkt_internal));
+ add_key(_imp->restrictions);
+}
+
+void
+EbuildID::load_provide(const std::string & r, const std::string & h, const std::string & v) const
+{
+ _imp->provide.reset(new EProvideKey(shared_from_this(), r, h, v, mkt_dependencies));
+ add_key(_imp->provide);
+}
+
+void
+EbuildID::load_iuse(const std::string & r, const std::string & h, const std::string & v) const
+{
+ _imp->iuse.reset(new EIUseKey(shared_from_this(), r, h, v, mkt_normal));
+ add_key(_imp->iuse);
+}
+
+void
+EbuildID::load_keywords(const std::string & r, const std::string & h, const std::string & v) const
+{
+ _imp->keywords.reset(new EKeywordsKey(shared_from_this(), r, h, v, mkt_normal));
+ add_key(_imp->keywords);
+}
+
+void
+EbuildID::load_inherited(const std::string & r, const std::string & h, const std::string & v) const
+{
+ _imp->inherited.reset(new EInheritedKey(shared_from_this(), r, h, v, mkt_internal));
+ add_key(_imp->inherited);
+}
+
diff --git a/paludis/repositories/e/ebuild_id.hh b/paludis/repositories/e/ebuild_id.hh
new file mode 100644
index 000000000..04440b48a
--- /dev/null
+++ b/paludis/repositories/e/ebuild_id.hh
@@ -0,0 +1,113 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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_GENTOO_EBUILD_ID_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GENTOO_EBUILD_ID_HH 1
+
+#include <paludis/package_id.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/util/fs_entry-fwd.hh>
+
+namespace paludis
+{
+ class PortageRepository;
+ class EclassMtimes;
+
+ namespace erepository
+ {
+ class EbuildID :
+ public PackageID,
+ public tr1::enable_shared_from_this<EbuildID>,
+ private PrivateImplementationPattern<EbuildID>
+ {
+ private:
+ Implementation<EbuildID> * const _imp;
+
+ protected:
+ virtual void need_keys_added() const;
+
+ public:
+ EbuildID(const QualifiedPackageName &, const VersionSpec &,
+ const Environment * const e,
+ const tr1::shared_ptr<const PortageRepository> &,
+ const FSEntry & file,
+ const std::string & guessed_eapi,
+ const time_t master_mtime,
+ const tr1::shared_ptr<const EclassMtimes> & eclass_mtimes);
+
+ ~EbuildID();
+
+ 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 tr1::shared_ptr<const Repository> repository() const;
+ virtual const tr1::shared_ptr<const EAPI> eapi() const;
+
+ virtual const tr1::shared_ptr<const MetadataPackageIDKey> virtual_for_key() const;
+ virtual const tr1::shared_ptr<const MetadataCollectionKey<KeywordNameCollection> > keywords_key() const;
+ virtual const tr1::shared_ptr<const MetadataCollectionKey<UseFlagNameCollection> > use_key() const;
+ virtual const tr1::shared_ptr<const MetadataCollectionKey<IUseFlagCollection> > iuse_key() const;
+ virtual const tr1::shared_ptr<const MetadataCollectionKey<InheritedCollection> > inherited_key() const;
+ virtual const tr1::shared_ptr<const MetadataSpecTreeKey<LicenseSpecTree> > license_key() const;
+ virtual const tr1::shared_ptr<const MetadataSpecTreeKey<ProvideSpecTree> > provide_key() const;
+ virtual const tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > build_dependencies_key() const;
+ virtual const tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > run_dependencies_key() const;
+ virtual const tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > post_dependencies_key() const;
+ virtual const tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> > suggested_dependencies_key() const;
+ virtual const tr1::shared_ptr<const MetadataSpecTreeKey<RestrictSpecTree> > restrict_key() const;
+ virtual const tr1::shared_ptr<const MetadataSpecTreeKey<URISpecTree> > src_uri_key() const;
+ virtual const tr1::shared_ptr<const MetadataSpecTreeKey<URISpecTree> > bin_uri_key() const;
+ virtual const tr1::shared_ptr<const MetadataSpecTreeKey<URISpecTree> > homepage_key() const;
+ virtual const tr1::shared_ptr<const MetadataStringKey> short_description_key() const;
+ virtual const tr1::shared_ptr<const MetadataStringKey> long_description_key() const;
+ virtual const tr1::shared_ptr<const MetadataContentsKey> contents_key() const;
+ virtual const tr1::shared_ptr<const MetadataTimeKey> installed_time_key() const;
+ virtual const tr1::shared_ptr<const MetadataStringKey> source_origin_key() const;
+ virtual const tr1::shared_ptr<const MetadataStringKey> binary_origin_key() const;
+
+ 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));
+
+ virtual tr1::shared_ptr<const PortageRepository> portage_repository() const;
+
+ void set_eapi(const std::string &) const;
+ void set_slot(const SlotName &) const;
+
+ void load_short_description(const std::string &, const std::string &, const std::string &) const;
+ void load_build_depend(const std::string &, const std::string &, const std::string &) const;
+ void load_run_depend(const std::string &, const std::string &, const std::string &) const;
+ void load_post_depend(const std::string &, const std::string &, const std::string &) const;
+ void load_src_uri(const std::string &, const std::string &, const std::string &) const;
+ void load_homepage(const std::string &, const std::string &, const std::string &) const;
+ void load_license(const std::string &, const std::string &, const std::string &) const;
+ void load_provide(const std::string &, const std::string &, const std::string &) const;
+ void load_iuse(const std::string &, const std::string &, const std::string &) const;
+ void load_inherited(const std::string &, const std::string &, const std::string &) const;
+ void load_keywords(const std::string &, const std::string &, const std::string &) const;
+ void load_restrict(const std::string &, const std::string &, const std::string &) const;
+ };
+ }
+}
+
+#endif
diff --git a/paludis/repositories/e/eclass_mtimes.cc b/paludis/repositories/e/eclass_mtimes.cc
new file mode 100644
index 000000000..041cdfe22
--- /dev/null
+++ b/paludis/repositories/e/eclass_mtimes.cc
@@ -0,0 +1,71 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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 "eclass_mtimes.hh"
+#include <paludis/hashed_containers.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+
+using namespace paludis;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<EclassMtimes>
+ {
+ tr1::shared_ptr<const FSEntryCollection> eclass_dirs;
+ mutable MakeHashedMap<std::string, time_t>::Type eclass_mtimes;
+
+ Implementation(tr1::shared_ptr<const FSEntryCollection> d) :
+ eclass_dirs(d)
+ {
+ }
+ };
+}
+
+EclassMtimes::EclassMtimes(tr1::shared_ptr<const FSEntryCollection> d) :
+ PrivateImplementationPattern<EclassMtimes>(new Implementation<EclassMtimes>(d))
+{
+}
+
+EclassMtimes::~EclassMtimes()
+{
+}
+
+time_t
+EclassMtimes::mtime(const std::string & e) const
+{
+ MakeHashedMap<std::string, time_t>::Type::const_iterator i(_imp->eclass_mtimes.find(e));
+ if (i != _imp->eclass_mtimes.end())
+ return i->second;
+
+ time_t r(0);
+ for (FSEntryCollection::Iterator d(_imp->eclass_dirs->begin()),
+ d_end(_imp->eclass_dirs->end()) ; d != d_end ; ++d)
+ {
+ FSEntry f(*d / (e + ".eclass"));
+ if (f.exists())
+ r = std::max(r, f.mtime());
+ }
+
+ _imp->eclass_mtimes.insert(std::make_pair(e, r));
+ return r;
+}
+
diff --git a/paludis/repositories/e/eclass_mtimes.hh b/paludis/repositories/e/eclass_mtimes.hh
new file mode 100644
index 000000000..4fd49c000
--- /dev/null
+++ b/paludis/repositories/e/eclass_mtimes.hh
@@ -0,0 +1,55 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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_PORTAGE_ECLASS_MTIMES_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_ECLASS_MTIMES_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/collection.hh>
+
+namespace paludis
+{
+ /**
+ * Holds an eclass mtimes cache for a PortageRepository.
+ *
+ * \see PortageRepository
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class EclassMtimes :
+ private PrivateImplementationPattern<EclassMtimes>
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ EclassMtimes(tr1::shared_ptr<const FSEntryCollection>);
+ ~EclassMtimes();
+
+ ///\}
+
+ /**
+ * Fetch the mtime for a given eclass.
+ */
+ time_t mtime(const std::string &) const;
+ };
+}
+
+#endif
diff --git a/paludis/repositories/e/exheres_layout.cc b/paludis/repositories/e/exheres_layout.cc
new file mode 100644
index 000000000..461d0c1be
--- /dev/null
+++ b/paludis/repositories/e/exheres_layout.cc
@@ -0,0 +1,441 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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/e/exheres_layout.hh>
+#include <paludis/repositories/e/portage_repository_entries.hh>
+#include <paludis/repositories/e/portage_repository_exceptions.hh>
+#include <paludis/repositories/e/portage_repository.hh>
+#include <paludis/config_file.hh>
+#include <paludis/hashed_containers.hh>
+#include <paludis/package_id.hh>
+#include <paludis/package_database.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/tr1_functional.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/strip.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+
+#include <paludis/util/tr1_functional.hh>
+#include <functional>
+#include <algorithm>
+
+using namespace paludis;
+
+typedef MakeHashedMap<CategoryNamePart, bool>::Type CategoryMap;
+typedef MakeHashedMap<QualifiedPackageName, bool>::Type PackagesMap;
+typedef MakeHashedMap<QualifiedPackageName, tr1::shared_ptr<PackageIDSequence> >::Type IDMap;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<ExheresLayout>
+ {
+ const PortageRepository * const repository;
+ const FSEntry tree_root;
+
+ mutable bool has_category_names;
+ mutable CategoryMap category_names;
+ mutable PackagesMap package_names;
+ mutable IDMap ids;
+
+ mutable tr1::shared_ptr<CategoryNamePartCollection> category_names_collection;
+ tr1::shared_ptr<const PortageRepositoryEntries> entries;
+
+ tr1::shared_ptr<FSEntryCollection> arch_list_files;
+ tr1::shared_ptr<FSEntryCollection> repository_mask_files;
+ tr1::shared_ptr<FSEntryCollection> profiles_desc_files;
+ tr1::shared_ptr<FSEntryCollection> mirror_files;
+ tr1::shared_ptr<FSEntryCollection> use_desc_dirs;
+
+ Implementation(const PortageRepository * const n, const FSEntry & t,
+ tr1::shared_ptr<const PortageRepositoryEntries> e) :
+ repository(n),
+ tree_root(t),
+ has_category_names(false),
+ entries(e),
+ arch_list_files(new FSEntryCollection::Concrete),
+ repository_mask_files(new FSEntryCollection::Concrete),
+ profiles_desc_files(new FSEntryCollection::Concrete),
+ mirror_files(new FSEntryCollection::Concrete),
+ use_desc_dirs(new FSEntryCollection::Concrete)
+ {
+ }
+ };
+}
+
+ExheresLayout::ExheresLayout(const PortageRepository * const r, const FSEntry & tree_root,
+ tr1::shared_ptr<const PortageRepositoryEntries> e,
+ tr1::shared_ptr<const FSEntry> f) :
+ Layout(f),
+ PrivateImplementationPattern<ExheresLayout>(new Implementation<ExheresLayout>(r, tree_root, e))
+{
+ if (master_repository_location())
+ {
+ _imp->arch_list_files->push_back(*master_repository_location() / "metadata" / "arch.conf");
+ _imp->repository_mask_files->push_back(*master_repository_location() / "metadata" / "repository_mask.conf");
+ _imp->profiles_desc_files->push_back(*master_repository_location() / "metadata" / "profiles_desc.conf");
+ _imp->mirror_files->push_back(*master_repository_location() / "metadata" / "mirrors.conf");
+ _imp->use_desc_dirs->push_back(*master_repository_location() / "metadata" / "desc");
+ }
+
+ _imp->arch_list_files->push_back(_imp->tree_root / "metadata" / "arch.conf");
+ _imp->repository_mask_files->push_back(_imp->tree_root / "metadata" / "repository_mask.conf");
+ _imp->profiles_desc_files->push_back(_imp->tree_root / "metadata" / "profiles_desc.conf");
+ _imp->mirror_files->push_back(_imp->tree_root / "metadata" / "mirrors.conf");
+ _imp->use_desc_dirs->push_back(_imp->tree_root / "metadata" / "desc");
+}
+
+ExheresLayout::~ExheresLayout()
+{
+}
+
+void
+ExheresLayout::need_category_names() const
+{
+ if (_imp->has_category_names)
+ return;
+
+ Context context("When loading category names for " + stringify(_imp->repository->name()) + ":");
+
+ Log::get_instance()->message(ll_debug, lc_context, "need_category_names");
+
+ bool found_one(false);
+
+ std::list<FSEntry> cats_list;
+ if (master_repository_location())
+ cats_list.push_back(*master_repository_location() / "metadata" / "categories.conf");
+ cats_list.push_back(_imp->tree_root / "metadata" / "categories.conf");
+
+ for (std::list<FSEntry>::const_iterator i(cats_list.begin()), i_end(cats_list.end()) ;
+ i != i_end ; ++i)
+ {
+ if (! i->exists())
+ continue;
+
+ LineConfigFile cats(*i, LineConfigFileOptions());
+
+ for (LineConfigFile::Iterator line(cats.begin()), line_end(cats.end()) ;
+ line != line_end ; ++line)
+ {
+ try
+ {
+ _imp->category_names.insert(std::make_pair(CategoryNamePart(*line), false));
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Skipping line '"
+ + *line + "' in '" + stringify(*i) + "' due to exception '"
+ + stringify(e.message()) + "' ('" + e.what() + ")");
+ }
+ }
+
+ found_one = true;
+ }
+
+ if (! found_one)
+ throw PortageRepositoryConfigurationError("No categories file available for repository '"
+ + stringify(_imp->repository->name()) + "', and this layout does not allow auto-generation");
+
+ _imp->has_category_names = true;
+}
+
+void
+ExheresLayout::need_package_ids(const QualifiedPackageName & n) const
+{
+ using namespace tr1::placeholders;
+
+ if (_imp->package_names[n])
+ return;
+
+ Context context("When loading versions for '" + stringify(n) + "' in "
+ + stringify(_imp->repository->name()) + ":");
+
+ tr1::shared_ptr<PackageIDSequence> v(new PackageIDSequence::Concrete);
+
+ FSEntry path(_imp->tree_root / "packages" / stringify(n.category) / stringify(n.package));
+
+ for (DirIterator e(path), e_end ; e != e_end ; ++e)
+ {
+ if (! _imp->entries->is_package_file(n, *e))
+ continue;
+
+ try
+ {
+ tr1::shared_ptr<const PackageID> id(_imp->entries->make_id(n, _imp->entries->extract_package_file_version(n, *e), *e, ""));
+ if (v->end() != std::find_if(v->begin(), v->end(),
+ tr1::bind(std::equal_to<VersionSpec>(), id->version(), tr1::bind(tr1::mem_fn(&PackageID::version), _1))))
+ Log::get_instance()->message(ll_warning, lc_context, "Ignoring entry '" + stringify(*e)
+ + "' for '" + stringify(n) + "' in repository '" + stringify(_imp->repository->name())
+ + "' because another equivalent version already exists");
+ v->push_back(id);
+ }
+ catch (const Exception & ee)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Skipping entry '"
+ + stringify(*e) + "' for '" + stringify(n) + "' in repository '"
+ + stringify(_imp->repository->name()) + "' due to exception '" + ee.message() + "' ("
+ + ee.what() + ")'");
+ }
+ }
+
+ _imp->ids.insert(std::make_pair(n, v));
+ _imp->package_names[n] = true;
+}
+
+bool
+ExheresLayout::has_category_named(const CategoryNamePart & c) const
+{
+ Context context("When checking for category '" + stringify(c) + "' in '" + stringify(_imp->repository->name()) + "':");
+
+ need_category_names();
+ return _imp->category_names.end() != _imp->category_names.find(c);
+}
+
+bool
+ExheresLayout::has_package_named(const QualifiedPackageName & q) const
+{
+ Context context("When checking for package '" + stringify(q) + "' in '" + stringify(_imp->repository->name()) + ":");
+
+ need_category_names();
+
+ CategoryMap::iterator cat_iter(_imp->category_names.find(q.category));
+
+ if (_imp->category_names.end() == cat_iter)
+ return false;
+
+ if (cat_iter->second)
+ {
+ /* this category's package names are fully loaded */
+ return _imp->package_names.find(q) != _imp->package_names.end();
+ }
+ else
+ {
+ /* package names are only partially loaded or not loaded */
+ if (_imp->package_names.find(q) != _imp->package_names.end())
+ return true;
+
+ FSEntry fs(_imp->tree_root);
+ fs /= "packages";
+ fs /= stringify(q.category);
+ fs /= stringify(q.package);
+ if (! fs.is_directory_or_symlink_to_directory())
+ return false;
+ _imp->package_names.insert(std::make_pair(q, false));
+ return true;
+ }
+}
+
+void
+ExheresLayout::need_category_names_collection() const
+{
+ if (_imp->category_names_collection)
+ return;
+
+ need_category_names();
+
+ _imp->category_names_collection.reset(new CategoryNamePartCollection::Concrete);
+ std::copy(_imp->category_names.begin(), _imp->category_names.end(),
+ transform_inserter(_imp->category_names_collection->inserter(),
+ tr1::mem_fn(&std::pair<const CategoryNamePart, bool>::first)));
+}
+
+tr1::shared_ptr<const CategoryNamePartCollection>
+ExheresLayout::category_names() const
+{
+ Context context("When fetching category names in " + stringify(stringify(_imp->repository->name())) + ":");
+
+ need_category_names_collection();
+ return _imp->category_names_collection;
+}
+
+tr1::shared_ptr<const QualifiedPackageNameCollection>
+ExheresLayout::package_names(const CategoryNamePart & c) const
+{
+ using namespace tr1::placeholders;
+
+ /* this isn't particularly fast because it isn't called very often. avoid
+ * changing the data structures used to make this faster at the expense of
+ * slowing down single item queries. */
+
+ Context context("When fetching package names in category '" + stringify(c)
+ + "' in '" + stringify(_imp->repository->name()) + "':");
+
+ need_category_names();
+
+ if (_imp->category_names.end() == _imp->category_names.find(c))
+ return tr1::shared_ptr<QualifiedPackageNameCollection>(new QualifiedPackageNameCollection::Concrete);
+
+ if ((_imp->tree_root / "packages" / stringify(c)).is_directory_or_symlink_to_directory())
+ for (DirIterator d(_imp->tree_root / "packages" / stringify(c)), d_end ; d != d_end ; ++d)
+ {
+ try
+ {
+ if (! d->is_directory_or_symlink_to_directory())
+ continue;
+
+ if (DirIterator() == std::find_if(DirIterator(*d), DirIterator(),
+ tr1::bind(&PortageRepositoryEntries::is_package_file, _imp->entries.get(),
+ c + PackageNamePart(d->basename()), _1)))
+ continue;
+
+ _imp->package_names.insert(std::make_pair(c + PackageNamePart(d->basename()), false));
+ }
+ catch (const NameError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Skipping entry '" +
+ d->basename() + "' in category '" + stringify(c) + "' in repository '"
+ + stringify(_imp->repository->name()) + "' (" + e.message() + ")");
+ }
+ }
+
+ _imp->category_names[c] = true;
+
+ tr1::shared_ptr<QualifiedPackageNameCollection> result(new QualifiedPackageNameCollection::Concrete);
+
+ for (PackagesMap::const_iterator p(_imp->package_names.begin()), p_end(_imp->package_names.end()) ;
+ p != p_end ; ++p)
+ if (p->first.category == c)
+ result->insert(p->first);
+
+ return result;
+}
+
+tr1::shared_ptr<const PackageIDSequence>
+ExheresLayout::package_ids(const QualifiedPackageName & n) const
+{
+ Context context("When fetching versions of '" + stringify(n) + "' in " + stringify(_imp->repository->name()) + ":");
+
+ if (has_package_named(n))
+ {
+ need_package_ids(n);
+ return _imp->ids.find(n)->second;
+ }
+ else
+ return tr1::shared_ptr<PackageIDSequence>(new PackageIDSequence::Concrete);
+}
+
+FSEntry
+ExheresLayout::info_packages_file(const FSEntry & dir) const
+{
+ return dir / "info_packages.conf";
+}
+
+FSEntry
+ExheresLayout::info_variables_file(const FSEntry & dir) const
+{
+ return dir / "info_variables.conf";
+}
+
+FSEntry
+ExheresLayout::package_directory(const QualifiedPackageName & qpn) const
+{
+ return _imp->tree_root / "packages" / stringify(qpn.category) / stringify(qpn.package);
+}
+
+FSEntry
+ExheresLayout::category_directory(const CategoryNamePart & cat) const
+{
+ return _imp->tree_root / "packages" / stringify(cat);
+}
+
+tr1::shared_ptr<const FSEntryCollection>
+ExheresLayout::arch_list_files() const
+{
+ return _imp->arch_list_files;
+}
+
+tr1::shared_ptr<const FSEntryCollection>
+ExheresLayout::repository_mask_files() const
+{
+ return _imp->repository_mask_files;
+}
+
+tr1::shared_ptr<const FSEntryCollection>
+ExheresLayout::profiles_desc_files() const
+{
+ return _imp->profiles_desc_files;
+}
+
+tr1::shared_ptr<const FSEntryCollection>
+ExheresLayout::mirror_files() const
+{
+ return _imp->mirror_files;
+}
+
+tr1::shared_ptr<const FSEntryCollection>
+ExheresLayout::use_desc_dirs() const
+{
+ return _imp->use_desc_dirs;
+}
+
+bool
+ExheresLayout::eapi_ebuild_suffix() const
+{
+ return true;
+}
+
+FSEntry
+ExheresLayout::package_file(const PackageID & id) const
+{
+ for (DirIterator d(package_directory(id.name())), d_end ; d != d_end ; ++d)
+ {
+ std::string::size_type p(d->basename().rfind('.'));
+ if (std::string::npos == p)
+ continue;
+
+ std::string prefix(stringify(id.name().package) + "-" + stringify(id.version()));
+ if (0 == d->basename().compare(0, p, prefix))
+ if (_imp->entries->is_package_file(id.name(), *d))
+ return *d;
+ }
+
+ throw NoSuchPackageError(stringify(id));
+}
+
+FSEntry
+ExheresLayout::profiles_base_dir() const
+{
+ return _imp->tree_root / "profiles";
+}
+
+tr1::shared_ptr<const FSEntryCollection>
+ExheresLayout::exlibsdirs(const QualifiedPackageName & q) const
+{
+ tr1::shared_ptr<FSEntryCollection> result(new FSEntryCollection::Concrete);
+
+ if (_imp->repository->params().master_repository)
+ result->push_back(_imp->repository->params().master_repository->params().location / "exlibs");
+ result->push_back(_imp->tree_root / "exlibs");
+ if (_imp->repository->params().master_repository)
+ result->push_back(_imp->repository->params().master_repository->layout()->category_directory(q.category) / "exlibs");
+ result->push_back(_imp->repository->layout()->category_directory(q.category) / "exlibs");
+ if (_imp->repository->params().master_repository)
+ result->push_back(_imp->repository->params().master_repository->layout()->package_directory(q));
+ result->push_back(_imp->repository->layout()->package_directory(q));
+
+ return result;
+}
+
diff --git a/paludis/repositories/e/exheres_layout.hh b/paludis/repositories/e/exheres_layout.hh
new file mode 100644
index 000000000..1517af8c9
--- /dev/null
+++ b/paludis/repositories/e/exheres_layout.hh
@@ -0,0 +1,114 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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_GENTOO_EXHERES_LAYOUT_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GENTOO_EXHERES_LAYOUT_HH 1
+
+#include <paludis/repositories/e/layout.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace paludis
+{
+ class PortageRepositoryEntries;
+
+ /**
+ * The Exheres tree layout for a PortageRepository.
+ *
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE ExheresLayout :
+ public Layout,
+ private PrivateImplementationPattern<ExheresLayout>
+ {
+ private:
+ void need_category_names() const;
+ void need_category_names_collection() const;
+ void need_package_ids(const QualifiedPackageName &) const;
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ ExheresLayout(const PortageRepository * const, const FSEntry &,
+ tr1::shared_ptr<const PortageRepositoryEntries>,
+ tr1::shared_ptr<const FSEntry>);
+
+ virtual ~ExheresLayout();
+
+ ///\}
+
+ virtual bool has_category_named(const CategoryNamePart &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool has_package_named(const QualifiedPackageName &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const CategoryNamePartCollection> category_names() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const QualifiedPackageNameCollection> package_names(
+ const CategoryNamePart &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const PackageIDSequence> package_ids(
+ const QualifiedPackageName &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual FSEntry info_packages_file(const FSEntry &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual FSEntry info_variables_file(const FSEntry &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual FSEntry package_directory(const QualifiedPackageName &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual FSEntry category_directory(const CategoryNamePart &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual FSEntry package_file(const PackageID &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const FSEntryCollection> arch_list_files() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const FSEntryCollection> repository_mask_files() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const FSEntryCollection> profiles_desc_files() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const FSEntryCollection> mirror_files() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const FSEntryCollection> use_desc_dirs() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool eapi_ebuild_suffix() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual FSEntry profiles_base_dir() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const FSEntryCollection> exlibsdirs(const QualifiedPackageName &) const;
+ };
+}
+
+#endif
diff --git a/paludis/repositories/e/glsa.cc b/paludis/repositories/e/glsa.cc
new file mode 100644
index 000000000..df4f723f6
--- /dev/null
+++ b/paludis/repositories/e/glsa.cc
@@ -0,0 +1,254 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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 "glsa.hh"
+#include <paludis/util/iterator.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+#include <list>
+#include <dlfcn.h>
+#include <stdint.h>
+#include "config.h"
+
+#define STUPID_CAST(type, val) reinterpret_cast<type>(reinterpret_cast<uintptr_t>(val))
+
+using namespace paludis;
+
+#include "glsa-sr.cc"
+
+#ifdef MONOLITHIC
+# include <paludis/repositories/portage/xml_things.hh>
+#endif
+
+namespace paludis
+{
+ template<>
+ struct Implementation<GLSAPackage>
+ {
+ QualifiedPackageName name;
+ std::list<UseFlagName> archs;
+ std::list<GLSARange> unaffected;
+ std::list<GLSARange> vulnerable;
+
+ Implementation(const QualifiedPackageName & n) :
+ name(n)
+ {
+ }
+ };
+
+ template<>
+ struct Implementation<GLSA>
+ {
+ std::string id;
+ std::string title;
+ std::list<tr1::shared_ptr<const GLSAPackage> > packages;
+ };
+}
+
+GLSAPackage::GLSAPackage(const QualifiedPackageName & n) :
+ PrivateImplementationPattern<GLSAPackage>(new Implementation<GLSAPackage>(n))
+{
+}
+
+GLSAPackage::~GLSAPackage()
+{
+}
+
+GLSAPackage::ArchsIterator
+GLSAPackage::begin_archs() const
+{
+ return ArchsIterator(_imp->archs.begin());
+}
+
+GLSAPackage::ArchsIterator
+GLSAPackage::end_archs() const
+{
+ return ArchsIterator(_imp->archs.end());
+}
+
+void
+GLSAPackage::add_arch(const UseFlagName & n)
+{
+ _imp->archs.push_back(n);
+}
+
+GLSAPackage::RangesIterator
+GLSAPackage::begin_unaffected() const
+{
+ return RangesIterator(_imp->unaffected.begin());
+}
+
+GLSAPackage::RangesIterator
+GLSAPackage::end_unaffected() const
+{
+ return RangesIterator(_imp->unaffected.end());
+}
+
+GLSAPackage::RangesIterator
+GLSAPackage::begin_vulnerable() const
+{
+ return RangesIterator(_imp->vulnerable.begin());
+}
+
+GLSAPackage::RangesIterator
+GLSAPackage::end_vulnerable() const
+{
+ return RangesIterator(_imp->vulnerable.end());
+}
+
+void
+GLSAPackage::add_unaffected(const GLSARange & r)
+{
+ _imp->unaffected.push_back(r);
+}
+
+void
+GLSAPackage::add_vulnerable(const GLSARange & r)
+{
+ _imp->vulnerable.push_back(r);
+}
+
+QualifiedPackageName
+GLSAPackage::name() const
+{
+ return _imp->name;
+}
+
+GLSA::GLSA() :
+ PrivateImplementationPattern<GLSA>(new Implementation<GLSA>)
+{
+}
+
+GLSA::~GLSA()
+{
+}
+
+GLSA::PackagesIterator
+GLSA::begin_packages() const
+{
+ return PackagesIterator(indirect_iterator(_imp->packages.begin()));
+}
+
+GLSA::PackagesIterator
+GLSA::end_packages() const
+{
+ return PackagesIterator(indirect_iterator(_imp->packages.end()));
+}
+
+void
+GLSA::add_package(tr1::shared_ptr<const GLSAPackage> p)
+{
+ _imp->packages.push_back(p);
+}
+
+void
+GLSA::set_id(const std::string & s)
+{
+ _imp->id = s;
+}
+
+void
+GLSA::set_title(const std::string & s)
+{
+ _imp->title = s;
+}
+
+std::string
+GLSA::id() const
+{
+ return _imp->id;
+}
+
+std::string
+GLSA::title() const
+{
+ return _imp->title;
+}
+
+#ifndef MONOLITHIC
+
+namespace
+{
+ struct LibXMLHandle
+ {
+ void * handle;
+ tr1::shared_ptr<GLSA> (* create_glsa_from_xml_file_handle)(const std::string &);
+
+ LibXMLHandle() :
+ handle(0),
+ create_glsa_from_xml_file_handle(0)
+ {
+ }
+
+ ~LibXMLHandle()
+ {
+ if (0 != handle)
+ dlclose(handle);
+ }
+
+ } libxmlhandle;
+}
+
+#endif
+
+tr1::shared_ptr<GLSA>
+GLSA::create_from_xml_file(const std::string & filename)
+{
+#if ENABLE_GLSA
+# ifdef MONOLITHIC
+
+# else
+ if (0 == libxmlhandle.handle)
+ libxmlhandle.handle = dlopen("libpaludisgentoorepositoryxmlthings.so",
+ RTLD_NOW | RTLD_GLOBAL);
+ if (0 == libxmlhandle.handle)
+ throw NotAvailableError("Cannot create GLSA from XML file '" + filename + "' due to error '"
+ + stringify(dlerror()) + "' when dlopen(libpaludisgentoorepositoryxmlthings.so)");
+
+ if (0 == libxmlhandle.create_glsa_from_xml_file_handle)
+ libxmlhandle.create_glsa_from_xml_file_handle = STUPID_CAST(tr1::shared_ptr<GLSA> (*)(const std::string &),
+ dlsym(libxmlhandle.handle, "create_glsa_from_xml_file"));
+ if (0 == libxmlhandle.create_glsa_from_xml_file_handle)
+ throw NotAvailableError("Cannot create GLSA from XML file '" + filename + "' due to error '"
+ + stringify(dlerror()) + "' when dlsym(libpaludisgentoorepositoryxmlthings.so, create_glsa_from_xml_file)");
+
+# endif
+#else
+# ifndef MONOLITHIC
+ /* avoid noreturn warning */
+ if (0 == libxmlhandle.handle)
+ throw NotAvailableError("Cannot create GLSA from XML file '" + filename + "' because Paludis was built "
+ "without GLSA support");
+# endif
+#endif
+
+#ifdef MONOLITHIC
+ return create_glsa_from_xml_file(filename);
+#else
+ return (*libxmlhandle.create_glsa_from_xml_file_handle)(filename);
+#endif
+}
+
+GLSAError::GLSAError(const std::string & msg, const std::string & filename) throw () :
+ ConfigurationError("GLSA error: " + msg + (filename.empty() ? "" : " in file " + filename))
+{
+}
+
diff --git a/paludis/repositories/e/glsa.hh b/paludis/repositories/e/glsa.hh
new file mode 100644
index 000000000..47ffae527
--- /dev/null
+++ b/paludis/repositories/e/glsa.hh
@@ -0,0 +1,174 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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_PORTAGE_GLSA_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_GLSA_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/sr.hh>
+#include <paludis/name.hh>
+#include <paludis/version_spec.hh>
+#include <libwrapiter/libwrapiter_forward_iterator-fwd.hh>
+
+#include <string>
+
+namespace paludis
+{
+
+#include <paludis/repositories/e/glsa-sr.hh>
+
+ /**
+ * Thrown if a bad GLSA is found.
+ *
+ * \ingroup grpexceptions
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE GLSAError :
+ public ConfigurationError
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ GLSAError(const std::string & message,
+ const std::string & filename = "") throw ();
+
+ ///\}
+ };
+
+ /**
+ * Represents a package entry in a GLSA.
+ *
+ * \see GLSA
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE GLSAPackage :
+ private PrivateImplementationPattern<GLSAPackage>
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ GLSAPackage(const QualifiedPackageName & name);
+ ~GLSAPackage();
+
+ ///\}
+
+ ///\name Iterate over our archs.
+ ///\{
+
+ typedef libwrapiter::ForwardIterator<GLSAPackage, const UseFlagName> ArchsIterator;
+ ArchsIterator begin_archs() const;
+ ArchsIterator end_archs() const;
+
+ ///\}
+
+ /**
+ * Add an arch.
+ */
+ void add_arch(const UseFlagName &);
+
+ ///\name Iterate over our ranges.
+ ///\{
+
+ typedef libwrapiter::ForwardIterator<GLSAPackage, const GLSARange> RangesIterator;
+ RangesIterator begin_unaffected() const;
+ RangesIterator end_unaffected() const;
+ RangesIterator begin_vulnerable() const;
+ RangesIterator end_vulnerable() const;
+
+ ///\}
+
+ /**
+ * Add an unaffected package.
+ */
+ void add_unaffected(const GLSARange &);
+
+ /**
+ * Add a vulnerable package.
+ */
+ void add_vulnerable(const GLSARange &);
+
+ /**
+ * Our package's name.
+ */
+ QualifiedPackageName name() const;
+ };
+
+ /**
+ * Represents a GLSA (security advisory).
+ *
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE GLSA :
+ private PrivateImplementationPattern<GLSA>
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ GLSA();
+ ~GLSA();
+
+ ///\}
+
+ /**
+ * Create a GLSA from an XML file.
+ */
+ static tr1::shared_ptr<GLSA> create_from_xml_file(const std::string & filename);
+
+ ///\name Iterate over our packages.
+ ///\{
+
+ typedef libwrapiter::ForwardIterator<GLSA, const GLSAPackage> PackagesIterator;
+ PackagesIterator begin_packages() const;
+ PackagesIterator end_packages() const;
+
+ ///\}
+
+ /**
+ * Add a package.
+ */
+ void add_package(tr1::shared_ptr<const GLSAPackage>);
+
+ /**
+ * Set our ID.
+ */
+ void set_id(const std::string &);
+
+ /**
+ * Fetch our ID.
+ */
+ std::string id() const;
+
+ /**
+ * Set our title.
+ */
+ void set_title(const std::string &);
+
+ /**
+ * Fetch our title.
+ */
+ std::string title() const;
+ };
+}
+
+#endif
diff --git a/paludis/repositories/e/glsa.sr b/paludis/repositories/e/glsa.sr
new file mode 100644
index 000000000..fdff8e421
--- /dev/null
+++ b/paludis/repositories/e/glsa.sr
@@ -0,0 +1,19 @@
+make_class_GLSARange()
+{
+ visible
+
+ key op std::string
+ # not a version, may be something like 1.3*
+ key version std::string
+
+ allow_named_args
+
+ doxygen_comment << "END"
+ /**
+ * A version range in a GLSA.
+ *
+ * \see PortageRepositorySets
+ * \ingroup grpportagerepository
+ */
+END
+}
diff --git a/paludis/repositories/e/layout.cc b/paludis/repositories/e/layout.cc
new file mode 100644
index 000000000..88f22d799
--- /dev/null
+++ b/paludis/repositories/e/layout.cc
@@ -0,0 +1,76 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ *
+ * 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/e/layout.hh>
+#include <paludis/repositories/e/traditional_layout.hh>
+#include <paludis/repositories/e/exheres_layout.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/virtual_constructor-impl.hh>
+#include <paludis/util/instantiation_policy-impl.hh>
+
+using namespace paludis;
+
+template class VirtualConstructor<std::string,
+ tr1::shared_ptr<Layout> (*) (const PortageRepository * const, const FSEntry &,
+ tr1::shared_ptr<const PortageRepositoryEntries>,
+ tr1::shared_ptr<const FSEntry>),
+ virtual_constructor_not_found::ThrowException<NoSuchLayoutType> >;
+
+template class InstantiationPolicy<LayoutMaker, instantiation_method::SingletonTag>;
+
+Layout::Layout(tr1::shared_ptr<const FSEntry> l) :
+ _master_repository_location(l)
+{
+}
+
+Layout::~Layout()
+{
+}
+
+tr1::shared_ptr<const FSEntry>
+Layout::master_repository_location() const
+{
+ return _master_repository_location;
+}
+
+namespace
+{
+ template <typename T_>
+ tr1::shared_ptr<Layout>
+ make_layout(const PortageRepository * const n, const FSEntry & b,
+ tr1::shared_ptr<const PortageRepositoryEntries> e,
+ tr1::shared_ptr<const FSEntry> f)
+ {
+ return tr1::shared_ptr<Layout>(new T_(n, b, e, f));
+ }
+}
+
+LayoutMaker::LayoutMaker()
+{
+ register_maker("traditional", &make_layout<TraditionalLayout>);
+ register_maker("exheres", &make_layout<ExheresLayout>);
+}
+
+NoSuchLayoutType::NoSuchLayoutType(const std::string & format) throw () :
+ ConfigurationError("No available maker for Portage repository layout type '" + format + "'")
+{
+}
+
diff --git a/paludis/repositories/e/layout.hh b/paludis/repositories/e/layout.hh
new file mode 100644
index 000000000..7d257bb53
--- /dev/null
+++ b/paludis/repositories/e/layout.hh
@@ -0,0 +1,171 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ *
+ * 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_GENTOO_LAYOUT_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GENTOO_LAYOUT_HH 1
+
+#include <paludis/name-fwd.hh>
+#include <paludis/version_spec-fwd.hh>
+#include <paludis/package_id-fwd.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/fs_entry-fwd.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/virtual_constructor.hh>
+#include <paludis/util/tr1_memory.hh>
+
+namespace paludis
+{
+ class PortageRepositoryEntries;
+ class PortageRepository;
+
+ /**
+ * Manages the layout of a PortageRepository.
+ *
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE Layout
+ {
+ private:
+ tr1::shared_ptr<const FSEntry> _master_repository_location;
+
+ protected:
+ ///\name Basic operations
+ ///\{
+
+ Layout(tr1::shared_ptr<const FSEntry> master_repository_location);
+
+ ///\}
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ virtual ~Layout() = 0;
+
+ ///\}
+
+ ///\name Configuration information
+ ///\{
+
+ tr1::shared_ptr<const FSEntry> master_repository_location() const;
+
+ ///\}
+
+ ///\name Layout operations
+ ///\{
+
+ virtual bool has_category_named(const CategoryNamePart &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual bool has_package_named(const QualifiedPackageName &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual tr1::shared_ptr<const CategoryNamePartCollection> category_names() const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual tr1::shared_ptr<const QualifiedPackageNameCollection> package_names(
+ const CategoryNamePart &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual tr1::shared_ptr<const PackageIDSequence> package_ids(
+ const QualifiedPackageName &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual FSEntry info_packages_file(const FSEntry &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual FSEntry info_variables_file(const FSEntry &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual FSEntry package_directory(const QualifiedPackageName &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual FSEntry category_directory(const CategoryNamePart &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual FSEntry package_file(const PackageID &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual tr1::shared_ptr<const FSEntryCollection> arch_list_files() const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual tr1::shared_ptr<const FSEntryCollection> repository_mask_files() const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual tr1::shared_ptr<const FSEntryCollection> profiles_desc_files() const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual tr1::shared_ptr<const FSEntryCollection> mirror_files() const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual tr1::shared_ptr<const FSEntryCollection> use_desc_dirs() const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual bool eapi_ebuild_suffix() const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual FSEntry profiles_base_dir() const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual tr1::shared_ptr<const FSEntryCollection> exlibsdirs(const QualifiedPackageName &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ ///\}
+ };
+
+ /**
+ * Thrown if a layout of the specified type does not exist.
+ *
+ * \ingroup grpexceptions
+ * \ingroup grpportagerepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE NoSuchLayoutType :
+ public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ NoSuchLayoutType(const std::string & format) throw ();
+ };
+
+ /**
+ * Virtual constructor for Layout.
+ *
+ * \ingroup grpportagerepository
+ */
+ class PALUDIS_VISIBLE LayoutMaker :
+ public VirtualConstructor<std::string,
+ tr1::shared_ptr<Layout> (*) (const PortageRepository * const, const FSEntry &,
+ tr1::shared_ptr<const PortageRepositoryEntries>,
+ tr1::shared_ptr<const FSEntry>),
+ virtual_constructor_not_found::ThrowException<NoSuchLayoutType> >,
+ public InstantiationPolicy<LayoutMaker, instantiation_method::SingletonTag>
+ {
+ friend class InstantiationPolicy<LayoutMaker, instantiation_method::SingletonTag>;
+
+ private:
+ LayoutMaker();
+ };
+}
+
+#endif
diff --git a/paludis/repositories/e/make_ebin_repository.cc b/paludis/repositories/e/make_ebin_repository.cc
new file mode 100644
index 000000000..1244a4f59
--- /dev/null
+++ b/paludis/repositories/e/make_ebin_repository.cc
@@ -0,0 +1,196 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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 "make_ebin_repository.hh"
+#include <paludis/util/log.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/repositories/e/portage_repository_exceptions.hh>
+#include <paludis/environment.hh>
+#include <paludis/distribution.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+
+using namespace paludis;
+
+tr1::shared_ptr<PortageRepository>
+paludis::make_ebin_repository(
+ Environment * const env,
+ tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m)
+{
+ std::string repo_file(m->end() == m->find("repo_file") ? std::string("?") :
+ m->find("repo_file")->second);
+
+ Context context("When making ebin repository from repo_file '" + repo_file + "':");
+
+ std::string location;
+ if (m->end() == m->find("location") || ((location = m->find("location")->second)).empty())
+ throw PortageRepositoryConfigurationError("Key 'location' not specified or empty");
+
+ tr1::shared_ptr<const RepositoryName> master_repository_name;
+ tr1::shared_ptr<const PortageRepository> master_repository;
+ if (m->end() != m->find("master_repository") && ! m->find("master_repository")->second.empty())
+ {
+ Context context_local("When finding configuration information for master_repository '"
+ + stringify(m->find("master_repository")->second) + "':");
+
+ master_repository_name.reset(new RepositoryName(m->find("master_repository")->second));
+
+ tr1::shared_ptr<const Repository> master_repository_uncasted(
+ env->package_database()->fetch_repository(*master_repository_name));
+
+ if (master_repository_uncasted->format() != "ebuild" && master_repository_uncasted->format() != "ebin")
+ throw PortageRepositoryConfigurationError("Master repository format is '" +
+ stringify(master_repository_uncasted->format()) + "', not 'ebuild' or 'ebin'");
+
+ master_repository = tr1::static_pointer_cast<const PortageRepository>(master_repository_uncasted);
+
+ if (master_repository->params().master_repository)
+ throw PortageRepositoryConfigurationError("Requested master repository has a master_repository of '" +
+ stringify(master_repository->params().master_repository->name()) + "', so it cannot "
+ "be used as a master repository");
+ }
+
+ tr1::shared_ptr<FSEntryCollection> profiles(new FSEntryCollection::Concrete);
+ if (m->end() != m->find("profiles"))
+ WhitespaceTokeniser::get_instance()->tokenise(m->find("profiles")->second,
+ create_inserter<FSEntry>(std::back_inserter(*profiles)));
+
+ if (profiles->empty())
+ {
+ if (master_repository)
+ std::copy(master_repository->params().profiles->begin(),
+ master_repository->params().profiles->end(), profiles->inserter());
+ else
+ throw PortageRepositoryConfigurationError("No profiles have been specified");
+ }
+
+ tr1::shared_ptr<FSEntryCollection> eclassdirs(new FSEntryCollection::Concrete);
+
+ std::string setsdir;
+ if (m->end() == m->find("setsdir") || ((setsdir = m->find("setsdir")->second)).empty())
+ setsdir = location + "/sets";
+
+ std::string securitydir;
+ if (m->end() == m->find("securitydir") || ((securitydir = m->find("securitydir")->second)).empty())
+ securitydir = location + "/metadata/glsa";
+
+ std::string newsdir;
+ if (m->end() == m->find("newsdir") || ((newsdir = m->find("newsdir")->second)).empty())
+ newsdir = location + "/metadata/news";
+
+ std::string names_cache;
+ if (m->end() == m->find("names_cache") || ((names_cache = m->find("names_cache")->second)).empty())
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "The names_cache key is not set in '"
+ + repo_file + "'. You should read http://paludis.pioto.org/cachefiles.html and select an "
+ "appropriate value.");
+ names_cache = "/var/empty";
+ }
+
+ std::string distdir;
+ if (m->end() == m->find("distdir") || ((distdir = m->find("distdir")->second)).empty())
+ {
+ if (master_repository)
+ distdir = stringify(master_repository->params().distdir);
+ else
+ {
+ distdir = DistributionData::get_instance()->distribution_from_string(
+ env->default_distribution())->default_ebuild_distdir;
+ if (distdir.empty())
+ distdir = location + "/distfiles";
+ else if ('/' != distdir.at(0))
+ distdir = location + "/" + distdir;
+ }
+ }
+
+ std::string sync;
+ if (m->end() != m->find("sync"))
+ sync = m->find("sync")->second;
+
+ std::string write_bin_uri_prefix;
+ if (m->end() != m->find("write_bin_uri_prefix"))
+ write_bin_uri_prefix = m->find("write_bin_uri_prefix")->second;
+
+ std::string sync_options;
+ if (m->end() != m->find("sync_options"))
+ sync_options = m->find("sync_options")->second;
+
+ std::string layout;
+ if (m->end() == m->find("layout") || ((layout = m->find("layout")->second)).empty())
+ layout = DistributionData::get_instance()->distribution_from_string(
+ env->default_distribution())->default_ebuild_layout;
+
+ std::string eapi_when_unknown;
+ if (m->end() == m->find("eapi_when_unknown") || ((eapi_when_unknown = m->find("eapi_when_unknown")->second)).empty())
+ eapi_when_unknown = DistributionData::get_instance()->distribution_from_string(
+ env->default_distribution())->default_ebuild_eapi_when_unknown;
+
+ std::string eapi_when_unspecified;
+ if (m->end() == m->find("eapi_when_unspecified") || ((eapi_when_unspecified = m->find("eapi_when_unspecified")->second)).empty())
+ eapi_when_unspecified = DistributionData::get_instance()->distribution_from_string(
+ env->default_distribution())->default_ebuild_eapi_when_unspecified;
+
+ if (m->end() != m->find("sync_exclude"))
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "The sync_exclude key in '"
+ + repo_file + "' is deprecated in favour of sync_options = --exclude-from=");
+ if (! sync_options.empty())
+ sync_options += " ";
+ sync_options += "--exclude-from='" + m->find("sync_exclude")->second + "'";
+ }
+
+ std::string buildroot;
+ if (m->end() == m->find("buildroot") || ((buildroot = m->find("buildroot")->second)).empty())
+ buildroot = DistributionData::get_instance()->distribution_from_string(
+ env->default_distribution())->default_ebuild_build_root;
+
+ return tr1::shared_ptr<PortageRepository>(new PortageRepository(PortageRepositoryParams::create()
+ .entry_format("ebin")
+ .layout(layout)
+ .environment(env)
+ .location(location)
+ .profiles(profiles)
+ .cache(FSEntry("/var/empty"))
+ .write_cache(FSEntry("/var/empty"))
+ .names_cache(names_cache)
+ .eclassdirs(tr1::shared_ptr<const FSEntryCollection>(new FSEntryCollection::Concrete))
+ .distdir(FSEntry("/var/empty"))
+ .securitydir(securitydir)
+ .setsdir(setsdir)
+ .newsdir(newsdir)
+ .sync(sync)
+ .sync_options(sync_options)
+ .master_repository(master_repository)
+ .enable_destinations(true)
+ .write_bin_uri_prefix(write_bin_uri_prefix)
+ .eapi_when_unspecified(eapi_when_unspecified)
+ .eapi_when_unknown(eapi_when_unknown)
+ .buildroot(buildroot)));
+}
+
+tr1::shared_ptr<Repository>
+paludis::make_ebin_repository_wrapped(
+ Environment * const env,
+ tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m)
+{
+ return make_ebin_repository(env, m);
+}
+
+
diff --git a/paludis/repositories/e/make_ebin_repository.hh b/paludis/repositories/e/make_ebin_repository.hh
new file mode 100644
index 000000000..a4fb4b5db
--- /dev/null
+++ b/paludis/repositories/e/make_ebin_repository.hh
@@ -0,0 +1,51 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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_GENTOO_MAKE_EBIN_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_GENTOO_MAKE_EBIN_REPOSITORY_HH 1
+
+#include <paludis/repositories/e/portage_repository.hh>
+
+namespace paludis
+{
+ /**
+ * Create an ebin format repository.
+ *
+ * \see PortageRepository
+ * \ingroup grpportagerepository
+ */
+ tr1::shared_ptr<PortageRepository>
+ make_ebin_repository(
+ Environment * const,
+ tr1::shared_ptr<const AssociativeCollection<std::string, std::string> >) PALUDIS_VISIBLE;
+
+ /**
+ * Create an ebin format repository (wrapper for our virtual constructor).
+ *
+ * \see PortageRepository
+ * \ingroup grpportagerepository
+ */
+ tr1::shared_ptr<Repository>
+ make_ebin_repository_wrapped(
+ Environment * const env,
+ tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m);
+}
+
+
+#endif
diff --git a/paludis/repositories/e/make_ebuild_repository.cc b/paludis/repositories/e/make_ebuild_repository.cc
new file mode 100644
index 000000000..1527698f6
--- /dev/null
+++ b/paludis/repositories/e/make_ebuild_repository.cc
@@ -0,0 +1,222 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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 "make_ebuild_repository.hh"
+#include <paludis/util/log.hh>
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/repositories/e/portage_repository_exceptions.hh>
+#include <paludis/environment.hh>
+#include <paludis/distribution.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+
+using namespace paludis;
+
+tr1::shared_ptr<PortageRepository>
+paludis::make_ebuild_repository(
+ Environment * const env,
+ tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m)
+{
+ std::string repo_file(m->end() == m->find("repo_file") ? std::string("?") :
+ m->find("repo_file")->second);
+
+ Context context("When making ebuild repository from repo_file '" + repo_file + "':");
+
+ std::string location;
+ if (m->end() == m->find("location") || ((location = m->find("location")->second)).empty())
+ throw PortageRepositoryConfigurationError("Key 'location' not specified or empty");
+
+ tr1::shared_ptr<const RepositoryName> master_repository_name;
+ tr1::shared_ptr<const PortageRepository> master_repository;
+ if (m->end() != m->find("master_repository") && ! m->find("master_repository")->second.empty())
+ {
+ Context context_local("When finding configuration information for master_repository '"
+ + stringify(m->find("master_repository")->second) + "':");
+
+ master_repository_name.reset(new RepositoryName(m->find("master_repository")->second));
+
+ tr1::shared_ptr<const Repository> master_repository_uncasted(
+ env->package_database()->fetch_repository(*master_repository_name));
+
+ if (master_repository_uncasted->format() != "ebuild")
+ throw PortageRepositoryConfigurationError("Master repository format is '" +
+ stringify(master_repository_uncasted->format()) + "', not 'ebuild'");
+
+ master_repository = tr1::static_pointer_cast<const PortageRepository>(master_repository_uncasted);
+
+ if (master_repository->params().master_repository)
+ throw PortageRepositoryConfigurationError("Requested master repository has a master_repository of '" +
+ stringify(master_repository->params().master_repository->name()) + "', so it cannot "
+ "be used as a master repository");
+ }
+
+ tr1::shared_ptr<FSEntryCollection> profiles(new FSEntryCollection::Concrete);
+ if (m->end() != m->find("profiles"))
+ WhitespaceTokeniser::get_instance()->tokenise(m->find("profiles")->second,
+ create_inserter<FSEntry>(std::back_inserter(*profiles)));
+
+ if (profiles->empty())
+ {
+ if (master_repository)
+ std::copy(master_repository->params().profiles->begin(),
+ master_repository->params().profiles->end(), profiles->inserter());
+ else
+ throw PortageRepositoryConfigurationError("No profiles have been specified");
+ }
+
+ tr1::shared_ptr<FSEntryCollection> eclassdirs(new FSEntryCollection::Concrete);
+
+ if (m->end() != m->find("eclassdirs"))
+ WhitespaceTokeniser::get_instance()->tokenise(m->find("eclassdirs")->second,
+ create_inserter<FSEntry>(std::back_inserter(*eclassdirs)));
+
+ if (eclassdirs->empty())
+ {
+ if (master_repository)
+ std::copy(master_repository->params().eclassdirs->begin(),
+ master_repository->params().eclassdirs->end(), eclassdirs->inserter());
+
+ eclassdirs->push_back(location + "/eclass");
+ }
+
+ std::string distdir;
+ if (m->end() == m->find("distdir") || ((distdir = m->find("distdir")->second)).empty())
+ {
+ if (master_repository)
+ distdir = stringify(master_repository->params().distdir);
+ else
+ {
+ distdir = DistributionData::get_instance()->distribution_from_string(
+ env->default_distribution())->default_ebuild_distdir;
+ if (distdir.empty())
+ distdir = location + "/distfiles";
+ else if ('/' != distdir.at(0))
+ distdir = location + "/" + distdir;
+ }
+ }
+
+ std::string setsdir;
+ if (m->end() == m->find("setsdir") || ((setsdir = m->find("setsdir")->second)).empty())
+ setsdir = location + "/sets";
+
+ std::string securitydir;
+ if (m->end() == m->find("securitydir") || ((securitydir = m->find("securitydir")->second)).empty())
+ securitydir = location + "/metadata/glsa";
+
+ std::string newsdir;
+ if (m->end() == m->find("newsdir") || ((newsdir = m->find("newsdir")->second)).empty())
+ newsdir = location + "/metadata/news";
+
+ std::string cache;
+ if (m->end() == m->find("cache") || ((cache = m->find("cache")->second)).empty())
+ {
+ cache = location + "/metadata/cache";
+ if (! FSEntry(cache).exists())
+ cache = "/var/empty";
+ }
+
+ std::string write_cache;
+ if (m->end() == m->find("write_cache") || ((write_cache = m->find("write_cache")->second)).empty())
+ write_cache = DistributionData::get_instance()->distribution_from_string(
+ env->default_distribution())->default_ebuild_write_cache;
+
+ std::string eapi_when_unknown;
+ if (m->end() == m->find("eapi_when_unknown") || ((eapi_when_unknown = m->find("eapi_when_unknown")->second)).empty())
+ eapi_when_unknown = DistributionData::get_instance()->distribution_from_string(
+ env->default_distribution())->default_ebuild_eapi_when_unknown;
+
+ std::string eapi_when_unspecified;
+ if (m->end() == m->find("eapi_when_unspecified") || ((eapi_when_unspecified = m->find("eapi_when_unspecified")->second)).empty())
+ eapi_when_unspecified = DistributionData::get_instance()->distribution_from_string(
+ env->default_distribution())->default_ebuild_eapi_when_unspecified;
+
+ std::string names_cache;
+ if (m->end() == m->find("names_cache") || ((names_cache = m->find("names_cache")->second)).empty())
+ {
+ names_cache = DistributionData::get_instance()->distribution_from_string(
+ env->default_distribution())->default_ebuild_names_cache;
+ if (names_cache.empty())
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "The names_cache key is not set in '"
+ + repo_file + "'. You should read http://paludis.pioto.org/cachefiles.html and select an "
+ "appropriate value.");
+ names_cache = "/var/empty";
+ }
+ }
+
+ std::string sync;
+ if (m->end() != m->find("sync"))
+ sync = m->find("sync")->second;
+
+ std::string sync_options;
+ if (m->end() != m->find("sync_options"))
+ sync_options = m->find("sync_options")->second;
+
+ if (m->end() != m->find("sync_exclude"))
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "The sync_exclude key in '"
+ + repo_file + "' is deprecated in favour of sync_options = --exclude-from=");
+ if (! sync_options.empty())
+ sync_options += " ";
+ sync_options += "--exclude-from='" + m->find("sync_exclude")->second + "'";
+ }
+
+ std::string buildroot;
+ if (m->end() == m->find("buildroot") || ((buildroot = m->find("buildroot")->second)).empty())
+ buildroot = DistributionData::get_instance()->distribution_from_string(
+ env->default_distribution())->default_ebuild_build_root;
+
+ std::string layout;
+ if (m->end() == m->find("layout") || ((layout = m->find("layout")->second)).empty())
+ layout = DistributionData::get_instance()->distribution_from_string(
+ env->default_distribution())->default_ebuild_layout;
+
+ return tr1::shared_ptr<PortageRepository>(new PortageRepository(PortageRepositoryParams::create()
+ .entry_format("ebuild")
+ .layout(layout)
+ .environment(env)
+ .location(location)
+ .profiles(profiles)
+ .cache(cache)
+ .write_cache(write_cache)
+ .names_cache(names_cache)
+ .eclassdirs(eclassdirs)
+ .distdir(distdir)
+ .securitydir(securitydir)
+ .setsdir(setsdir)
+ .newsdir(newsdir)
+ .sync(sync)
+ .sync_options(sync_options)
+ .master_repository(master_repository)
+ .enable_destinations(false)
+ .write_bin_uri_prefix("")
+ .eapi_when_unknown(eapi_when_unknown)
+ .eapi_when_unspecified(eapi_when_unspecified)
+ .buildroot(buildroot)));
+}
+
+tr1::shared_ptr<Repository>
+paludis::make_ebuild_repository_wrapped(
+ Environment * const env,
+ tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m)
+{
+ return make_ebuild_repository(env, m);
+}
+
diff --git a/paludis/repositories/e/make_ebuild_repository.hh b/paludis/repositories/e/make_ebuild_repository.hh
new file mode 100644
index 000000000..259f8ad04
--- /dev/null
+++ b/paludis/repositories/e/make_ebuild_repository.hh
@@ -0,0 +1,50 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ *
+ * 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_PORTAGE_MAKE_EBUILD_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_PORTAGE_MAKE_EBUILD_REPOSITORY_HH 1
+
+#include <paludis/repositories/e/portage_repository.hh>
+
+namespace paludis
+{
+ /**
+ * Create an ebuild format repository.
+ *
+ * \see PortageRepository
+ * \ingroup grpportagerepository
+ */
+ tr1::shared_ptr<PortageRepository>
+ make_ebuild_repository(
+ Environment * const,
+ tr1::shared_ptr<const AssociativeCollection<std::string, std::string> >) PALUDIS_VISIBLE;
+
+ /**
+ * Create an ebuild format repository (wrapper for our virtual constructor).
+ *
+ * \see PortageRepository
+ * \ingroup grpportagerepository
+ */
+ tr1::shared_ptr<Repository>
+ make_ebuild_repository_wrapped(
+ Environment * const env,
+ tr1::shared_ptr<const AssociativeCollection<std::string, std::string> > m);
+}
+
+#endif
diff --git a/paludis/repositories/e/portage_repository.cc b/paludis/repositories/e/portage_repository.cc
new file mode 100644
index 000000000..3604d21ce
--- /dev/null
+++ b/paludis/repositories/e/portage_repository.cc
@@ -0,0 +1,938 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ *
+ * 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 "config.h"
+
+#include <paludis/repositories/e/portage_repository.hh>
+#include <paludis/repositories/e/portage_repository_profile.hh>
+#include <paludis/repositories/e/portage_repository_news.hh>
+#include <paludis/repositories/e/portage_repository_sets.hh>
+#include <paludis/repositories/e/portage_repository_exceptions.hh>
+#include <paludis/repositories/e/portage_repository_entries.hh>
+#include <paludis/repositories/e/use_desc.hh>
+#include <paludis/repositories/e/layout.hh>
+#include <paludis/repository_info.hh>
+
+#include <paludis/config_file.hh>
+#include <paludis/distribution.hh>
+#include <paludis/dep_spec.hh>
+#include <paludis/environment.hh>
+#include <paludis/hashed_containers.hh>
+#include <paludis/hook.hh>
+#include <paludis/match_package.hh>
+#include <paludis/query.hh>
+#include <paludis/repository_name_cache.hh>
+#include <paludis/syncer.hh>
+#include <paludis/eapi.hh>
+
+#include <paludis/util/collection_concrete.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/random.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/tr1_functional.hh>
+
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+
+#include <map>
+#include <functional>
+#include <algorithm>
+#include <vector>
+
+#include <strings.h>
+#include <ctype.h>
+
+/** \file
+ * Implementation of PortageRepository.
+ *
+ * \ingroup grpportagerepository
+ */
+
+using namespace paludis;
+
+typedef MakeHashedMap<QualifiedPackageName, std::list<tr1::shared_ptr<const PackageDepSpec> > >::Type RepositoryMaskMap;
+typedef MakeHashedMultiMap<std::string, std::string>::Type MirrorMap;
+typedef MakeHashedMap<QualifiedPackageName, tr1::shared_ptr<const PackageDepSpec> >::Type VirtualsMap;
+typedef std::list<RepositoryPortageInterface::ProfilesDescLine> ProfilesDesc;
+
+namespace paludis
+{
+ /**
+ * Implementation data for a PortageRepository.
+ *
+ * \ingroup grpportagerepository
+ */
+ template <>
+ struct Implementation<PortageRepository>
+ {
+ PortageRepository * const repo;
+ const PortageRepositoryParams params;
+
+ tr1::shared_ptr<RepositoryNameCache> names_cache;
+
+ mutable RepositoryMaskMap repo_mask;
+ mutable bool has_repo_mask;
+
+ mutable VirtualsMap our_virtuals;
+ const std::map<QualifiedPackageName, QualifiedPackageName> provide_map;
+
+ mutable tr1::shared_ptr<UseFlagNameCollection> arch_flags;
+
+ mutable bool has_mirrors;
+ mutable MirrorMap mirrors;
+
+ mutable bool has_profiles_desc;
+ mutable ProfilesDesc profiles_desc;
+ mutable std::list<tr1::shared_ptr<UseDesc> > use_desc;
+
+ mutable tr1::shared_ptr<PortageRepositoryProfile> profile_ptr;
+ mutable tr1::shared_ptr<PortageRepositoryNews> news_ptr;
+ mutable tr1::shared_ptr<PortageRepositorySets> sets_ptr;
+ mutable tr1::shared_ptr<PortageRepositoryEntries> entries_ptr;
+ mutable tr1::shared_ptr<Layout> layout;
+
+ Implementation(PortageRepository * const, const PortageRepositoryParams &);
+ ~Implementation();
+
+ void need_profiles() const;
+ void need_profiles_desc() const;
+ };
+
+ Implementation<PortageRepository>::Implementation(PortageRepository * const r,
+ const PortageRepositoryParams & p) :
+ repo(r),
+ params(p),
+ names_cache(new RepositoryNameCache(p.names_cache, r)),
+ has_repo_mask(false),
+ has_mirrors(false),
+ has_profiles_desc(false),
+ sets_ptr(new PortageRepositorySets(params.environment, r, p)),
+ entries_ptr(PortageRepositoryEntriesMaker::get_instance()->find_maker(
+ params.entry_format)(params.environment, r, p)),
+ layout(LayoutMaker::get_instance()->find_maker(
+ params.layout)(r, params.location, entries_ptr, params.master_repository ?
+ make_shared_ptr(new FSEntry(params.master_repository->params().location)) :
+ tr1::shared_ptr<FSEntry>()))
+ {
+ }
+
+ Implementation<PortageRepository>::~Implementation()
+ {
+ }
+
+ void
+ Implementation<PortageRepository>::need_profiles() const
+ {
+ if (profile_ptr)
+ return;
+
+ profile_ptr.reset(new PortageRepositoryProfile(
+ params.environment, repo, repo->name(), *params.profiles,
+ EAPIData::get_instance()->eapi_from_string(params.eapi_when_unknown)->supported->ebuild_options->want_arch_var));
+ }
+
+ void
+ Implementation<PortageRepository>::need_profiles_desc() const
+ {
+ if (has_profiles_desc)
+ return;
+
+ Context context("When loading profiles.desc:");
+
+ bool found_one(false);
+ tr1::shared_ptr<const FSEntryCollection> profiles_desc_files(layout->profiles_desc_files());
+ for (FSEntryCollection::Iterator p(profiles_desc_files->begin()), p_end(profiles_desc_files->end()) ;
+ p != p_end ; ++p)
+ {
+ if (! p->exists())
+ continue;
+
+ found_one = true;
+
+ LineConfigFile f(*p, LineConfigFileOptions());
+ for (LineConfigFile::Iterator line(f.begin()), line_end(f.end()) ; line != line_end ; ++line)
+ {
+ std::vector<std::string> tokens;
+ WhitespaceTokeniser::get_instance()->tokenise(*line,
+ std::back_inserter(tokens));
+ if (tokens.size() < 3)
+ continue;
+
+ FSEntryCollection::Concrete profiles;
+ profiles.push_back(layout->profiles_base_dir() / tokens.at(1));
+ profiles_desc.push_back(RepositoryPortageInterface::ProfilesDescLine::create()
+ .arch(tokens.at(0))
+ .path(*profiles.begin())
+ .status(tokens.at(2))
+ .profile(tr1::shared_ptr<PortageRepositoryProfile>(new PortageRepositoryProfile(
+ params.environment, repo, repo->name(), profiles,
+ EAPIData::get_instance()->eapi_from_string(
+ params.eapi_when_unknown)->supported->ebuild_options->want_arch_var))));
+ }
+ }
+
+ if (! found_one)
+ throw PortageRepositoryConfigurationError("No profiles.desc found");
+
+ has_profiles_desc = true;
+ }
+}
+
+namespace
+{
+ RepositoryName
+ fetch_repo_name(const FSEntry & tree_root)
+ {
+ try
+ {
+ do
+ {
+ FSEntry name_file(tree_root);
+ name_file /= "profiles";
+ name_file /= "repo_name";
+
+ if (! name_file.is_regular_file())
+ break;
+
+ LineConfigFile f(name_file, LineConfigFileOptions());
+ if (f.begin() == f.end())
+ break;
+ return RepositoryName(*f.begin());
+
+ } while (false);
+ }
+ catch (...)
+ {
+ }
+
+ std::string modified_location(tree_root.basename());
+ std::replace(modified_location.begin(), modified_location.end(), '/', '-');
+
+ Log::get_instance()->message(ll_qa, lc_no_context, "Couldn't open repo_name file in '"
+ + stringify(tree_root) + "/profiles/', falling back to generated name 'x-" + modified_location +
+ "' (ignore this message if you have yet to sync this repository).");
+
+ return RepositoryName("x-" + modified_location);
+ }
+}
+
+PortageRepository::PortageRepository(const PortageRepositoryParams & p) :
+ Repository(fetch_repo_name(p.location),
+ RepositoryCapabilities::create()
+ .mask_interface(this)
+ .installable_interface(this)
+ .installed_interface(0)
+ .sets_interface(this)
+ .syncable_interface(this)
+ .uninstallable_interface(0)
+ .use_interface(this)
+ .world_interface(0)
+ .environment_variable_interface(this)
+ .mirrors_interface(this)
+ .virtuals_interface(DistributionData::get_instance()->distribution_from_string(
+ p.environment->default_distribution())->support_old_style_virtuals ? this : 0)
+ .provides_interface(0)
+ .config_interface(0)
+ .destination_interface(p.enable_destinations ? this : 0)
+ .licenses_interface(this)
+ .make_virtuals_interface(0)
+ .portage_interface(this)
+ .pretend_interface(this)
+ .hook_interface(this),
+ p.entry_format),
+ PrivateImplementationPattern<PortageRepository>(new Implementation<PortageRepository>(this, p))
+{
+ // the info_vars and info_pkgs info is only added on demand, since it's
+ // fairly slow to calculate.
+ tr1::shared_ptr<RepositoryInfoSection> config_info(new RepositoryInfoSection("Configuration information"));
+
+ config_info->add_kv("entry_format", _imp->params.entry_format);
+ config_info->add_kv("layout", _imp->params.layout);
+ config_info->add_kv("location", stringify(_imp->params.location));
+ config_info->add_kv("profiles", join(_imp->params.profiles->begin(),
+ _imp->params.profiles->end(), " "));
+ config_info->add_kv("eclassdirs", join(_imp->params.eclassdirs->begin(),
+ _imp->params.eclassdirs->end(), " "));
+ config_info->add_kv("cache", stringify(_imp->params.cache));
+ config_info->add_kv("write_cache", stringify(_imp->params.write_cache));
+ config_info->add_kv("names_cache", stringify(_imp->params.names_cache));
+ config_info->add_kv("distdir", stringify(_imp->params.distdir));
+ config_info->add_kv("securitydir", stringify(_imp->params.securitydir));
+ config_info->add_kv("setsdir", stringify(_imp->params.setsdir));
+ config_info->add_kv("newsdir", stringify(_imp->params.newsdir));
+ config_info->add_kv("format", _imp->params.entry_format);
+ config_info->add_kv("layout", _imp->params.layout);
+ config_info->add_kv("buildroot", stringify(_imp->params.buildroot));
+ config_info->add_kv("sync", _imp->params.sync);
+ config_info->add_kv("sync_options", _imp->params.sync_options);
+ config_info->add_kv("eapi_when_unknown", _imp->params.eapi_when_unknown);
+ config_info->add_kv("eapi_when_unspecified", _imp->params.eapi_when_unspecified);
+ if (_imp->params.master_repository)
+ config_info->add_kv("master_repository", stringify(_imp->params.master_repository->name()));
+
+ _info->add_section(config_info);
+}
+
+PortageRepository::~PortageRepository()
+{
+}
+
+bool
+PortageRepository::do_has_category_named(const CategoryNamePart & c) const
+{
+ return _imp->layout->has_category_named(c);
+}
+
+bool
+PortageRepository::do_has_package_named(const QualifiedPackageName & q) const
+{
+ return _imp->layout->has_package_named(q);
+}
+
+tr1::shared_ptr<const CategoryNamePartCollection>
+PortageRepository::do_category_names() const
+{
+ return _imp->layout->category_names();
+}
+
+tr1::shared_ptr<const QualifiedPackageNameCollection>
+PortageRepository::do_package_names(const CategoryNamePart & c) const
+{
+ return _imp->layout->package_names(c);
+}
+
+tr1::shared_ptr<const PackageIDSequence>
+PortageRepository::do_package_ids(const QualifiedPackageName & n) const
+{
+ return _imp->layout->package_ids(n);
+}
+
+bool
+PortageRepository::do_query_repository_masks(const PackageID & id) const
+{
+ if (! _imp->has_repo_mask)
+ {
+ Context context("When querying repository mask for '" + stringify(id) + "':");
+
+ tr1::shared_ptr<const FSEntryCollection> repository_mask_files(_imp->layout->repository_mask_files());
+ for (FSEntryCollection::Iterator p(repository_mask_files->begin()), p_end(repository_mask_files->end()) ;
+ p != p_end ; ++p)
+ {
+ Context context_local("When reading '" + stringify(*p) + "':");
+
+ if (p->exists())
+ {
+ LineConfigFile ff(*p, LineConfigFileOptions());
+ for (LineConfigFile::Iterator line(ff.begin()), line_end(ff.end()) ;
+ line != line_end ; ++line)
+ {
+ try
+ {
+ tr1::shared_ptr<const PackageDepSpec> a(new PackageDepSpec(*line, pds_pm_eapi_0));
+ if (a->package_ptr())
+ _imp->repo_mask[*a->package_ptr()].push_back(a);
+ else
+ Log::get_instance()->message(ll_warning, lc_context, "Loading package mask spec '"
+ + stringify(*line) + "' failed because specification does not restrict to a "
+ "unique package");
+ }
+ catch (const Exception & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Loading package mask spec '"
+ + stringify(*line) + "' failed due to exception '" + e.message() + "' ("
+ + e.what() + ")");
+ }
+ }
+ }
+ }
+
+ _imp->has_repo_mask = true;
+ }
+
+ RepositoryMaskMap::iterator r(_imp->repo_mask.find(id.name()));
+ if (_imp->repo_mask.end() == r)
+ return false;
+ else
+ for (IndirectIterator<std::list<tr1::shared_ptr<const PackageDepSpec> >::const_iterator, const PackageDepSpec>
+ k(r->second.begin()), k_end(r->second.end()) ; k != k_end ; ++k)
+ if (match_package(*_imp->params.environment, *k, id))
+ return true;
+
+ return false;
+}
+
+bool
+PortageRepository::do_query_profile_masks(const PackageID & id) const
+{
+ _imp->need_profiles();
+ return _imp->profile_ptr->profile_masked(id);
+}
+
+UseFlagState
+PortageRepository::do_query_use(const UseFlagName & f, const PackageID & e) const
+{
+ _imp->need_profiles();
+ return _imp->profile_ptr->use_state_ignoring_masks(f, e);
+}
+
+bool
+PortageRepository::do_query_use_mask(const UseFlagName & u, const PackageID & e) const
+{
+ _imp->need_profiles();
+ return _imp->profile_ptr->use_masked(u, e) ||
+ (arch_flags()->end() != arch_flags()->find(u) && use_enabled != do_query_use(u, e));
+}
+
+bool
+PortageRepository::do_query_use_force(const UseFlagName & u, const PackageID & e) const
+{
+ _imp->need_profiles();
+ return _imp->profile_ptr->use_forced(u, e);
+}
+
+tr1::shared_ptr<const UseFlagNameCollection>
+PortageRepository::do_arch_flags() const
+{
+ if (! _imp->arch_flags)
+ {
+ Context context("When loading arch list:");
+ _imp->arch_flags.reset(new UseFlagNameCollection::Concrete);
+
+ bool found_one(false);
+ tr1::shared_ptr<const FSEntryCollection> arch_list_files(_imp->layout->arch_list_files());
+ for (FSEntryCollection::Iterator p(arch_list_files->begin()), p_end(arch_list_files->end()) ;
+ p != p_end ; ++p)
+ {
+ if (! p->exists())
+ continue;
+
+ LineConfigFile archs(*p, LineConfigFileOptions());
+ std::copy(archs.begin(), archs.end(), create_inserter<UseFlagName>(_imp->arch_flags->inserter()));
+ found_one = true;
+ }
+
+ if (! found_one)
+ {
+ Log::get_instance()->message(ll_qa, lc_no_context, "Couldn't find arch.list file for repository '"
+ + stringify(name()) + "', arch flags may incorrectly show up as unmasked");
+ }
+ }
+
+ return _imp->arch_flags;
+}
+
+tr1::shared_ptr<FSEntry>
+PortageRepository::do_license_exists(const std::string & license) const
+{
+ tr1::shared_ptr<FSEntry> p;
+
+ if (_imp->params.master_repository)
+ {
+ FSEntry l(_imp->params.master_repository->params().location / "licenses" / license);
+ if (l.exists() && l.is_regular_file_or_symlink_to_regular_file())
+ p.reset(new FSEntry(l));
+ }
+
+ FSEntry l(_imp->params.location / "licenses" / license);
+ if (l.exists() && l.is_regular_file_or_symlink_to_regular_file())
+ p.reset(new FSEntry(l));
+
+ return p;
+}
+
+void
+PortageRepository::need_mirrors() const
+{
+ if (! _imp->has_mirrors)
+ {
+ bool found_one(false);
+ tr1::shared_ptr<const FSEntryCollection> mirror_files(_imp->layout->mirror_files());
+ for (FSEntryCollection::Iterator p(mirror_files->begin()), p_end(mirror_files->end()) ;
+ p != p_end ; ++p)
+ {
+ if (p->exists())
+ {
+ LineConfigFile mirrors(*p, LineConfigFileOptions());
+ for (LineConfigFile::Iterator line(mirrors.begin()) ; line != mirrors.end() ; ++line)
+ {
+ std::vector<std::string> entries;
+ WhitespaceTokeniser::get_instance()->tokenise(*line, std::back_inserter(entries));
+ if (! entries.empty())
+ {
+ /* pick up to five random mirrors only */
+ static Random r;
+ std::random_shuffle(next(entries.begin()), entries.end(), r);
+ if (entries.size() > 6)
+ entries.resize(6);
+ for (std::vector<std::string>::const_iterator e(next(entries.begin())),
+ e_end(entries.end()) ; e != e_end ; ++e)
+ _imp->mirrors.insert(std::make_pair(entries.at(0), *e));
+ }
+ }
+ }
+
+ found_one = true;
+ }
+
+ if (! found_one)
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "No thirdpartymirrors file found in '"
+ + stringify(_imp->params.location / "profiles") + "', so mirror:// SRC_URI "
+ "components cannot be fetched");
+
+ _imp->has_mirrors = true;
+ }
+}
+
+void
+PortageRepository::do_install(const tr1::shared_ptr<const PackageID> & id,
+ const InstallOptions & o) const
+{
+ _imp->need_profiles();
+ _imp->entries_ptr->install(id, o, _imp->profile_ptr);
+}
+
+bool
+PortageRepository::do_pretend(const tr1::shared_ptr<const PackageID> & id) const
+{
+ _imp->need_profiles();
+ return _imp->entries_ptr->pretend(id, _imp->profile_ptr);
+}
+
+tr1::shared_ptr<SetSpecTree::ConstItem>
+PortageRepository::do_package_set(const SetName & s) const
+{
+ if (s.data() == "system")
+ {
+ _imp->need_profiles();
+ return _imp->profile_ptr->system_packages();
+ }
+
+ return _imp->sets_ptr->package_set(s);
+}
+
+tr1::shared_ptr<const SetNameCollection>
+PortageRepository::sets_list() const
+{
+ return _imp->sets_ptr->sets_list();
+}
+
+bool
+PortageRepository::do_sync() const
+{
+ Context context("When syncing repository '" + stringify(name()) + "':");
+
+ if (_imp->params.sync.empty())
+ return false;
+
+ std::list<std::string> sync_list;
+ WhitespaceTokeniser::get_instance()->tokenise(_imp->params.sync, std::back_inserter(sync_list));
+
+ bool ok(false);
+ for (std::list<std::string>::const_iterator s(sync_list.begin()),
+ s_end(sync_list.end()) ; s != s_end ; ++s)
+ {
+ DefaultSyncer syncer(SyncerParams::create()
+ .environment(_imp->params.environment)
+ .local(stringify(_imp->params.location))
+ .remote(*s));
+ SyncOptions opts(_imp->params.sync_options);
+ try
+ {
+ syncer.sync(opts);
+ }
+ catch (const SyncFailedError & e)
+ {
+ continue;
+ }
+
+ ok = true;
+ break;
+ }
+
+ if (! ok)
+ throw SyncFailedError(stringify(_imp->params.location), _imp->params.sync);
+
+ return true;
+}
+
+void
+PortageRepository::invalidate()
+{
+ _imp.reset(new Implementation<PortageRepository>(this, _imp->params));
+}
+
+void
+PortageRepository::update_news() const
+{
+ if (! _imp->news_ptr)
+ _imp->news_ptr.reset(new PortageRepositoryNews(_imp->params.environment, this, _imp->params));
+
+ _imp->news_ptr->update_news();
+}
+
+const tr1::shared_ptr<const Layout>
+PortageRepository::layout() const
+{
+ return _imp->layout;
+}
+
+std::string
+PortageRepository::get_environment_variable(
+ const tr1::shared_ptr<const PackageID> & for_package,
+ const std::string & var) const
+{
+ Context context("When fetching environment variable '" + var + "' from repository '"
+ + stringify(name()) + "':");
+
+ _imp->need_profiles();
+
+ return _imp->entries_ptr->get_environment_variable(for_package, var, _imp->profile_ptr);
+}
+
+tr1::shared_ptr<const RepositoryInfo>
+PortageRepository::info(bool verbose) const
+{
+ tr1::shared_ptr<const RepositoryInfo> result_non_verbose(Repository::info(verbose));
+ if (! verbose)
+ return result_non_verbose;
+
+ tr1::shared_ptr<RepositoryInfo> result(new RepositoryInfo);
+
+ for (RepositoryInfo::SectionIterator s(result_non_verbose->begin_sections()),
+ s_end(result_non_verbose->end_sections()) ; s != s_end ; ++s)
+ result->add_section(*s);
+
+ // don't inherit from master_repository, just causes clutter
+ std::set<std::string> info_pkgs;
+ if ((_imp->layout->info_packages_file(_imp->params.location / "profiles")).exists())
+ {
+ LineConfigFile vars(_imp->layout->info_packages_file(_imp->params.location / "profiles"), LineConfigFileOptions());
+ info_pkgs.insert(vars.begin(), vars.end());
+ }
+
+ if (! info_pkgs.empty())
+ {
+ tr1::shared_ptr<RepositoryInfoSection> package_info(new RepositoryInfoSection("Package information"));
+ for (std::set<std::string>::const_iterator i(info_pkgs.begin()),
+ i_end(info_pkgs.end()) ; i != i_end ; ++i)
+ {
+ tr1::shared_ptr<const PackageIDSequence> q(
+ _imp->params.environment->package_database()->query(
+ query::Matches(PackageDepSpec(*i, pds_pm_eapi_0)) &
+ query::InstalledAtRoot(_imp->params.environment->root()),
+ qo_order_by_version));
+ if (q->empty())
+ package_info->add_kv(*i, "(none)");
+ else
+ {
+ using namespace tr1::placeholders;
+ std::set<VersionSpec> versions;
+ std::copy(q->begin(), q->end(),
+ transform_inserter(std::inserter(versions, versions.begin()),
+ tr1::bind<const VersionSpec>(tr1::mem_fn(&PackageID::version), _1)));
+ package_info->add_kv(*i, join(versions.begin(), versions.end(), ", "));
+ }
+ }
+
+ result->add_section(package_info);
+ }
+
+#if 0
+ // don't inherit from master_repository, just causes clutter
+ std::set<std::string> info_vars;
+ if (_imp->layout->info_variables_file(_imp->params.location / "profiles").exists())
+ {
+ LineConfigFile vars(_imp->layout->info_variables_file(_imp->params.location / "profiles"), LineConfigFileOptions());
+ info_vars.insert(vars.begin(), vars.end());
+ }
+
+ if (! info_vars.empty() && ! info_pkgs.empty() &&
+ ! package_ids(QualifiedPackageName(*info_pkgs.begin()))->empty())
+ {
+ PackageDatabaseEntry e(QualifiedPackageName(*info_pkgs.begin()),
+ *package_ids(QualifiedPackageName(*info_pkgs.begin()))->last(),
+ name());
+ tr1::shared_ptr<RepositoryInfoSection> variable_info(new RepositoryInfoSection("Variable information"));
+ for (std::set<std::string>::const_iterator i(info_vars.begin()),
+ i_end(info_vars.end()) ; i != i_end ; ++i)
+ variable_info->add_kv(*i, get_environment_variable(e, *i));
+
+ result->add_section(variable_info);
+ }
+ else if (! info_vars.empty())
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Skipping info_vars for '" + stringify(name()) +
+ "' because info_pkgs is not usable");
+#endif
+
+ return result;
+}
+
+std::string
+PortageRepository::profile_variable(const std::string & s) const
+{
+ _imp->need_profiles();
+
+ return _imp->profile_ptr->environment_variable(s);
+}
+
+PortageRepository::MirrorsIterator
+PortageRepository::begin_mirrors(const std::string & s) const
+{
+ need_mirrors();
+ return MirrorsIterator(_imp->mirrors.equal_range(s).first);
+}
+
+PortageRepository::MirrorsIterator
+PortageRepository::end_mirrors(const std::string & s) const
+{
+ need_mirrors();
+ return MirrorsIterator(_imp->mirrors.equal_range(s).second);
+}
+
+tr1::shared_ptr<const PortageRepository::VirtualsSequence>
+PortageRepository::virtual_packages() const
+{
+ Context context("When loading virtual packages for repository '" +
+ stringify(name()) + "'");
+
+ _imp->need_profiles();
+
+ tr1::shared_ptr<VirtualsSequence> result(new VirtualsSequence::Concrete);
+
+ for (PortageRepositoryProfile::VirtualsIterator i(_imp->profile_ptr->begin_virtuals()),
+ i_end(_imp->profile_ptr->end_virtuals()) ; i != i_end ; ++i)
+ result->push_back(RepositoryVirtualsEntry::create()
+ .provided_by_spec(i->second)
+ .virtual_name(i->first));
+
+ return result;
+}
+
+tr1::shared_ptr<const UseFlagNameCollection>
+PortageRepository::do_use_expand_flags() const
+{
+ _imp->need_profiles();
+
+ tr1::shared_ptr<UseFlagNameCollection> result(new UseFlagNameCollection::Concrete);
+ for (PortageRepositoryProfile::UseExpandIterator i(_imp->profile_ptr->begin_use_expand()),
+ i_end(_imp->profile_ptr->end_use_expand()) ; i != i_end ; ++i)
+ {
+ std::list<std::string> values;
+ WhitespaceTokeniser::get_instance()->tokenise(_imp->profile_ptr->environment_variable(
+ stringify(*i)), std::back_inserter(values));
+ for (std::list<std::string>::const_iterator j(values.begin()), j_end(values.end()) ;
+ j != j_end ; ++j)
+ {
+ std::string f(stringify(*i) + "_" + *j), lower_f;
+ std::transform(f.begin(), f.end(), std::back_inserter(lower_f), &::tolower);
+ result->insert(UseFlagName(lower_f));
+ }
+ }
+
+ return result;
+}
+
+tr1::shared_ptr<const UseFlagNameCollection>
+PortageRepository::do_use_expand_prefixes() const
+{
+ _imp->need_profiles();
+
+ tr1::shared_ptr<UseFlagNameCollection> result(new UseFlagNameCollection::Concrete);
+ for (PortageRepositoryProfile::UseExpandIterator i(_imp->profile_ptr->begin_use_expand()),
+ i_end(_imp->profile_ptr->end_use_expand()) ; i != i_end ; ++i)
+ {
+ std::string lower_i;
+ std::transform(i->data().begin(), i->data().end(), std::back_inserter(lower_i), &::tolower);
+ result->insert(UseFlagName(lower_i));
+ }
+
+ return result;
+}
+
+tr1::shared_ptr<const UseFlagNameCollection>
+PortageRepository::do_use_expand_hidden_prefixes() const
+{
+ _imp->need_profiles();
+
+ tr1::shared_ptr<UseFlagNameCollection> result(new UseFlagNameCollection::Concrete);
+ for (PortageRepositoryProfile::UseExpandIterator i(_imp->profile_ptr->begin_use_expand_hidden()),
+ i_end(_imp->profile_ptr->end_use_expand_hidden()) ; i != i_end ; ++i)
+ {
+ std::string lower_i;
+ std::transform(i->data().begin(), i->d