aboutsummaryrefslogtreecommitdiff
path: root/0.26.0_alpha1/paludis/repositories
diff options
context:
space:
mode:
Diffstat (limited to '0.26.0_alpha1/paludis/repositories')
-rw-r--r--0.26.0_alpha1/paludis/repositories/Makefile.am32
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/Makefile.am160
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran/Makefile.am21
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran/cran.bash151
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran_dep_parser.cc88
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran_dep_parser.hh35
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran_dep_parser_TEST.cc63
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository.cc662
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository.hh156
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository.sr25
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository_TEST.cc55
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository_TEST_cleanup.sh9
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository_TEST_setup.sh7
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran_package_id.cc531
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran_package_id.hh94
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran_repository.cc503
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran_repository.hh137
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran_repository.sr28
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/cran_repository_TEST.cc79
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/cran/cran_repository_TEST_cleanup.sh8
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/cran/cran_repository_TEST_setup.sh57
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/dep_spec_pretty_printer.cc130
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/dep_spec_pretty_printer.hh90
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/description_file.cc113
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/description_file.hh49
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/description_file_TEST.cc49
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/keys.cc168
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/keys.hh137
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/masks.cc70
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/masks.hh45
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/normalise.cc40
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/normalise.hh35
-rw-r--r--0.26.0_alpha1/paludis/repositories/cran/registration.cc42
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/Makefile.am521
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/aa_visitor.cc75
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/aa_visitor.hh80
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/aa_visitor_TEST.cc47
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/check_fetched_files_visitor.cc399
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/check_fetched_files_visitor.hh77
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/dep_lexer.cc117
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/dep_lexer.hh129
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/dep_lexer_TEST.cc244
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/dep_parser-fwd.hh39
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/dep_parser.cc835
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/dep_parser.hh124
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/dep_parser.se23
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/dep_parser_TEST.cc352
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/dep_spec_pretty_printer.cc402
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/dep_spec_pretty_printer.hh129
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/dep_spec_pretty_printer_TEST.cc103
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_key.cc1229
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_key.hh356
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_mask.cc162
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_mask.hh71
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository.cc1258
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository.hh245
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_TEST.cc1219
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/e_repository_TEST_cleanup.sh10
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/e_repository_TEST_setup.sh689
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_entries.cc52
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_entries.hh156
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_exceptions.cc29
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_exceptions.hh53
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_id.cc33
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_id.hh42
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_mask_file.cc97
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_mask_file.hh68
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_news.cc294
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_news.hh131
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_params.cc32
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_params.hh47
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_params.se23
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_params.sr45
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_profile.cc807
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_profile.hh133
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_profile_file.cc145
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_profile_file.hh70
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_sets.cc353
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_sets.hh76
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/e_repository_sets_TEST.cc185
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/e_repository_sets_TEST_cleanup.sh10
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/e_repository_sets_TEST_setup.sh214
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/eapi-fwd.hh39
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/eapi.cc271
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/eapi.hh96
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/eapi.sr202
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/eapi_phase.cc116
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/eapi_phase.hh94
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/eapis/0.conf155
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/eapis/1.conf156
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/eapis/Makefile.am26
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/eapis/exheres-0.conf174
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/eapis/paludis-1.conf157
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebin.cc306
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebin.hh202
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebin.se25
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebin.sr89
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebin_entries.cc480
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebin_entries.hh82
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild.cc809
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild.hh393
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild.sr204
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/0/Makefile.am33
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/1/Makefile.am35
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/1/src_compile.bash62
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/Makefile.am72
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/build_functions.bash105
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/builtin_infovars.bash54
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/builtin_init.bash95
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/builtin_initbin.bash90
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/builtin_loadenv.bash48
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/builtin_metadata.bash41
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/builtin_prepare.bash49
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/builtin_saveenv.bash55
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/builtin_strip.bash80
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/builtin_tidyup.bash43
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/builtin_unpackbin.bash40
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/builtin_variable.bash23
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/die_functions.bash59
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/ebuild.bash447
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/echo_functions.bash.in238
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/echo_functions_TEST.bash45
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/eclass_functions.bash82
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/exheres-0/Makefile.am38
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/exheres-0/builtin_fetch.bash138
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/exheres-0/echo_functions.bash.in248
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/exheres-0/list_functions.bash90
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/exheres-0/pkg_nofetch.bash51
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/exheres-0/portage_stubs.bash62
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/exlib_functions.bash77
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/install_functions.bash109
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/kernel_functions.bash59
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/kernel_functions_TEST.bash41
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/list_functions.bash70
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/list_functions_TEST.bash74
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/multilib_functions.bash66
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/pkg_config.bash58
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/pkg_info.bash50
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/pkg_nofetch.bash51
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/pkg_postinst.bash58
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/pkg_postrm.bash59
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/pkg_preinst.bash58
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/pkg_prerm.bash58
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/pkg_pretend.bash47
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/pkg_setup.bash58
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/portage_stubs.bash94
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/run_test.bash48
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/sandbox.bash42
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/src_compile.bash61
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/src_install.bash58
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/src_test.bash86
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/src_unpack.bash54
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/usage_error.bash31
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/utils/Makefile.am113
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/awk19
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/utils/awk_TEST.bash47
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/canonicalise6
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/dobin48
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/utils/dobin_TEST.bash70
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/doconfd32
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/dodir34
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/dodoc50
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/doenvd32
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/doexe58
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/dohard34
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/dohtml122
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/doinfo50
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/doinitd32
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/doins89
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/dolib62
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/dolib.a.in27
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/dolib.so.in26
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/doman75
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/domo54
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/donewins41
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/dosbin45
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/dosed52
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/dosym42
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/emake22
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/utils/exheres-0/Makefile.am61
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/exheres-0/banned_in_eapi_exheres-028
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/exheres-0/dodoc64
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/exheres-0/emake29
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/exheres-0/unpack134
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/fowners24
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/fperms24
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/make19
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/utils/make_TEST.bash41
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/newbin38
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/newconfd38
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/newdoc38
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/newenvd38
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/newexe38
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/newinitd38
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/newins38
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/newlib.a.in38
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/newlib.so.in38
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/newman38
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/newsbin38
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/patch19
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/utils/patch_TEST.bash75
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/prep.in24
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/utils/run_test.bash62
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/sed19
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild/utils/sed_TEST.bash46
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/unpack137
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/wrapped_getfsize18
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/wrapped_getfsize_TEST.bash44
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/wrapped_getmtime19
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/utils/wrapped_ldconfig19
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/ebuild/write_vdb_entry.bash111
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild_entries.cc848
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild_entries.hh99
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild_flat_metadata_cache.cc272
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild_flat_metadata_cache.hh70
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild_id.cc894
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/ebuild_id.hh125
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/eclass_mtimes.cc77
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/eclass_mtimes.hh55
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/exheres_layout.cc532
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/exheres_layout.hh122
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/fetch_visitor.cc245
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/fetch_visitor.hh71
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/fetch_visitor_TEST.cc75
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/fetch_visitor_TEST_cleanup.sh9
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/fetch_visitor_TEST_setup.sh13
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/glsa.cc260
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/glsa.hh175
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/glsa.sr19
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/layout.cc85
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/layout.hh183
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/make_ebin_repository.cc218
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/make_ebin_repository.hh52
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/make_ebuild_repository.cc251
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/make_ebuild_repository.hh51
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/manifest2_entry.sr18
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/manifest2_reader.cc155
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/manifest2_reader.hh84
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/Makefile.am154
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/eapi_supported.cc47
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/eapi_supported.hh39
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/extractors.cc407
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/extractors.conf7
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/extractors.hh40
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/extractors_TEST.cc154
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/homepage_key.cc110
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/homepage_key.hh39
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/qa.cc63
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/qa_checks.cc110
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/qa_checks.hh89
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/qa_checks_group.cc118
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/qa_checks_group.hh56
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/qa_controller.cc277
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/qa_controller.hh68
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/short_description_key.cc66
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/short_description_key.hh39
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/spec_keys.cc431
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/spec_keys.hh40
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/spec_keys_TEST.cc208
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/spec_keys_pds_blacklist.DEPEND.conf2
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/spec_keys_pds_blacklist.PDEPEND.conf0
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/spec_keys_pds_blacklist.PROVIDE.conf1
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/spec_keys_pds_blacklist.RDEPEND.conf16
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/spec_keys_pds_blacklist.SDEPEND.conf0
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/stray_files.cc92
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/stray_files.hh47
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/stray_files_TEST.cc40
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/test_extras.cc26
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/visibility.cc367
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/visibility.hh44
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/qa/visibility_TEST.cc113
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/qa/visibility_TEST_cleanup.sh9
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/qa/visibility_TEST_setup.sh62
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/registration.cc70
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/source_uri_finder.cc215
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/source_uri_finder.hh68
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/source_uri_finder_TEST.cc104
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/traditional.exclude4
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/traditional_layout.cc557
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/traditional_layout.hh126
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/use_desc.cc96
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/use_desc.hh59
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/vdb_id.cc721
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/vdb_id.hh97
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/vdb_merger.cc267
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/vdb_merger.hh73
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/vdb_merger.sr31
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/vdb_merger_TEST.cc181
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/vdb_merger_TEST_cleanup.sh9
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/vdb_merger_TEST_setup.sh66
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/vdb_repository.cc1317
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/vdb_repository.hh275
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/vdb_repository.sr28
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/vdb_repository_TEST.cc247
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/vdb_repository_TEST_cleanup.sh11
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/vdb_repository_TEST_setup.sh35
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/vdb_unmerger.cc399
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/vdb_unmerger.hh98
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/vdb_unmerger.sr30
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/vdb_unmerger_TEST.cc389
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/vdb_unmerger_TEST_cleanup.sh9
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/vdb_unmerger_TEST_setup.sh100
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/xml_things.cc219
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/xml_things.hh30
-rw-r--r--0.26.0_alpha1/paludis/repositories/e/xml_things_TEST.cc93
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/xml_things_TEST_cleanup.sh11
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/e/xml_things_TEST_setup.sh115
-rw-r--r--0.26.0_alpha1/paludis/repositories/fake/Makefile.am87
-rw-r--r--0.26.0_alpha1/paludis/repositories/fake/fake_installed_repository.cc177
-rw-r--r--0.26.0_alpha1/paludis/repositories/fake/fake_installed_repository.hh74
-rw-r--r--0.26.0_alpha1/paludis/repositories/fake/fake_installed_repository_TEST.cc41
-rw-r--r--0.26.0_alpha1/paludis/repositories/fake/fake_package_id.cc940
-rw-r--r--0.26.0_alpha1/paludis/repositories/fake/fake_package_id.hh236
-rw-r--r--0.26.0_alpha1/paludis/repositories/fake/fake_repository.cc173
-rw-r--r--0.26.0_alpha1/paludis/repositories/fake/fake_repository.hh72
-rw-r--r--0.26.0_alpha1/paludis/repositories/fake/fake_repository_TEST.cc42
-rw-r--r--0.26.0_alpha1/paludis/repositories/fake/fake_repository_base.cc257
-rw-r--r--0.26.0_alpha1/paludis/repositories/fake/fake_repository_base.hh162
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/Makefile.am156
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/exceptions.cc29
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/exceptions.hh50
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/gem_specification-fwd.hh32
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/gem_specification.cc680
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/gem_specification.hh127
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/gem_specification_TEST.cc162
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/gem_specifications.cc214
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/gem_specifications.hh73
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/gem_specifications_TEST.cc41
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/gems/gems.bash55
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/gems_repository.cc310
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/gems_repository.hh84
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/gems_repository_TEST.cc52
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/gems/gems_repository_TEST_cleanup.sh9
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/gems/gems_repository_TEST_setup.sh6
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/installed_gems_repository.cc344
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/installed_gems_repository.hh104
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/installed_gems_repository_TEST.cc50
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/gems/installed_gems_repository_TEST_cleanup.sh9
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/gems/installed_gems_repository_TEST_setup.sh10
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/params-fwd.hh32
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/params.cc26
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/params.hh41
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/params.sr28
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/registration.cc100
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/yaml-fwd.hh38
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/yaml.cc389
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/yaml.hh249
-rw-r--r--0.26.0_alpha1/paludis/repositories/gems/yaml_TEST.cc186
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/Makefile.am176
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/exceptions.cc29
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/exceptions.hh38
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/installed_unpackaged_id.cc589
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/installed_unpackaged_id.hh95
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/installed_unpackaged_repository.cc374
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/installed_unpackaged_repository.hh99
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/installed_unpackaged_repository.sr14
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/installed_unpackaged_repository_TEST.cc596
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/unpackaged/installed_unpackaged_repository_TEST_cleanup.sh9
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/unpackaged/installed_unpackaged_repository_TEST_setup.sh72
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/ndbam-fwd.hh31
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/ndbam.cc562
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/ndbam.hh84
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/unpackaged/ndbam.sr18
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/ndbam_merger.cc298
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/ndbam_merger.hh62
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/ndbam_merger.sr18
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/ndbam_unmerger.cc295
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/ndbam_unmerger.hh84
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/ndbam_unmerger.sr19
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/registration.cc97
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/unpackaged_id.cc320
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/unpackaged_id.hh90
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/unpackaged_repository.cc140
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/unpackaged_repository.hh74
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/unpackaged_repository.sr16
-rw-r--r--0.26.0_alpha1/paludis/repositories/unpackaged/unpackaged_repository_TEST.cc207
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/unpackaged/unpackaged_repository_TEST_cleanup.sh9
-rwxr-xr-x0.26.0_alpha1/paludis/repositories/unpackaged/unpackaged_repository_TEST_setup.sh14
-rw-r--r--0.26.0_alpha1/paludis/repositories/virtuals/Makefile.am101
-rw-r--r--0.26.0_alpha1/paludis/repositories/virtuals/installed_virtuals_repository.cc337
-rw-r--r--0.26.0_alpha1/paludis/repositories/virtuals/installed_virtuals_repository.hh104
-rw-r--r--0.26.0_alpha1/paludis/repositories/virtuals/installed_virtuals_repository_TEST.cc41
-rw-r--r--0.26.0_alpha1/paludis/repositories/virtuals/package_id.cc527
-rw-r--r--0.26.0_alpha1/paludis/repositories/virtuals/package_id.hh132
-rw-r--r--0.26.0_alpha1/paludis/repositories/virtuals/registration.cc42
-rw-r--r--0.26.0_alpha1/paludis/repositories/virtuals/virtuals_repository.cc416
-rw-r--r--0.26.0_alpha1/paludis/repositories/virtuals/virtuals_repository.hh99
-rw-r--r--0.26.0_alpha1/paludis/repositories/virtuals/virtuals_repository_TEST.cc110
388 files changed, 53556 insertions, 0 deletions
diff --git a/0.26.0_alpha1/paludis/repositories/Makefile.am b/0.26.0_alpha1/paludis/repositories/Makefile.am
new file mode 100644
index 000000000..bcfcf0306
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/Makefile.am
@@ -0,0 +1,32 @@
+if MONOLITHIC
+
+SUBDIRS = $(BUILD_REPOSITORIES) .
+
+else
+
+SUBDIRS = . $(BUILD_REPOSITORIES)
+
+endif
+
+DIST_SUBDIRS = $(ALL_REPOSITORIES)
+
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+MAINTAINERCLEANFILES = Makefile.in
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
+DEFS= \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+distcheck-deps-local : $(DISTCHECK_DEPS)
+
+distcheck-deps : distcheck-deps-subdirs
+
+distcheck-deps-subdirs :
+ for s in $(SUBDIRS) . ; do if test x$$s = x. ; then $(MAKE) distcheck-deps-local || exit 1 ; \
+ else $(MAKE) -C $$s distcheck-deps || exit 1 ; fi ; done
diff --git a/0.26.0_alpha1/paludis/repositories/cran/Makefile.am b/0.26.0_alpha1/paludis/repositories/cran/Makefile.am
new file mode 100644
index 000000000..4aa54044c
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/Makefile.am
@@ -0,0 +1,160 @@
+SUBDIRS = cran .
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+DISTCLEANFILES = cran_repository-sr.hh cran_repository-sr.cc
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
+DEFS= \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBDIR=\"$(libdir)\"
+
+paludis_repositories_libdir = $(libdir)/paludis/repositories
+
+if MONOLITHIC
+
+noinst_LTLIBRARIES = libpaludiscranrepository.la
+
+else
+
+paludis_repositories_lib_LTLIBRARIES = libpaludiscranrepository.la
+
+endif
+
+paludis_repositories_cran_includedir = $(includedir)/paludis-$(PALUDIS_PC_SLOT)/paludis/repositories/cran/
+libpaludiscranrepository_la_LDFLAGS = -version-info @VERSION_LIB_CURRENT@:@VERSION_LIB_REVISION@:0
+
+paludis_repositories_cran_include_HEADERS = \
+ cran_package_id.hh \
+ cran_dep_parser.hh \
+ cran_repository.hh \
+ cran_repository-sr.hh \
+ cran_installed_repository.hh \
+ cran_installed_repository-sr.hh \
+ description_file.hh \
+ masks.hh \
+ keys.hh \
+ normalise.hh \
+ dep_spec_pretty_printer.hh
+
+libpaludiscranrepository_la_SOURCES = \
+ cran_package_id.cc \
+ cran_dep_parser.cc \
+ cran_repository.cc \
+ cran_installed_repository.cc \
+ description_file.cc \
+ registration.cc \
+ normalise.cc \
+ masks.cc \
+ keys.cc \
+ dep_spec_pretty_printer.cc \
+ $(paludis_repositories_cran_include_HEADERS)
+
+libpaludiscranrepository_la_LIBADD = \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+TESTS = \
+ cran_dep_parser_TEST \
+ cran_repository_TEST \
+ cran_installed_repository_TEST \
+ description_file_TEST
+
+cran_dep_parser_TEST_SOURCES = cran_dep_parser_TEST.cc
+
+cran_dep_parser_TEST_LDADD= \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/test/libtest.a \
+ libpaludiscranrepository.la
+
+cran_installed_repository_TEST_SOURCES = cran_installed_repository_TEST.cc
+
+cran_installed_repository_TEST_LDADD = \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/test/libtest.a \
+ libpaludiscranrepository.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
+ $(DYNAMIC_LD_LIBS)
+
+cran_repository_TEST_SOURCES = cran_repository_TEST.cc
+
+cran_repository_TEST_LDADD = \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/test/libtest.a \
+ libpaludiscranrepository.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
+ $(DYNAMIC_LD_LIBS)
+
+description_file_TEST_SOURCES = description_file_TEST.cc
+
+description_file_TEST_LDADD = \
+ $(top_builddir)/paludis/util/test_extras.o \
+ $(top_builddir)/test/libtest.a \
+ libpaludiscranrepository.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/environments/test/libpaludistestenvironment.la \
+ $(DYNAMIC_LD_LIBS)
+
+EXTRA_DIST = \
+ cran_repository_TEST.cc \
+ cran_repository_TEST_setup.sh \
+ cran_repository_TEST_cleanup.sh \
+ cran_repository.sr \
+ cran_repository-sr.hh \
+ cran_repository-sr.cc \
+ cran_installed_repository.sr \
+ cran_installed_repository-sr.hh \
+ cran_installed_repository-sr.cc \
+ cran_installed_repository_TEST.cc \
+ cran_installed_repository_TEST_setup.sh \
+ cran_installed_repository_TEST_cleanup.sh
+
+BUILT_SOURCES = \
+ cran_repository-sr.hh \
+ cran_repository-sr.cc \
+ cran_installed_repository-sr.hh \
+ cran_installed_repository-sr.cc
+
+check_PROGRAMS = $(TESTS)
+check_SCRIPTS = \
+ cran_repository_TEST_setup.sh cran_repository_TEST_cleanup.sh \
+ cran_installed_repository_TEST_setup.sh cran_installed_repository_TEST_cleanup.sh
+
+TESTS_ENVIRONMENT = env \
+ CRAN_BASH_DIR="$(top_srcdir)/paludis/repositories/cran/cran/" \
+ PALUDIS_SKIP_CONFIG="yes" \
+ PALUDIS_DISTRIBUTIONS_DIR="$(top_srcdir)/paludis/distributions/" \
+ PALUDIS_DISTRIBUTION="gentoo" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ PALUDIS_REPOSITORY_SO_DIR="$(top_builddir)/paludis/repositories" \
+ bash $(top_srcdir)/test/run_test.sh
+
+cran_repository-sr.hh : cran_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/cran_repository.sr > $@
+
+cran_repository-sr.cc : cran_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/cran_repository.sr > $@
+
+cran_installed_repository-sr.hh : cran_installed_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/cran_installed_repository.sr > $@
+
+cran_installed_repository-sr.cc : cran_installed_repository.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/cran_installed_repository.sr > $@
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+distcheck-deps-local : $(DISTCHECK_DEPS)
+
+distcheck-deps : distcheck-deps-subdirs
+
+distcheck-deps-subdirs :
+ for s in $(SUBDIRS) . ; do if test x$$s = x. ; then $(MAKE) distcheck-deps-local || exit 1 ; \
+ else $(MAKE) -C $$s distcheck-deps || exit 1 ; fi ; done
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran/Makefile.am b/0.26.0_alpha1/paludis/repositories/cran/cran/Makefile.am
new file mode 100644
index 000000000..90ad7e819
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran/Makefile.am
@@ -0,0 +1,21 @@
+MAINTAINERCLEANFILES = Makefile.in
+CLEANFILES = *~
+SUBDIRS = .
+
+libexecprogdir = $(libexecdir)/paludis/
+
+libexecprog_SCRIPTS = \
+ cran.bash
+
+EXTRA_DIST = $(libexecprog_SCRIPTS)
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+distcheck-deps-local : $(DISTCHECK_DEPS)
+
+distcheck-deps : distcheck-deps-subdirs
+
+distcheck-deps-subdirs :
+ for s in $(SUBDIRS) . ; do if test x$$s = x. ; then $(MAKE) distcheck-deps-local || exit 1 ; \
+ else $(MAKE) -C $$s distcheck-deps || exit 1 ; fi ; done
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran/cran.bash b/0.26.0_alpha1/paludis/repositories/cran/cran/cran.bash
new file mode 100644
index 000000000..db88e2812
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran/cran.bash
@@ -0,0 +1,151 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+# Copyright (c) 2006,2007 Danny van Dyk <kugelfang@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
+
+. ${PALUDIS_EBUILD_DIR}/echo_functions.bash
+
+shopt -s expand_aliases
+
+CRAN_KILL_PID=$$
+alias die='diefunc "$FUNCNAME" "$LINENO"'
+trap 'echo "die trap: exiting with error." 1>&2 ; exit 250' 15
+
+for f in ${PALUDIS_BASHRC_FILES} ; do
+ if [[ -f ${f} ]] ; then
+ ebuild_notice "debug" "Loading bashrc file ${f}"
+ source ${f}
+ else
+ ebuild_notice "debug" "Skipping bashrc file ${f}"
+ fi
+done
+
+diefunc()
+{
+ local func="$1" line="$2"
+ shift 2
+ echo 1>&2
+ echo "!!! ERROR in cran/${PN:-?}:" 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
+
+ kill ${CRAN_KILL_PID}
+ exit 249
+}
+
+cran_command() {
+ local ret=1 command=${1}
+ shift
+
+ ebuild_section "Starting ${command}"
+
+ if type cran_do_${command} &> /dev/null ; then
+ cran_do_${command} || die "Failed to run command: ${command}"
+ else
+ die "Unknown command: ${command}"
+ fi
+
+ ebuild_section "Done ${command}"
+}
+
+cran_do_clean() {
+ [[ -e ${WORKDIR} ]] && rm -rf ${WORKDIR}
+ [[ -e ${IMAGE} ]] && rm -rf ${IMAGE}
+ return 0
+}
+
+cran_do_fetch() {
+ local mirror ret=0
+ shift
+
+ for mirror in ${PALUDIS_CRAN_MIRRORS[@]} ; do
+ mkdir -p ${DISTDIR}
+ cd ${DISTDIR}
+
+ if [[ -e ${DISTFILE} ]] ; then
+ echo "Already fetched: $(basename ${DISTFILE})"
+ return 0
+ fi
+
+ local dofetch="${PALUDIS_EBUILD_DIR}/fetchers/do$(echo ${mirror%%://*})"
+ local a="${mirror}/src/contrib/${DISTFILE}"
+ if [[ -f "${dofetch}" ]] ; then
+ ${dofetch} "${a}" "${DISTFILE}"
+ ret=$?
+ else
+ eerror "Don't know how to fetch '${a}'"
+ ret=1
+ fi
+ if [[ ${ret} == 0 ]] ; then
+ break
+ else
+ echo "Failed to run \"${command}\" for mirror ${mirror}."
+ fi
+ done
+ if [[ ${ret} != 0 ]] ; then
+ echo "Finally failed to run \"${command}\"."
+ fi
+}
+
+cran_do_install() {
+ if [[ -e "${WORKDIR}" ]] ; then
+ rm -Rf "${WORKDIR}" || die "Could not remove existing WORKDIR: ${WORKDIR}"
+ fi
+ mkdir -p "${WORKDIR}"
+ cd "${WORKDIR}" || die "Could not cd to WORKDIR: ${WORKDIR}"
+
+ local dounpack="${PALUDIS_EBUILD_DIR}/utils/dounpack"
+ ${dounpack} "${DISTFILE}"
+
+ # \todo Sandbox this?
+ R CMD INSTALL -l "${IMAGE}/${PALUDIS_CRAN_LIBRARY##${ROOT}}" ${PN}
+
+ if [[ ${IS_BUNDLE} == "yes" ]] ; then
+ mkdir -p "${IMAGE}/${PALUDIS_CRAN_LIBRARY##${ROOT}}/paludis/bundles/"
+ cp "${PN}/DESCRIPTION" "${IMAGE}/${PALUDIS_CRAN_LIBRARY##${ROOT}}/paludis/bundles/${PN}.DESCRIPTION"
+ fi
+}
+
+cran_do_merge() {
+ [[ -e "${IMAGE}/${INSTALL_TO##${ROOT}}/R.css" ]] \
+ && rm -f "${IMAGE}/${PALUDIS_CRAN_LIBRARY##${ROOT}}/R.css"
+ mkdir -p "${PALUDIS_CRAN_LIBRARY}/paludis/${PN}"
+ ${PALUDIS_EBUILD_DIR}/merge "${IMAGE}" "${ROOT}" "${PALUDIS_CRAN_LIBRARY}/paludis/${PN}/CONTENTS"
+ echo ${REPOSITORY} > "${PALUDIS_CRAN_LIBRARY}/paludis/${PN}/REPOSITORY"
+}
+
+cran_do_unmerge() {
+ [[ -e "${PALUDIS_CRAN_LIBRARY}/paludis/${PN}/CONTENTS" ]] || die "CONTENTS file is missing for package ${PN}"
+ ${PALUDIS_EBUILD_DIR}/unmerge "${ROOT}" "${PALUDIS_CRAN_LIBRARY}/paludis/${PN}/CONTENTS"
+}
+
+for cmd in $* ; do
+ cran_command ${cmd}
+done
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_dep_parser.cc b/0.26.0_alpha1/paludis/repositories/cran/cran_dep_parser.cc
new file mode 100644
index 000000000..b44002b8f
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_dep_parser.cc
@@ -0,0 +1,88 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 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/dep_spec.hh>
+#include <paludis/repositories/cran/cran_dep_parser.hh>
+#include <paludis/repositories/cran/normalise.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/tokeniser.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+
+#include <string>
+#include <list>
+
+using namespace paludis;
+
+tr1::shared_ptr<DependencySpecTree::ConstItem>
+cranrepository::parse_depends(const std::string & s)
+{
+ Context context("When parsing CRAN 'Depends:' string: '" + s + "':");
+
+ tr1::shared_ptr<ConstTreeSequence<DependencySpecTree, AllDepSpec> > result(
+ new ConstTreeSequence<DependencySpecTree, AllDepSpec>(tr1::shared_ptr<AllDepSpec>(new AllDepSpec)));
+
+ std::list<std::string> specs;
+ Tokeniser<delim_kind::AnyOfTag>::tokenise(s, ",", std::back_inserter(specs));
+
+ std::list<std::string>::const_iterator a(specs.begin()), a_end(specs.end());
+ for ( ; a != a_end ; ++a)
+ {
+ Context local_context("When processing token '" + *a + "':");
+
+ std::string aa = strip_leading(strip_trailing(*a, ")"), " \t");
+
+ std::string name, tmp, version, range;
+ std::string::size_type p(aa.find('('));
+ if ((std::string::npos != p))
+ {
+ name = strip_leading(strip_trailing(aa.substr(0, p), " \t"), " \t");
+ tmp = aa.substr(p + 1);
+ p = tmp.find(')');
+ aa = tmp.substr(0, p);
+ version = strip_trailing(strip_leading(aa, " \t(<>=~"), " )\t\n");
+ range = strip_trailing(strip_leading(aa.substr(0, aa.find(version)), " \t"), " \t\n");
+ }
+ else
+ name = strip_leading(strip_trailing(aa, " \t"), " \t");
+
+ name = cran_name_to_internal(name);
+ version = cran_version_to_internal(version);
+
+ if ("R" == name)
+ name = "dev-lang/R";
+ else
+ name = "cran/" + name;
+
+ std::string spec_string;
+ if (version.empty() || range.empty())
+ spec_string = name;
+ else
+ spec_string = range + name + "-" + version;
+ tr1::shared_ptr<TreeLeaf<DependencySpecTree, PackageDepSpec> > spec(
+ new TreeLeaf<DependencySpecTree, PackageDepSpec>(tr1::shared_ptr<PackageDepSpec>(
+ new PackageDepSpec(spec_string, pds_pm_permissive))));
+ result->add(spec);
+ }
+
+ return result;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_dep_parser.hh b/0.26.0_alpha1/paludis/repositories/cran/cran_dep_parser.hh
new file mode 100644
index 000000000..e3769dbc3
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_dep_parser.hh
@@ -0,0 +1,35 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_CRAN_DEP_PARSER_HH
+#define PALUDIS_GUARD_PALUDIS_CRAN_DEP_PARSER_HH 1
+
+#include <paludis/dep_tree.hh>
+#include <string>
+
+namespace paludis
+{
+ namespace cranrepository
+ {
+ tr1::shared_ptr<DependencySpecTree::ConstItem> parse_depends(const std::string & s) PALUDIS_VISIBLE;
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_dep_parser_TEST.cc b/0.26.0_alpha1/paludis/repositories/cran/cran_dep_parser_TEST.cc
new file mode 100644
index 000000000..37803c5d1
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_dep_parser_TEST.cc
@@ -0,0 +1,63 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * 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/dep_spec.hh>
+#include <paludis/dep_spec_flattener.hh>
+#include <paludis/repositories/cran/cran_dep_parser.hh>
+#include <paludis/repositories/cran/dep_spec_pretty_printer.hh>
+#include <paludis/environments/test/test_environment.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/stringify_formatter.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace test;
+using namespace paludis;
+
+namespace test_cases
+{
+ struct CRANDepParserTest : TestCase
+ {
+ CRANDepParserTest() : TestCase("DepParser") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+ cranrepository::DepSpecPrettyPrinter d1(0, ff, 0, false), d2(0, ff, 0, false), d3(0, ff, 0, false);
+
+ // test R dependency
+ std::string dep1("R (>= 2.0.0)");
+ cranrepository::parse_depends(dep1)->accept(d1);
+ TEST_CHECK_EQUAL(stringify(d1), ">=dev-lang/R-2.0.0");
+
+ // test varying whitespaces
+ std::string dep2("testpackage1 \t(<1.9)");
+ cranrepository::parse_depends(dep2)->accept(d2);
+ TEST_CHECK_EQUAL(stringify(d2), "<cran/testpackage1-1.9");
+
+ // test for package-name and version normalisation
+ std::string dep3("R.matlab (>= 2.3-1)");
+ cranrepository::parse_depends(dep3)->accept(d3);
+ TEST_CHECK_EQUAL(stringify(d3), ">=cran/R-matlab-2.3.1");
+ }
+ } test_cran_dep_parser;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository.cc b/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository.cc
new file mode 100644
index 000000000..8efa82f51
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository.cc
@@ -0,0 +1,662 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Danny van Dyk <kugelfang@gentoo.org>
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/hashed_containers.hh>
+#include <paludis/environment.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/repository_info.hh>
+#include <paludis/dep_spec.hh>
+#include <paludis/dep_tag.hh>
+#include <paludis/util/config_file.hh>
+#include <paludis/set_file.hh>
+#include <paludis/action.hh>
+#include <paludis/repositories/cran/cran_package_id.hh>
+#include <paludis/repositories/cran/cran_dep_parser.hh>
+#include <paludis/repositories/cran/cran_installed_repository.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/map.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/tr1_functional.hh>
+#include <paludis/util/visitor-impl.hh>
+
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+
+#include <functional>
+#include <algorithm>
+#include <fstream>
+
+using namespace paludis;
+
+#include <paludis/repositories/cran/cran_installed_repository-sr.cc>
+
+typedef MakeHashedMap<QualifiedPackageName, tr1::shared_ptr<const cranrepository::CRANPackageID> >::Type IDMap;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<CRANInstalledRepository>
+ {
+ CRANInstalledRepositoryParams params;
+
+ mutable bool has_ids;
+ mutable IDMap ids;
+
+ /// Constructor.
+ Implementation(const CRANInstalledRepositoryParams &);
+
+ /// Destructor.
+ ~Implementation();
+ };
+}
+
+Implementation<CRANInstalledRepository>::Implementation(const CRANInstalledRepositoryParams & p) :
+ params(p),
+ has_ids(false)
+{
+}
+
+Implementation<CRANInstalledRepository>::~Implementation()
+{
+}
+
+#if 0
+void
+Implementation<CRANInstalledRepository>::need_ids() const
+{
+ Context context("When loading CRANInstalledRepository IDs from '" + stringify(location) + "':");
+
+ entries_valid = true;
+ try
+ {
+ for (DirIterator d(location), d_end ; d != d_end ; ++d)
+ {
+ Context local_context("When parsing directoryy '" + stringify(*d) + "':");
+ if (! d->is_directory())
+ continue;
+
+ FSEntry f(FSEntry(stringify(*d)) / "DESCRIPTION");
+ if (! f.is_regular_file())
+ continue;
+
+ std::string n(d->basename());
+ CRANDescription::normalise_name(n);
+
+ CRANDescription desc(n, f, true);
+ entries.push_back(desc);
+
+ QualifiedPackageName q("cran/" + n);
+ metadata.insert(std::make_pair(std::make_pair(q, VersionSpec(desc.version)), desc.metadata));
+ }
+
+ if (! FSEntry(location / "paludis" / "bundles").is_directory())
+ return;
+
+ // Load Bundle Metadata
+ for (DirIterator f(location / "paludis" / "bundles"), f_end ; f != f_end ; ++f)
+ {
+ Context local_context("When parsing file '" + stringify(*f) + "'.");
+
+ if (! f->is_regular_file())
+ {
+ continue;
+ }
+
+ std::string n(f->basename());
+ std::string::size_type pos(n.find_last_of("."));
+ if (std::string::npos != pos)
+ n.erase(pos);
+ CRANDescription::normalise_name(n);
+
+ CRANDescription desc(n, *f, true);
+ entries.push_back(desc);
+
+ QualifiedPackageName q("cran/" + n);
+ metadata.insert(std::make_pair(std::make_pair(q, VersionSpec(desc.version)), desc.metadata));
+ }
+
+ }
+ catch (...)
+ {
+ entries_valid = false;
+ throw;
+ }
+}
+#endif
+
+CRANInstalledRepository::CRANInstalledRepository(const CRANInstalledRepositoryParams & p) :
+ Repository(RepositoryName("installed-cran"),
+ RepositoryCapabilities::create()
+ .installed_interface(this)
+ .sets_interface(this)
+ .syncable_interface(0)
+ .use_interface(0)
+ .world_interface(this)
+ .environment_variable_interface(0)
+ .mirrors_interface(0)
+ .virtuals_interface(0)
+ .provides_interface(0)
+ .destination_interface(this)
+ .licenses_interface(0)
+ .e_interface(0)
+ .qa_interface(0)
+ .make_virtuals_interface(0)
+ .hook_interface(0)
+ .manifest_interface(0),
+ "cran_installed"),
+ PrivateImplementationPattern<CRANInstalledRepository>(new Implementation<CRANInstalledRepository>(p))
+{
+ tr1::shared_ptr<RepositoryInfoSection> config_info(new RepositoryInfoSection("Configuration information"));
+
+ config_info->add_kv("location", stringify(_imp->params.location));
+ config_info->add_kv("root", stringify(_imp->params.root));
+ config_info->add_kv("format", "cran_installed");
+
+ _info->add_section(config_info);
+}
+
+CRANInstalledRepository::~CRANInstalledRepository()
+{
+}
+
+bool
+CRANInstalledRepository::do_has_category_named(const CategoryNamePart & c) const
+{
+ return (CategoryNamePart("cran") == c);
+}
+
+bool
+CRANInstalledRepository::do_has_package_named(const QualifiedPackageName & q) const
+{
+ Context context("When checking for package '" + stringify(q) + "' in " + stringify(name()) + ":");
+
+ if (! do_has_category_named(q.category))
+ return false;
+
+ need_ids();
+
+ return _imp->ids.end() != _imp->ids.find(q);
+}
+
+tr1::shared_ptr<const CategoryNamePartSet>
+CRANInstalledRepository::do_category_names() const
+{
+ tr1::shared_ptr<CategoryNamePartSet> result(new CategoryNamePartSet);
+ result->insert(CategoryNamePart("cran"));
+ return result;
+}
+
+tr1::shared_ptr<const QualifiedPackageNameSet>
+CRANInstalledRepository::do_package_names(const CategoryNamePart & c) const
+{
+ Context context("When fetching package names in category '" + stringify(c)
+ + "' in " + stringify(name()) + ":");
+
+ tr1::shared_ptr<QualifiedPackageNameSet> result(new QualifiedPackageNameSet);
+ if (! do_has_category_named(c))
+ return result;
+
+ need_ids();
+
+ std::copy(_imp->ids.begin(), _imp->ids.end(), transform_inserter(result->inserter(),
+ tr1::mem_fn(&std::pair<const QualifiedPackageName, tr1::shared_ptr<const cranrepository::CRANPackageID> >::first)));
+
+ return result;
+}
+
+tr1::shared_ptr<const PackageIDSequence>
+CRANInstalledRepository::do_package_ids(const QualifiedPackageName & n) const
+{
+ Context context("When fetching versions of '" + stringify(n) + "' in "
+ + stringify(name()) + ":");
+
+ tr1::shared_ptr<PackageIDSequence> result(new PackageIDSequence);
+ if (! do_has_package_named(n))
+ return result;
+
+ need_ids();
+
+ IDMap::const_iterator i(_imp->ids.find(n));
+ if (i != _imp->ids.end())
+ result->push_back(i->second);
+ return result;
+}
+
+#if 0
+tr1::shared_ptr<const Contents>
+CRANInstalledRepository::do_contents(const Package ID & id) const
+{
+ Context context("When fetching contents for " + stringify(id) + ":");
+
+ tr1::shared_ptr<Contents> result(new Contents);
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ if (! has_version(q, v))
+ return result;
+
+ std::string pn = stringify(q.package);
+ CRANDescription::normalise_name(pn);
+ FSEntry f(_imp->location / "paludis" / pn / "CONTENTS");
+ if (! f.is_regular_file())
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "CONTENTS lookup failed for request for' " +
+ stringify(q) + "-" + stringify(v) + "' in CRANInstalled '" +
+ stringify(_imp->location) + "'");
+ return result;
+ }
+
+ 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::tokenise(line, std::back_inserter(tokens));
+ if (tokens.empty())
+ continue;
+
+ if (tokens.size() < 2)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "CONTENTS for '" +
+ stringify(q) + "-" + stringify(v) + "' in vdb '" +
+ stringify(_imp->location) + "' has broken line " +
+ stringify(line_number) + ", skipping");
+ continue;
+ }
+
+ if ("obj" == tokens.at(0))
+ result->add(tr1::shared_ptr<ContentsEntry>(new ContentsFileEntry(tokens.at(1))));
+ else if ("dir" == tokens.at(0))
+ result->add(tr1::shared_ptr<ContentsEntry>(new ContentsDirEntry(tokens.at(1))));
+ else if ("misc" == tokens.at(0))
+ result->add(tr1::shared_ptr<ContentsEntry>(new ContentsMiscEntry(tokens.at(1))));
+ else if ("sym" == tokens.at(0))
+ {
+ if (tokens.size() < 4)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "CONTENTS for '" +
+ stringify(q) + "-" + stringify(v) + "' in vdb '" +
+ stringify(_imp->location) + "' has broken sym line " +
+ stringify(line_number) + ", skipping");
+ continue;
+ }
+
+ result->add(tr1::shared_ptr<ContentsEntry>(new ContentsSymEntry(
+ tokens.at(1), tokens.at(3))));
+ }
+ }
+
+ return result;
+}
+
+time_t
+CRANInstalledRepository::do_installed_time(const QualifiedPackageName & q,
+ const VersionSpec & v) const
+{
+ Context context("When finding installed time for '" + stringify(q) +
+ "-" + stringify(v) + "':");
+
+ if (! _imp->entries_valid)
+ _imp->load_entries();
+
+ std::vector<CRANDescription>::iterator r(_imp->entries.begin()), r_end(_imp->entries.end());
+ for ( ; r != r_end ; ++r)
+ {
+ if (q == r->name)
+ break;
+ }
+
+ if (r == r_end)
+ throw NoSuchPackageError(stringify(PackageDatabaseEntry(q, v, name())));
+ else
+ {
+ if (0 == r->installed_time)
+ {
+ std::string pn(stringify(q.package));
+ CRANDescription::normalise_name(pn);
+ FSEntry f(_imp->location / "paludis" / pn / "CONTENTS");
+ try
+ {
+ r->installed_time = f.ctime();
+ }
+ catch (const FSError & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Can't get ctime of '"
+ + stringify(f) + "' due to exception '" + e.message() + "' (" + e.what()
+ + ")");
+ r->installed_time = 1;
+ }
+ }
+ return r->installed_time;
+ }
+}
+#endif
+
+tr1::shared_ptr<Repository>
+CRANInstalledRepository::make_cran_installed_repository(
+ Environment * const env,
+ tr1::shared_ptr<const Map<std::string, std::string> > m)
+{
+ Context context("When making CRAN installed repository from repo_file '" +
+ (m->end() == m->find("repo_file") ? std::string("?") : m->find("repo_file")->second) + "':");
+
+ std::string location;
+ if (m->end() == m->find("location") || ((location = m->find("location")->second)).empty())
+ throw CRANInstalledRepositoryConfigurationError("Key 'location' not specified or empty");
+
+ std::string root;
+ if (m->end() == m->find("root") || ((root = m->find("root")->second)).empty())
+ root = stringify(env->root());
+
+ std::string world;
+ if (m->end() == m->find("world") || ((world = m->find("world")->second)).empty())
+ world = location + "/world";
+
+ return tr1::shared_ptr<Repository>(new CRANInstalledRepository(CRANInstalledRepositoryParams::create()
+ .environment(env)
+ .location(location)
+ .root(root)
+ .world(world)));
+}
+
+CRANInstalledRepositoryConfigurationError::CRANInstalledRepositoryConfigurationError(
+ const std::string & msg) throw () :
+ ConfigurationError("CRAN installed repository configuration error: " + msg)
+{
+}
+
+#if 0
+void
+CRANInstalledRepository::do_uninstall(const QualifiedPackageName & q, const VersionSpec & v,
+ const UninstallOptions &) const
+{
+ Context context("When uninstalling '" + stringify(q) + "-" + stringify(v) +
+ "' from '" + stringify(name()) + "':");
+
+ if (! _imp->location.is_directory())
+ throw PackageInstallActionError("Couldn't uninstall '" + stringify(q) + "-" +
+ stringify(v) + "' because its location ('" + stringify(_imp->location) + "') is not a directory");
+
+ tr1::shared_ptr<const VersionMetadata> vm(do_version_metadata(q, v));
+ tr1::shared_ptr<const FSEntryCollection> bashrc_files(_imp->env->bashrc_files());
+
+ Command cmd(Command(LIBEXECDIR "/paludis/cran.bash unmerge")
+ .with_setenv("PN", vm->cran_interface->package)
+ .with_setenv("PV", stringify(v))
+ .with_setenv("PALUDIS_CRAN_LIBRARY", stringify(_imp->location))
+ .with_setenv("PALUDIS_EBUILD_DIR", std::string(LIBEXECDIR "/paludis/"))
+ .with_setenv("PALUDIS_BASHRC_FILES", join(bashrc_files->begin(), bashrc_files->end(), " ")));
+
+ if (0 != run_command(cmd))
+ throw PackageUninstallActionError("Couldn't unmerge '" + stringify(q) + "-" + stringify(v) + "'");
+}
+#endif
+
+tr1::shared_ptr<SetSpecTree::ConstItem>
+CRANInstalledRepository::do_package_set(const SetName & s) const
+{
+ Context context("When fetching package set '" + stringify(s) + "' from '" +
+ stringify(name()) + "':");
+
+ if ("everything" == s.data())
+ {
+ tr1::shared_ptr<ConstTreeSequence<SetSpecTree, AllDepSpec> > result(new ConstTreeSequence<SetSpecTree, AllDepSpec>(
+ tr1::shared_ptr<AllDepSpec>(new AllDepSpec)));
+
+ need_ids();
+
+ for (IDMap::const_iterator p(_imp->ids.begin()), p_end(_imp->ids.end()) ;
+ p != p_end ; ++p)
+ {
+ tr1::shared_ptr<TreeLeaf<SetSpecTree, PackageDepSpec> > spec(
+ new TreeLeaf<SetSpecTree, PackageDepSpec>(make_shared_ptr(
+ new PackageDepSpec(make_shared_ptr(new QualifiedPackageName(p->first))))));
+ result->add(spec);
+ }
+
+ return result;
+ }
+ else if ("world" == s.data())
+ {
+ tr1::shared_ptr<ConstTreeSequence<SetSpecTree, AllDepSpec> > result(new ConstTreeSequence<SetSpecTree, AllDepSpec>(
+ tr1::shared_ptr<AllDepSpec>(new AllDepSpec)));
+ tr1::shared_ptr<GeneralSetDepTag> tag(new GeneralSetDepTag(SetName("world"), stringify(name())));
+
+ if (_imp->params.world.exists())
+ {
+ SetFile world(SetFileParams::create()
+ .file_name(_imp->params.world)
+ .type(sft_simple)
+ .parse_mode(pds_pm_unspecific)
+ .tag(tag)
+ .environment(_imp->params.environment));
+
+ return world.contents();
+ }
+ else
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context) << "World file '" << _imp->params.world << "' doesn't exist";
+ return result;
+ }
+ }
+ else
+ return tr1::shared_ptr<SetSpecTree::ConstItem>();
+}
+
+tr1::shared_ptr<const SetNameSet>
+CRANInstalledRepository::sets_list() const
+{
+ Context context("While generating the list of sets:");
+
+ tr1::shared_ptr<SetNameSet> result(new SetNameSet);
+ result->insert(SetName("everything"));
+ result->insert(SetName("world"));
+ return result;
+}
+
+void
+CRANInstalledRepository::invalidate()
+{
+ _imp.reset(new Implementation<CRANInstalledRepository>(_imp->params));
+}
+
+void
+CRANInstalledRepository::invalidate_masks()
+{
+}
+
+void
+CRANInstalledRepository::add_string_to_world(const std::string & n) const
+{
+ Context context("When adding '" + n + "' to world file '" + stringify(_imp->params.world) + "':");
+
+ if (! _imp->params.world.exists())
+ {
+ std::ofstream f(stringify(_imp->params.world).c_str());
+ if (! f)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context, "Cannot create world file '"
+ + stringify(_imp->params.world) + "'");
+ return;
+ }
+ }
+
+ SetFile world(SetFileParams::create()
+ .file_name(_imp->params.world)
+ .type(sft_simple)
+ .parse_mode(pds_pm_unspecific)
+ .tag(tr1::shared_ptr<DepTag>())
+ .environment(_imp->params.environment));
+ world.add(n);
+ world.rewrite();
+}
+
+void
+CRANInstalledRepository::remove_string_from_world(const std::string & n) const
+{
+ Context context("When removing '" + n + "' from world file '" + stringify(_imp->params.world) + "':");
+
+ if (_imp->params.world.exists())
+ {
+ SetFile world(SetFileParams::create()
+ .file_name(_imp->params.world)
+ .type(sft_simple)
+ .parse_mode(pds_pm_unspecific)
+ .tag(tr1::shared_ptr<DepTag>())
+ .environment(_imp->params.environment));
+
+ world.remove(n);
+ world.rewrite();
+ }
+}
+
+bool
+CRANInstalledRepository::is_suitable_destination_for(const PackageID & e) const
+{
+ std::string f(e.repository()->format());
+ return f == "cran";
+}
+
+void
+CRANInstalledRepository::add_to_world(const QualifiedPackageName & n) const
+{
+ add_string_to_world(stringify(n));
+}
+
+void
+CRANInstalledRepository::remove_from_world(const QualifiedPackageName & n) const
+{
+ remove_string_from_world(stringify(n));
+}
+
+void
+CRANInstalledRepository::add_to_world(const SetName & n) const
+{
+ add_string_to_world(stringify(n));
+}
+
+void
+CRANInstalledRepository::remove_from_world(const SetName & n) const
+{
+ remove_string_from_world(stringify(n));
+}
+
+FSEntry
+CRANInstalledRepository::root() const
+{
+ return _imp->params.root;
+}
+
+bool
+CRANInstalledRepository::is_default_destination() const
+{
+ return _imp->params.environment->root() == root();
+}
+
+bool
+CRANInstalledRepository::want_pre_post_phases() const
+{
+ return true;
+}
+
+void
+CRANInstalledRepository::merge(const MergeOptions & m)
+{
+ Context context("When merging '" + stringify(*m.package_id) + "' at '" + stringify(m.image_dir)
+ + "' to repository '" + stringify(name()) + "':");
+
+ if (! is_suitable_destination_for(*m.package_id))
+ throw InstallActionError("Not a suitable destination for '" + stringify(*m.package_id) + "'");
+
+}
+
+namespace
+{
+ struct SupportsActionQuery :
+ ConstVisitor<SupportsActionTestVisitorTypes>
+ {
+ bool result;
+
+ SupportsActionQuery() :
+ result(false)
+ {
+ }
+
+ void visit(const SupportsActionTest<InstalledAction> &)
+ {
+ result = true;
+ }
+
+ void visit(const SupportsActionTest<InstallAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<ConfigAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<PretendAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<FetchAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<UninstallAction> &)
+ {
+ result = true;
+ }
+
+ void visit(const SupportsActionTest<InfoAction> &)
+ {
+ }
+ };
+}
+
+bool
+CRANInstalledRepository::do_some_ids_might_support_action(const SupportsActionTestBase & a) const
+{
+ SupportsActionQuery q;
+ a.accept(q);
+ return q.result;
+}
+
+void
+CRANInstalledRepository::need_ids() const
+{
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository.hh b/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository.hh
new file mode 100644
index 000000000..7cce445e2
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository.hh
@@ -0,0 +1,156 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_CRAN_INSTALLED_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_CRAN_INSTALLED_REPOSITORY_HH 1
+
+#include <paludis/repository.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/map-fwd.hh>
+
+/** \file
+ * Declarations for CRANInstalledRepository.
+ *
+ * \ingroup grpcraninstrepository
+ */
+
+namespace paludis
+{
+
+#include <paludis/repositories/cran/cran_installed_repository-sr.hh>
+
+ /**
+ * A CRANInstalledRepository represents the database used for
+ * installed CRAN packages.
+ *
+ * \ingroup grpcraninstrepository
+ */
+ class PALUDIS_VISIBLE CRANInstalledRepository :
+ public Repository,
+ public RepositoryInstalledInterface,
+ public RepositorySetsInterface,
+ public RepositoryWorldInterface,
+ public RepositoryDestinationInterface,
+ public PrivateImplementationPattern<CRANInstalledRepository>
+ {
+ private:
+ void need_ids() const;
+ void add_string_to_world(const std::string & n) const;
+ void remove_string_from_world(const std::string &) const;
+
+ protected:
+ /* Repository */
+
+ virtual tr1::shared_ptr<const PackageIDSequence> do_package_ids(
+ const QualifiedPackageName &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const QualifiedPackageNameSet> do_package_names(
+ const CategoryNamePart &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const CategoryNamePartSet> do_category_names() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool do_has_category_named(const CategoryNamePart &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool do_some_ids_might_support_action(const SupportsActionTestBase &) const;
+
+ /* RepositorySetsInterface */
+
+ virtual tr1::shared_ptr<SetSpecTree::ConstItem> do_package_set(const SetName & id) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ public:
+ /**
+ * Constructor.
+ */
+ CRANInstalledRepository(const CRANInstalledRepositoryParams &);
+
+ /**
+ * Virtual constructor.
+ */
+ static tr1::shared_ptr<Repository> make_cran_installed_repository(
+ Environment * const env,
+ tr1::shared_ptr<const Map<std::string, std::string> > m);
+
+ /**
+ * Destructor.
+ */
+ ~CRANInstalledRepository();
+
+ virtual void invalidate();
+ virtual void invalidate_masks();
+
+ /* RepositoryInstalledInterface */
+
+ virtual FSEntry root() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /* RepositorySetsInterface */
+
+ virtual tr1::shared_ptr<const SetNameSet> sets_list() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /* RepositoryWorldInterface */
+
+ virtual void add_to_world(const QualifiedPackageName &) const;
+ virtual void add_to_world(const SetName &) const;
+ virtual void remove_from_world(const QualifiedPackageName &) const;
+ virtual void remove_from_world(const SetName &) const;
+
+ /* RepositoryDestinationInterface */
+
+ virtual bool is_suitable_destination_for(const PackageID &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool is_default_destination() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool want_pre_post_phases() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual void merge(const MergeOptions &);
+ };
+
+ /**
+ * Thrown if invalid parameters are provided for
+ * CRANInstalledRepositoryConfigurationError::make_cran_installed_repository.
+ *
+ * \ingroup grpcraninstrepository
+ * \ingroup grpexceptions
+ */
+ class PALUDIS_VISIBLE CRANInstalledRepositoryConfigurationError :
+ public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ CRANInstalledRepositoryConfigurationError(const std::string & msg) throw ();
+ };
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository.sr b/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository.sr
new file mode 100644
index 000000000..150c7d97e
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository.sr
@@ -0,0 +1,25 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_CRANInstalledRepositoryParams()
+{
+ visible
+
+ key environment "const Environment *"
+ key location FSEntry
+ key root FSEntry
+ key world FSEntry
+
+ doxygen_comment << "END"
+ /**
+ * Parameters used to create a CRANInstalledRepository
+ *
+ * \see CRANInstalledRepository
+ * \ingroup grpcraninstrepository
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository_TEST.cc b/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository_TEST.cc
new file mode 100644
index 000000000..dc85d9700
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository_TEST.cc
@@ -0,0 +1,55 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/dep_spec.hh>
+#include <paludis/dep_spec_flattener.hh>
+#include <paludis/repositories/cran/cran_dep_parser.hh>
+#include <paludis/repositories/cran/cran_package_id.hh>
+#include <paludis/repositories/cran/cran_installed_repository.hh>
+#include <paludis/environments/test/test_environment.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/map.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace test;
+using namespace paludis;
+
+namespace test_cases
+{
+ struct CRANInstalledRepositoryPackagesTest : TestCase
+ {
+ CRANInstalledRepositoryPackagesTest() : TestCase("PACKAGES") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(new Map<std::string, std::string>);
+ keys->insert("format", "cran_installed");
+ keys->insert("library", "cran_installed_repository_TEST_dir/library");
+ keys->insert("location", "cran_installed_repository_TEST_dir/repo1");
+ keys->insert("builddir", "cran_installed_repository_TEST_dir/tmp");
+ tr1::shared_ptr<Repository> repo(CRANInstalledRepository::make_cran_installed_repository(&env, keys));
+ TEST_CHECK(repo->has_category_named(CategoryNamePart("cran")));
+ }
+ } test_cran_repository_installed_packages;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository_TEST_cleanup.sh b/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository_TEST_cleanup.sh
new file mode 100755
index 000000000..a571a3d5a
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository_TEST_cleanup.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d cran_installed_repository_TEST_dir ] ; then
+ rm -fr cran_installed_repository_TEST_dir
+else
+ true
+fi
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository_TEST_setup.sh b/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository_TEST_setup.sh
new file mode 100755
index 000000000..ac0c137fa
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_installed_repository_TEST_setup.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir cran_installed_repository_TEST_dir || exit 1
+cd cran_installed_repository_TEST_dir || exit 1
+
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_package_id.cc b/0.26.0_alpha1/paludis/repositories/cran/cran_package_id.cc
new file mode 100644
index 000000000..6635ec4a4
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_package_id.cc
@@ -0,0 +1,531 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Danny van Dyk <kugelfang@gentoo.org>
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/cran/cran_package_id.hh>
+#include <paludis/repositories/cran/cran_dep_parser.hh>
+#include <paludis/repositories/cran/description_file.hh>
+#include <paludis/repositories/cran/masks.hh>
+#include <paludis/repositories/cran/keys.hh>
+#include <paludis/repositories/cran/normalise.hh>
+#include <paludis/repositories/cran/cran_repository.hh>
+#include <paludis/repositories/cran/cran_installed_repository.hh>
+#include <paludis/util/config_file.hh>
+#include <paludis/repository.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/name.hh>
+#include <paludis/version_spec.hh>
+#include <paludis/action.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <string>
+#include <algorithm>
+#include <list>
+
+#include <paludis/util/tr1_functional.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+
+using namespace paludis;
+using namespace paludis::cranrepository;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<CRANPackageID>
+ {
+ const Environment * const env;
+
+ const tr1::shared_ptr<const Repository> repository;
+ const tr1::shared_ptr<const CRANRepository> cran_repository;
+ const tr1::shared_ptr<const CRANInstalledRepository> cran_installed_repository;
+
+ QualifiedPackageName name;
+ VersionSpec version;
+
+ tr1::shared_ptr<FSLocationKey> fs_location_key;
+ tr1::shared_ptr<SimpleURIKey> homepage_key;
+ tr1::shared_ptr<StringKey> short_description_key;
+ tr1::shared_ptr<StringKey> long_description_key;
+ tr1::shared_ptr<PackageIDKey> contained_in_key;
+ tr1::shared_ptr<PackageIDSequenceKey> contains_key;
+ tr1::shared_ptr<DepKey> depends_key;
+ tr1::shared_ptr<DepKey> suggests_key;
+
+ Implementation(const Environment * const e,
+ const tr1::shared_ptr<const CRANRepository> & r, const FSEntry & f) :
+ env(e),
+ repository(r),
+ cran_repository(r),
+ name("cran/" + cran_name_to_internal(strip_trailing_string(f.basename(), ".DESCRIPTION"))),
+ version("0")
+ {
+ }
+
+ Implementation(const Environment * const e,
+ const tr1::shared_ptr<const CRANRepository> & c, const CRANPackageID * const r, const std::string & t) :
+ env(e),
+ repository(c),
+ cran_repository(c),
+ name("cran/" + cran_name_to_internal(t)),
+ version(r->version()),
+ contained_in_key(new PackageIDKey("Contained", "Contained in", r, mkt_normal))
+ {
+ }
+ };
+}
+
+CRANPackageID::CRANPackageID(const Environment * const env, const tr1::shared_ptr<const CRANRepository> & r, const FSEntry & f) :
+ PrivateImplementationPattern<CRANPackageID>(new Implementation<CRANPackageID>(env, r, f)),
+ _imp(PrivateImplementationPattern<CRANPackageID>::_imp.get())
+{
+ Context context("When parsing file '" + stringify(f) + "' to create a CRAN Package ID:");
+
+ if (! f.is_regular_file())
+ {
+ add_mask(make_shared_ptr(new BrokenMask('B', "Broken", "DESCRIPTION file not a file")));
+ Log::get_instance()->message(ll_warning, lc_context) << "Unexpected irregular file: '" << stringify(f) << "'";
+ return;
+ }
+
+ _imp->fs_location_key.reset(new FSLocationKey("DescriptionFileLocation", "Description File Location",
+ f, mkt_internal));
+ add_metadata_key(_imp->fs_location_key);
+
+ try
+ {
+ DescriptionFile file(f);
+
+ std::string raw_name;
+ if (! file.get("Package").empty())
+ {
+ Context local_context("When handling Package: key:");
+ raw_name = file.get("Package");
+ _imp->name = QualifiedPackageName(CategoryNamePart("cran"), PackageNamePart(cran_name_to_internal(raw_name)));
+ }
+ else if (! file.get("Bundle").empty())
+ {
+ Context local_context("When handling Bundle: key:");
+ raw_name = file.get("Bundle");
+ _imp->name = QualifiedPackageName(CategoryNamePart("cran"), PackageNamePart(cran_name_to_internal(raw_name)));
+ }
+ else
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "No Package: or Bundle: key in '" << stringify(f) << "'";
+ add_mask(make_shared_ptr(new BrokenMask('B', "Broken", "No Package: or Bundle: key")));
+ return;
+ }
+
+ if (file.get("Version").empty())
+ {
+ Context local_context("When handling Version: key:");
+ Log::get_instance()->message(ll_warning, lc_context) << "No Version: key in '" << stringify(f) << "'";
+ _imp->version = VersionSpec("0");
+ add_mask(make_shared_ptr(new BrokenMask('B', "Broken", "No Version: key")));
+ return;
+ }
+ else
+ {
+ Context local_context("When handling Version: key:");
+ _imp->version = VersionSpec(cran_version_to_internal(file.get("Version")));
+ }
+
+ if (! file.get("URL").empty())
+ {
+ Context local_context("When handling URL: key:");
+ _imp->homepage_key.reset(new SimpleURIKey("URL", "URL", file.get("URL"), mkt_significant));
+ add_metadata_key(_imp->homepage_key);
+ }
+
+ if (! file.get("Title").empty())
+ {
+ Context local_context("When handling Title: key:");
+ _imp->short_description_key.reset(new StringKey("Title", "Title", file.get("Title"), mkt_significant));
+ add_metadata_key(_imp->short_description_key);
+ }
+
+ if (! file.get("Description").empty())
+ {
+ Context local_context("When handling Description: key:");
+ _imp->long_description_key.reset(new StringKey("Description", "Description", file.get("Description"), mkt_normal));
+ add_metadata_key(_imp->long_description_key);
+ }
+ else if (! file.get("BundleDescription").empty())
+ {
+ Context local_context("When handling BundleDescription: key:");
+ _imp->long_description_key.reset(new StringKey("BundleDescription", "Bundle Description",
+ file.get("BundleDescription"), mkt_normal));
+ }
+
+ if (! file.get("Author").empty())
+ {
+ Context local_context("When handling Author: key:");
+ add_metadata_key(make_shared_ptr(new StringKey("Author", "Author", file.get("Author"), mkt_normal)));
+ }
+
+ if (! file.get("Maintainer").empty())
+ {
+ Context local_context("When handling Maintainer: key:");
+ add_metadata_key(make_shared_ptr(new StringKey("Maintainer", "Maintainer", file.get("Maintainer"), mkt_normal)));
+ }
+
+ if (! file.get("Contains").empty())
+ {
+ Context local_context("When handling Contains: key:");
+ std::list<std::string> tokens;
+ WhitespaceTokeniser::tokenise(file.get("Contains"), std::back_inserter(tokens));
+ _imp->contains_key.reset(new PackageIDSequenceKey(_imp->env, "Contains", "Contains", mkt_normal));
+ add_metadata_key(_imp->contains_key);
+ for (std::list<std::string>::const_iterator t(tokens.begin()), t_end(tokens.end()) ;
+ t != t_end ; ++t)
+ {
+ if (*t != stringify(name().package))
+ _imp->contains_key->push_back(make_shared_ptr(new CRANPackageID(_imp->env, _imp->cran_repository, this, *t)));
+ else
+ {
+ /* yay CRAN... */
+ Log::get_instance()->message(ll_qa, lc_context) << "Bundle '" << stringify(*this) << "' contains itself, but is "
+ "not a Klein bundle";
+ }
+ }
+ }
+
+ if (! file.get("Suggests").empty())
+ {
+ Context local_context("When handling Suggests: key:");
+ _imp->suggests_key.reset(new DepKey(_imp->env, "Suggests", "Suggests", file.get("Suggests"), mkt_dependencies));
+ add_metadata_key(_imp->suggests_key);
+ }
+
+ if (! file.get("Depends").empty())
+ {
+ Context local_context("When handling Depends: key:");
+ _imp->depends_key.reset(new DepKey(_imp->env, "Depends", "Depends", file.get("Depends") + ", R", mkt_dependencies));
+ }
+ else
+ _imp->depends_key.reset(new DepKey(_imp->env, "Depends", "Depends", "R", mkt_dependencies));
+ add_metadata_key(_imp->depends_key);
+ }
+ catch (const Exception & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_context) << "Broken CRAN description file '" << stringify(f) << "': '"
+ << e.message() << "' (" << e.what() << ")";
+ add_mask(make_shared_ptr(new BrokenMask('B', "Broken", "Got exception '" + stringify(e.message()) + "' (" + e.what() + "')")));
+ }
+
+#if 0
+ for (cranrepository::DescriptionFile::Iterator i(file.begin()), i_end(file.end()) ;
+ i != i_end ; ++i)
+ {
+ if (("Package" == key) || ("Bundle" == key))
+ {
+ metadata->set_homepage("http://cran.r-project.org/src/contrib/Descriptions/" + value + ".html");
+ if ("Package" == key)
+ {
+ CRANDescription::normalise_name(value);
+ if (n != value)
+ Log::get_instance()->message(ll_warning, lc_context) << "Inconsistent package name in file '" <<
+ f << "': '" << value << "'";
+ }
+ else
+ metadata->cran_interface->is_bundle = true;
+ }
+ else if ("Depends" == key)
+ {
+ if (value.empty())
+ value = "R";
+ else
+ value.append(", R");
+ metadata->deps_interface->set_build_depend(value);
+ metadata->deps_interface->set_run_depend(value);
+ }
+ else if ("Suggests" == key)
+ metadata->deps_interface->set_suggested_depend(value);
+ }
+#endif
+}
+
+CRANPackageID::CRANPackageID(const Environment * const e,
+ const tr1::shared_ptr<const CRANRepository> & c, const CRANPackageID * const r, const std::string & t) :
+ PrivateImplementationPattern<CRANPackageID>(new Implementation<CRANPackageID>(e, c, r, t)),
+ _imp(PrivateImplementationPattern<CRANPackageID>::_imp.get())
+{
+ Context context("When creating contained ID '" + stringify(t) + "' in " + stringify(*r) + "':");
+
+ add_metadata_key(_imp->contained_in_key);
+}
+
+CRANPackageID::~CRANPackageID()
+{
+}
+
+void
+CRANPackageID::need_keys_added() const
+{
+}
+
+void
+CRANPackageID::need_masks_added() const
+{
+}
+
+
+const QualifiedPackageName
+CRANPackageID::name() const
+{
+ return _imp->name;
+}
+
+const VersionSpec
+CRANPackageID::version() const
+{
+ return _imp->version;
+}
+
+const SlotName
+CRANPackageID::slot() const
+{
+ return SlotName("0");
+}
+
+const tr1::shared_ptr<const Repository>
+CRANPackageID::repository() const
+{
+ return _imp->repository;
+}
+
+const tr1::shared_ptr<const MetadataPackageIDKey>
+CRANPackageID::virtual_for_key() const
+{
+ return tr1::shared_ptr<const MetadataPackageIDKey>();
+}
+
+const tr1::shared_ptr<const MetadataSetKey<KeywordNameSet> >
+CRANPackageID::keywords_key() const
+{
+ return tr1::shared_ptr<const MetadataSetKey<KeywordNameSet> >();
+}
+
+const tr1::shared_ptr<const MetadataSetKey<IUseFlagSet> >
+CRANPackageID::iuse_key() const
+{
+ return tr1::shared_ptr<const MetadataSetKey<IUseFlagSet> >();
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<ProvideSpecTree> >
+CRANPackageID::provide_key() const
+{
+ return tr1::shared_ptr<const MetadataSpecTreeKey<ProvideSpecTree> >();
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+CRANPackageID::build_dependencies_key() const
+{
+ return tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >();
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+CRANPackageID::run_dependencies_key() const
+{
+ return tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >();
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+CRANPackageID::post_dependencies_key() const
+{
+ return tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >();
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >
+CRANPackageID::suggested_dependencies_key() const
+{
+ return tr1::shared_ptr<const MetadataSpecTreeKey<DependencySpecTree> >();
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<FetchableURISpecTree> >
+CRANPackageID::fetches_key() const
+{
+ return tr1::shared_ptr<const MetadataSpecTreeKey<FetchableURISpecTree> >();
+}
+
+const tr1::shared_ptr<const MetadataSpecTreeKey<SimpleURISpecTree> >
+CRANPackageID::homepage_key() const
+{
+ return _imp->homepage_key;
+}
+
+const tr1::shared_ptr<const MetadataStringKey>
+CRANPackageID::short_description_key() const
+{
+ return _imp->short_description_key;
+}
+
+const tr1::shared_ptr<const MetadataStringKey>
+CRANPackageID::long_description_key() const
+{
+ return _imp->long_description_key;
+}
+
+const tr1::shared_ptr<const MetadataContentsKey>
+CRANPackageID::contents_key() const
+{
+ return tr1::shared_ptr<const MetadataContentsKey>();
+}
+
+const tr1::shared_ptr<const MetadataTimeKey>
+CRANPackageID::installed_time_key() const
+{
+ return tr1::shared_ptr<const MetadataTimeKey>();
+}
+
+const tr1::shared_ptr<const MetadataStringKey>
+CRANPackageID::source_origin_key() const
+{
+ return tr1::shared_ptr<const MetadataStringKey>();
+}
+
+const tr1::shared_ptr<const MetadataStringKey>
+CRANPackageID::binary_origin_key() const
+{
+ return tr1::shared_ptr<const MetadataStringKey>();
+}
+
+std::size_t
+CRANPackageID::extra_hash_value() const
+{
+ return 0;
+}
+
+bool
+CRANPackageID::arbitrary_less_than_comparison(const PackageID &) const
+{
+ return false;
+}
+
+bool
+CRANPackageID::breaks_portage() const
+{
+ return true;
+}
+
+const std::string
+CRANPackageID::canonical_form(const PackageIDCanonicalForm f) const
+{
+ switch (f)
+ {
+ case idcf_full:
+ return stringify(_imp->name) + "-" + stringify(_imp->version) + ":" + stringify(slot()) + "::" + stringify(_imp->repository->name());
+
+ case idcf_version:
+ return stringify(_imp->version);
+
+ case idcf_no_version:
+ return stringify(_imp->name) + ":" + stringify(slot()) + "::" + stringify(_imp->repository->name());
+
+ case last_idcf:
+ break;
+ }
+
+ throw InternalError(PALUDIS_HERE, "Bad PackageIDCanonicalForm");
+}
+
+namespace
+{
+ struct SupportsActionQuery :
+ ConstVisitor<SupportsActionTestVisitorTypes>
+ {
+ bool result;
+ const tr1::shared_ptr<const CRANRepository> cran_repository;
+ const tr1::shared_ptr<const CRANInstalledRepository> cran_installed_repository;
+
+ SupportsActionQuery(const tr1::shared_ptr<const CRANRepository> & c, const tr1::shared_ptr<const CRANInstalledRepository> & r) :
+ result(false),
+ cran_repository(c),
+ cran_installed_repository(r)
+ {
+ }
+
+ void visit(const SupportsActionTest<InstalledAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<FetchAction> &)
+ {
+ result = cran_repository;
+ }
+
+ void visit(const SupportsActionTest<InstallAction> &)
+ {
+ result = cran_repository;
+ }
+
+ void visit(const SupportsActionTest<ConfigAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<PretendAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<UninstallAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<InfoAction> &)
+ {
+ }
+ };
+}
+
+bool
+CRANPackageID::supports_action(const SupportsActionTestBase & b) const
+{
+ SupportsActionQuery q(_imp->cran_repository, _imp->cran_installed_repository);
+ b.accept(q);
+ return q.result;
+}
+
+void
+CRANPackageID::perform_action(Action & a) const
+{
+ throw UnsupportedActionError(*this, a);
+}
+
+const tr1::shared_ptr<const MetadataSetKey<PackageIDSequence> >
+CRANPackageID::contains_key() const
+{
+ return _imp->contains_key;
+}
+
+const tr1::shared_ptr<const MetadataPackageIDKey>
+CRANPackageID::contained_in_key() const
+{
+ return _imp->contained_in_key;
+}
+
+const tr1::shared_ptr<const MetadataFSEntryKey>
+CRANPackageID::fs_location_key() const
+{
+ return _imp->fs_location_key;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_package_id.hh b/0.26.0_alpha1/paludis/repositories/cran/cran_package_id.hh
new file mode 100644
index 000000000..bb53e12fb
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_package_id.hh
@@ -0,0 +1,94 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_CRAN_PACKAGE_ID_HH
+#define PALUDIS_GUARD_PALUDIS_CRAN_PACKAGE_ID_HH 1
+
+#include <paludis/package_id.hh>
+#include <paludis/util/fs_entry.hh>
+
+namespace paludis
+{
+ class CRANRepository;
+ class CRANInstalledRepository;
+
+ namespace cranrepository
+ {
+ class PALUDIS_VISIBLE CRANPackageID :
+ public PackageID,
+ private PrivateImplementationPattern<CRANPackageID>,
+ public tr1::enable_shared_from_this<CRANPackageID>
+ {
+ private:
+ Implementation<CRANPackageID> * const _imp;
+
+ protected:
+ virtual void need_keys_added() const;
+ virtual void need_masks_added() const;
+
+ public:
+ CRANPackageID(const Environment * const, const tr1::shared_ptr<const CRANRepository> &,
+ const FSEntry &);
+ CRANPackageID(const Environment * const, const tr1::shared_ptr<const CRANRepository> &,
+ const CRANPackageID * const, const std::string &);
+ ~CRANPackageID();
+
+ 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 MetadataPackageIDKey> virtual_for_key() const;
+ virtual const tr1::shared_ptr<const MetadataSetKey<KeywordNameSet> > keywords_key() const;
+ virtual const tr1::shared_ptr<const MetadataSetKey<IUseFlagSet> > iuse_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<FetchableURISpecTree> > fetches_key() const;
+ virtual const tr1::shared_ptr<const MetadataSpecTreeKey<SimpleURISpecTree> > 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 const tr1::shared_ptr<const MetadataSetKey<PackageIDSequence> > contains_key() const;
+ virtual const tr1::shared_ptr<const MetadataPackageIDKey> contained_in_key() const;
+ virtual const tr1::shared_ptr<const MetadataFSEntryKey> fs_location_key() const;
+
+ virtual bool supports_action(const SupportsActionTestBase &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual void perform_action(Action &) const PALUDIS_ATTRIBUTE((noreturn));
+
+ virtual bool breaks_portage() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool arbitrary_less_than_comparison(const PackageID &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::size_t extra_hash_value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_repository.cc b/0.26.0_alpha1/paludis/repositories/cran/cran_repository.cc
new file mode 100644
index 000000000..7581cc59f
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_repository.cc
@@ -0,0 +1,503 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Danny van Dyk <kugelfang@gentoo.org>
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/hashed_containers.hh>
+#include <paludis/util/config_file.hh>
+#include <paludis/dep_spec.hh>
+#include <paludis/environment.hh>
+#include <paludis/action.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/repositories/cran/cran_package_id.hh>
+#include <paludis/repositories/cran/cran_repository.hh>
+#include <paludis/repository_maker.hh>
+#include <paludis/repository_info.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/options.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/map.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/mutex.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/tr1_functional.hh>
+#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/visitor-impl.hh>
+
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+
+#include <functional>
+#include <algorithm>
+
+/** \file
+ * Implementation CRANRepository.
+ *
+ * \ingroup grpcranrepository
+ */
+
+using namespace paludis;
+
+#include <paludis/repositories/cran/cran_repository-sr.cc>
+
+typedef MakeHashedMap<QualifiedPackageName, tr1::shared_ptr<const cranrepository::CRANPackageID> >::Type IDMap;
+
+namespace paludis
+{
+ /**
+ * Implementation data for a CRANRepository.
+ *
+ * \ingroup grperepository
+ */
+ template <>
+ struct Implementation<CRANRepository>
+ {
+ CRANRepositoryParams params;
+
+ mutable tr1::shared_ptr<Mutex> big_nasty_mutex;
+ mutable bool has_ids;
+ mutable IDMap ids;
+
+ Implementation(const CRANRepositoryParams &, const tr1::shared_ptr<Mutex> &);
+ ~Implementation();
+ };
+}
+
+Implementation<CRANRepository>::Implementation(const CRANRepositoryParams & p, const tr1::shared_ptr<Mutex> & m) :
+ params(p),
+ big_nasty_mutex(m),
+ has_ids(false)
+{
+}
+
+Implementation<CRANRepository>::~Implementation()
+{
+}
+
+
+CRANRepository::CRANRepository(const CRANRepositoryParams & p) :
+ Repository(CRANRepository::fetch_repo_name(stringify(p.location)),
+ RepositoryCapabilities::create()
+ .installed_interface(0)
+ .sets_interface(this)
+ .syncable_interface(this)
+ .use_interface(0)
+ .world_interface(0)
+ .environment_variable_interface(0)
+ .make_virtuals_interface(0)
+ .mirrors_interface(0)
+ .provides_interface(0)
+ .destination_interface(0)
+ .virtuals_interface(0)
+ .licenses_interface(0)
+ .e_interface(0)
+ .qa_interface(0)
+ .hook_interface(0)
+ .manifest_interface(0),
+ "cran"),
+ PrivateImplementationPattern<CRANRepository>(new Implementation<CRANRepository>(p, make_shared_ptr(new Mutex)))
+{
+ tr1::shared_ptr<RepositoryInfoSection> config_info(new RepositoryInfoSection("Configuration information"));
+
+ config_info->add_kv("location", stringify(_imp->params.location));
+ config_info->add_kv("distdir", stringify(_imp->params.distdir));
+ config_info->add_kv("format", "cran");
+ config_info->add_kv("builddir", stringify(_imp->params.builddir));
+ config_info->add_kv("library", stringify(_imp->params.library));
+ config_info->add_kv("sync", _imp->params.sync);
+
+ _info->add_section(config_info);
+}
+
+CRANRepository::~CRANRepository()
+{
+}
+
+bool
+CRANRepository::do_has_category_named(const CategoryNamePart & c) const
+{
+ return "cran" == stringify(c);
+}
+
+bool
+CRANRepository::do_has_package_named(const QualifiedPackageName & q) const
+{
+ Context context("When checking for package '" + stringify(q) + "' in " + stringify(name()) + ":");
+ Lock l(*_imp->big_nasty_mutex);
+
+ if (! do_has_category_named(q.category))
+ return false;
+
+ need_ids();
+ return _imp->ids.end() != _imp->ids.find(q);
+}
+
+tr1::shared_ptr<const CategoryNamePartSet>
+CRANRepository::do_category_names() const
+{
+ Context context("When fetching category names in " + stringify(name()) + ":");
+ Lock l(*_imp->big_nasty_mutex);
+
+ tr1::shared_ptr<CategoryNamePartSet> result(new CategoryNamePartSet);
+ result->insert(CategoryNamePart("cran"));
+
+ return result;
+}
+
+tr1::shared_ptr<const QualifiedPackageNameSet>
+CRANRepository::do_package_names(const CategoryNamePart & c) const
+{
+ Context context("When fetching package names in category '" + stringify(c)
+ + "' in " + stringify(name()) + ":");
+ Lock l(*_imp->big_nasty_mutex);
+
+ tr1::shared_ptr<QualifiedPackageNameSet> result(new QualifiedPackageNameSet);
+ if (! do_has_category_named(c))
+ return result;
+
+ need_ids();
+
+ std::copy(_imp->ids.begin(), _imp->ids.end(), transform_inserter(result->inserter(),
+ tr1::mem_fn(&std::pair<const QualifiedPackageName, tr1::shared_ptr<const cranrepository::CRANPackageID> >::first)));
+
+ return result;
+}
+
+tr1::shared_ptr<const PackageIDSequence>
+CRANRepository::do_package_ids(const QualifiedPackageName & n) const
+{
+ Context context("When fetching versions of '" + stringify(n) + "' in "
+ + stringify(name()) + ":");
+ Lock l(*_imp->big_nasty_mutex);
+
+ tr1::shared_ptr<PackageIDSequence> result(new PackageIDSequence);
+ if (! do_has_package_named(n))
+ return result;
+
+ need_ids();
+
+ IDMap::const_iterator i(_imp->ids.find(n));
+ if (i != _imp->ids.end())
+ result->push_back(i->second);
+ return result;
+}
+
+void
+CRANRepository::need_ids() const
+{
+ Lock l(*_imp->big_nasty_mutex);
+
+ if (_imp->has_ids)
+ return;
+
+ Context context("When loading IDs for " + stringify(name()) + ":");
+
+ for (DirIterator d(_imp->params.location), d_end ; d != d_end ; ++d)
+ if (is_file_with_extension(*d, ".DESCRIPTION", IsFileWithOptions()))
+ {
+ tr1::shared_ptr<cranrepository::CRANPackageID> id(new cranrepository::CRANPackageID(_imp->params.environment,
+ shared_from_this(), *d));
+ if (! _imp->ids.insert(std::make_pair(id->name(), id)).second)
+ Log::get_instance()->message(ll_warning, lc_context) << "Couldn't insert package '" << *id << "' due to name collision";
+
+ if (id->contains_key())
+ for (PackageIDSequence::ConstIterator i(id->contains_key()->value()->begin()),
+ i_end(id->contains_key()->value()->end()) ; i != i_end ; ++i)
+ if (! _imp->ids.insert(std::make_pair((*i)->name(),
+ tr1::static_pointer_cast<const cranrepository::CRANPackageID>(*i))).second)
+ Log::get_instance()->message(ll_warning, lc_context) << "Couldn't insert package '" << **i
+ << "', which is contained in '" << *id << "', due to name collision";
+ }
+
+ _imp->has_ids = true;
+}
+
+RepositoryName
+CRANRepository::fetch_repo_name(const std::string & location)
+{
+ std::string modified_location(FSEntry(location).basename());
+ std::replace(modified_location.begin(), modified_location.end(), '/', '-');
+ if (modified_location == "cran")
+ return RepositoryName("cran");
+ else
+ return RepositoryName("cran-" + modified_location);
+}
+
+#if 0
+void
+CRANRepository::do_install(const tr1::shared_ptr<const PackageID> & id_uncasted, const InstallOptions & o) const
+{
+ if (id_uncasted->repository().get() != this)
+ throw PackageInstallActionError("Couldn't install '" + stringify(*id_uncasted) + "' using repository '" +
+ stringify(name()) + "'");
+
+ const tr1::shared_ptr<const CRANPackageID> id(tr1::static_pointer_cast<const CRANPackageID>(id_uncasted));
+ if (id->bundle_member_key())
+ return;
+
+ tr1::shared_ptr<const FSEntrySequence> bashrc_files(_imp->params.environment->bashrc_files());
+
+ Command cmd(Command(LIBEXECDIR "/paludis/cran.bash fetch")
+ .with_setenv("CATEGORY", "cran")
+ .with_setenv("DISTDIR", stringify(_imp->params.distdir))
+ .with_setenv("DISTFILE", id->native_package() + "_" + id->native_version() + ".tar.gz")
+ .with_setenv("PN", id->native_package())
+ .with_setenv("PV", id->native_version())
+ .with_setenv("PALUDIS_CRAN_MIRRORS", _imp->params.mirror)
+ .with_setenv("PALUDIS_EBUILD_DIR", std::string(LIBEXECDIR "/paludis/"))
+ .with_setenv("PALUDIS_EBUILD_LOG_LEVEL", stringify(Log::get_instance()->log_level()))
+ .with_setenv("PALUDIS_BASHRC_FILES", join(bashrc_files->begin(), bashrc_files->end(), " ")));
+
+ if (0 != run_command(cmd))
+ throw PackageInstallActionError("Couldn't fetch sources for '" + stringify(*id) + "'");
+
+ if (o.fetch_only)
+ return;
+
+ FSEntry image(_imp->params.buildroot / stringify(id->native_package()) / "image");
+ FSEntry workdir(_imp->params.buildroot / stringify(id->native_package()) / "work");
+
+ if (! o.destination)
+ throw PackageInstallActionError("Can't merge '" + stringify(*id) + "' because no destination was provided.");
+
+ cmd = Command(LIBEXECDIR "/paludis/cran.bash clean install")
+ .with_sandbox()
+ .with_setenv("CATEGORY", "cran")
+ .with_setenv("DISTDIR", stringify(_imp->params.distdir))
+ .with_setenv("DISTFILE", id->native_package() + "_" + id->native_version() + ".tar.gz")
+ .with_setenv("IMAGE", stringify(image))
+ .with_setenv("IS_BUNDLE", (id->bundle_key() ? "yes" : ""))
+ .with_setenv("LOCATION", stringify(_imp->params.location))
+ .with_setenv("PN", id->native_package())
+ .with_setenv("PV", id->native_version())
+ .with_setenv("PALUDIS_CRAN_LIBRARY", stringify(_imp->params.library))
+ .with_setenv("PALUDIS_EBUILD_DIR", std::string(LIBEXECDIR "/paludis/"))
+ .with_setenv("PALUDIS_EBUILD_LOG_LEVEL", stringify(Log::get_instance()->log_level()))
+ .with_setenv("PALUDIS_BASHRC_FILES", join(bashrc_files->begin(), bashrc_files->end(), " "))
+ .with_setenv("ROOT", stringify(o.destination->installed_interface->root()))
+ .with_setenv("WORKDIR", stringify(workdir));
+
+ if (0 != run_command(cmd))
+ throw PackageInstallActionError("Couldn't install '" + stringify(*id) + "' to '" +
+ stringify(image) + "'");
+
+ MergeOptions m(id, image, FSEntry("/dev/null"));
+
+ if (! o.destination->destination_interface)
+ throw PackageInstallActionError("Couldn't install '" + stringify(*id) + "' to '" +
+ stringify(o.destination->name()) + "' because it does not provide destination_interface");
+
+ if (! o.destination->installed_interface)
+ throw PackageInstallActionError("Couldn't install '" + stringify(*id) + "' to '" +
+ stringify(o.destination->name()) + "' because it does not provide installed_interface");
+
+ o.destination->destination_interface->merge(m);
+
+ cmd = Command(LIBEXECDIR "/paludis/cran.bash clean")
+ .with_setenv("IMAGE", stringify(image))
+ .with_setenv("PN", id->native_package())
+ .with_setenv("PV", id->native_version())
+ .with_setenv("PALUDIS_CRAN_LIBRARY", stringify(_imp->params.library))
+ .with_setenv("PALUDIS_EBUILD_DIR", std::string(LIBEXECDIR "/paludis/"))
+ .with_setenv("PALUDIS_EBUILD_LOG_LEVEL", stringify(Log::get_instance()->log_level()))
+ .with_setenv("PALUDIS_BASHRC_FILES", join(bashrc_files->begin(), bashrc_files->end(), " "))
+ .with_setenv("ROOT", stringify(o.destination->installed_interface->root()))
+ .with_setenv("WORKDIR", stringify(workdir))
+ .with_setenv("REPOSITORY", stringify(name()));
+
+ if (0 != run_command(cmd))
+ throw PackageInstallActionError("Couldn't clean '" + stringify(*id) + "'");
+
+ return;
+}
+#endif
+
+tr1::shared_ptr<SetSpecTree::ConstItem>
+CRANRepository::do_package_set(const SetName & s) const
+{
+ if ("base" == s.data())
+ {
+ /**
+ * \todo Implement system as all package which are installed
+ * by dev-lang/R by default.
+ */
+ return tr1::shared_ptr<SetSpecTree::ConstItem>(new ConstTreeSequence<SetSpecTree, AllDepSpec>(
+ tr1::shared_ptr<AllDepSpec>(new AllDepSpec)));
+ }
+ else
+ return tr1::shared_ptr<SetSpecTree::ConstItem>();
+}
+
+tr1::shared_ptr<const SetNameSet>
+CRANRepository::sets_list() const
+{
+ Context context("While generating the list of sets:");
+
+ tr1::shared_ptr<SetNameSet> result(new SetNameSet);
+ result->insert(SetName("base"));
+ return result;
+}
+
+bool
+CRANRepository::do_sync() const
+{
+ Context context("When syncing repository '" + stringify(name()) + "':");
+ Lock l(*_imp->big_nasty_mutex);
+
+ std::string cmd("rsync --delete --recursive --progress --exclude \"*.html\" --exclude \"*.INDEX\" '" +
+ _imp->params.sync + "/src/contrib/Descriptions/' ./");
+
+ if (0 != run_command(Command(cmd).with_chdir(_imp->params.location)))
+ return false;
+
+ cmd = "rsync --progress '" + _imp->params.sync + "/src/contrib/PACKAGES' ./";
+
+ if (0 != run_command(Command(cmd).with_chdir(_imp->params.location)))
+ return false;
+
+ cmd = "rsync --progress '" + _imp->params.sync + "/CRAN_mirrors.csv' ./";
+
+ return 0 == run_command(Command(cmd).with_chdir(_imp->params.location));
+}
+
+tr1::shared_ptr<Repository>
+CRANRepository::make_cran_repository(
+ Environment * const env,
+ tr1::shared_ptr<const Map<std::string, std::string> > m)
+{
+ Context context("When making CRAN repository from repo_file '" +
+ (m->end() == m->find("repo_file") ? std::string("?") : m->find("repo_file")->second) + "':");
+
+ std::string location;
+ if (m->end() == m->find("location") || ((location = m->find("location")->second)).empty())
+ throw CRANRepositoryConfigurationError("Key 'location' not specified or empty");
+
+ std::string library;
+ if (m->end() == m->find("library") || ((library = m->find("library")->second)).empty())
+ throw CRANRepositoryConfigurationError("Key 'library' not specified or empty");
+
+ std::string distdir;
+ if (m->end() == m->find("distdir") || ((distdir = m->find("distdir")->second)).empty())
+ distdir = location + "/distfiles";
+
+ std::string mirror;
+ if (m->end() == m->find("mirror") || ((mirror = m->find("mirror")->second)).empty())
+ mirror = "http://cran.r-project.org/";
+
+ std::string sync;
+ if (m->end() == m->find("sync") || ((sync = m->find("sync")->second)).empty())
+ sync = "rsync://cran.r-project.org/CRAN";
+
+ std::string builddir;
+ if (m->end() == m->find("builddir") || ((builddir = m->find("builddir")->second)).empty())
+ {
+ if (m->end() == m->find("buildroot") || ((builddir = m->find("buildroot")->second)).empty())
+ builddir = "/var/tmp/paludis";
+ else
+ Log::get_instance()->message(ll_warning, lc_context) << "Key 'buildroot' is deprecated, use 'builddir' instead";
+ }
+
+ return tr1::shared_ptr<Repository>(new CRANRepository(CRANRepositoryParams::create()
+ .environment(env)
+ .location(location)
+ .distdir(distdir)
+ .sync(sync)
+ .builddir(builddir)
+ .library(library)
+ .mirror(mirror)));
+}
+
+CRANRepositoryConfigurationError::CRANRepositoryConfigurationError(
+ const std::string & msg) throw () :
+ ConfigurationError("CRAN repository configuration error: " + msg)
+{
+}
+
+
+void
+CRANRepository::invalidate()
+{
+ _imp.reset(new Implementation<CRANRepository>(_imp->params, _imp->big_nasty_mutex));
+}
+
+void
+CRANRepository::invalidate_masks()
+{
+}
+
+namespace
+{
+ struct SupportsActionQuery :
+ ConstVisitor<SupportsActionTestVisitorTypes>
+ {
+ bool result;
+
+ SupportsActionQuery() :
+ result(false)
+ {
+ }
+
+ void visit(const SupportsActionTest<InstalledAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<InstallAction> &)
+ {
+ result = true;
+ }
+
+ void visit(const SupportsActionTest<ConfigAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<PretendAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<FetchAction> &)
+ {
+ result = true;
+ }
+
+ void visit(const SupportsActionTest<UninstallAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<InfoAction> &)
+ {
+ }
+ };
+}
+
+bool
+CRANRepository::do_some_ids_might_support_action(const SupportsActionTestBase & a) const
+{
+ SupportsActionQuery q;
+ a.accept(q);
+ return q.result;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_repository.hh b/0.26.0_alpha1/paludis/repositories/cran/cran_repository.hh
new file mode 100644
index 000000000..b36ddd081
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_repository.hh
@@ -0,0 +1,137 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_CRAN_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_CRAN_REPOSITORY_HH 1
+
+#include <paludis/repository.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/map-fwd.hh>
+#include <paludis/util/tr1_memory.hh>
+#include <paludis/environment-fwd.hh>
+#include <string>
+
+/** \file
+ * Declaration for the CRANRepository class.
+ *
+ * \ingroup grpcranrepository
+ */
+
+namespace paludis
+{
+ class PackageDatabase;
+
+#include <paludis/repositories/cran/cran_repository-sr.hh>
+
+ /**
+ * A CRANRepository is a Repository that handles the layout used by
+ * the GNU R project for the Comprehensive R Archive Network
+ *
+ * \ingroup grpcranrepository
+ */
+ class PALUDIS_VISIBLE CRANRepository :
+ public Repository,
+ public RepositorySyncableInterface,
+ public RepositorySetsInterface,
+ private PrivateImplementationPattern<CRANRepository>,
+ public tr1::enable_shared_from_this<CRANRepository>
+ {
+ private:
+ void need_ids() const;
+
+ protected:
+ /**
+ * Try to get the repository name for a particular repository.
+ */
+ static RepositoryName fetch_repo_name(const std::string & location);
+
+ /* RepositorySyncableInterface */
+
+ virtual tr1::shared_ptr<SetSpecTree::ConstItem> do_package_set(const SetName &) const;
+
+ virtual tr1::shared_ptr<const SetNameSet> sets_list() const;
+
+ /* RepositorySyncableInterface */
+
+ virtual bool do_sync() const;
+
+ /* Repository */
+
+ virtual tr1::shared_ptr<const QualifiedPackageNameSet> do_package_names(
+ const CategoryNamePart &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const CategoryNamePartSet> do_category_names() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool do_has_category_named(const CategoryNamePart &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const PackageIDSequence> do_package_ids(
+ const QualifiedPackageName &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool do_some_ids_might_support_action(const SupportsActionTestBase &) const;
+
+ public:
+ /**
+ * Constructor.
+ */
+ CRANRepository(const CRANRepositoryParams &);
+
+ /**
+ * Virtual constructor.
+ */
+ static tr1::shared_ptr<Repository> make_cran_repository(
+ Environment * const env,
+ tr1::shared_ptr<const Map<std::string, std::string> > m);
+
+ /**
+ * Destructor.
+ */
+ virtual ~CRANRepository();
+
+ virtual void invalidate();
+ virtual void invalidate_masks();
+ };
+
+ /**
+ * Thrown if invalid parameters are provided for
+ * CRANRepository::make_cran_repository.
+ *
+ * \ingroup grpexceptions
+ * \ingroup grpcranrepository
+ */
+ class PALUDIS_VISIBLE CRANRepositoryConfigurationError :
+ public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ CRANRepositoryConfigurationError(const std::string & msg) throw ();
+ };
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_repository.sr b/0.26.0_alpha1/paludis/repositories/cran/cran_repository.sr
new file mode 100644
index 000000000..fb5732dd7
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_repository.sr
@@ -0,0 +1,28 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et :
+
+make_class_CRANRepositoryParams()
+{
+ visible
+
+ key environment "const Environment *"
+ key location FSEntry
+ key distdir FSEntry
+ key mirror std::string
+ key sync std::string
+ key builddir FSEntry
+ key library FSEntry
+
+ doxygen_comment << "END"
+ /**
+ * Parameters used to create a CRANRepository
+ *
+ * \see CRANRepository
+ * \ingroup grpcranrepository
+ * \nosubgrouping
+ */
+END
+
+ allow_named_args
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_repository_TEST.cc b/0.26.0_alpha1/paludis/repositories/cran/cran_repository_TEST.cc
new file mode 100644
index 000000000..006c1efd7
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_repository_TEST.cc
@@ -0,0 +1,79 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Danny van Dyk <kugelfang@gentoo.org>
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/dep_spec.hh>
+#include <paludis/dep_spec_flattener.hh>
+#include <paludis/repositories/cran/cran_dep_parser.hh>
+#include <paludis/repositories/cran/cran_package_id.hh>
+#include <paludis/repositories/cran/cran_repository.hh>
+#include <paludis/environments/test/test_environment.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/map.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace test;
+using namespace paludis;
+
+namespace test_cases
+{
+ struct CRANRepositoryPackagesTest : TestCase
+ {
+ CRANRepositoryPackagesTest() : TestCase("PACKAGES") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(new Map<std::string, std::string>);
+ keys->insert("format", "cran");
+ keys->insert("library", "cran_repository_TEST_dir/library");
+ keys->insert("location", "cran_repository_TEST_dir/repo1");
+ keys->insert("builddir", "cran_repository_TEST_dir/tmp");
+ tr1::shared_ptr<Repository> repo(CRANRepository::make_cran_repository(
+ &env, keys));
+ TEST_CHECK(repo->has_category_named(CategoryNamePart("cran")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cran/testpackage1")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cran/testpackage2")));
+ }
+ } test_cran_repository_packages;
+
+ struct CRANRepositoryBundleTest: TestCase
+ {
+ CRANRepositoryBundleTest() : TestCase("Bundle") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(new Map<std::string, std::string>);
+ keys->insert("format", "cran");
+ keys->insert("library", "cran_repository_TEST_dir/library");
+ keys->insert("location", "cran_repository_TEST_dir/repo2");
+ keys->insert("builddir", "cran_repository_TEST_dir/tmp");
+ tr1::shared_ptr<Repository> repo(CRANRepository::make_cran_repository(
+ &env, keys));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cran/testbundle")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cran/bundlepkg1")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cran/bundlepkg2")));
+ }
+ } test_cran_repository_bundle;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_repository_TEST_cleanup.sh b/0.26.0_alpha1/paludis/repositories/cran/cran_repository_TEST_cleanup.sh
new file mode 100755
index 000000000..d30492240
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_repository_TEST_cleanup.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d cran_repository_TEST_dir ] ; then
+ rm -fr cran_repository_TEST_dir
+else
+ true
+fi
diff --git a/0.26.0_alpha1/paludis/repositories/cran/cran_repository_TEST_setup.sh b/0.26.0_alpha1/paludis/repositories/cran/cran_repository_TEST_setup.sh
new file mode 100755
index 000000000..93fdbee71
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/cran_repository_TEST_setup.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir cran_repository_TEST_dir || exit 1
+cd cran_repository_TEST_dir || exit 1
+
+# repo1
+mkdir -p repo1
+cat <<EOF >> repo1/PACKAGES
+Package: testpackage1
+Version: 2006.05.08
+Title: Test on a well formed PACKAGES file
+Depends: R (>= 2.0.0)
+
+
+Package: testpackage2
+Version: 2006.05.08
+Title: Test on a well formed PACKAGES file
+EOF
+cat <<EOF >> repo1/testpackage1.DESCRIPTION
+Package: testpackage1
+Version: 2006.05.08
+Title: Test on a well formed PACKAGES file
+Depends: R (>= 2.0.0)
+Description: This description
+ spans
+ multiple lines without
+ trailing backslashes or leading tabs :-/
+License: Some weirdo license string
+Packaged: Mon May 08 12:00:00 2006; kugelfang
+EOF
+cat <<EOF >> repo1/testpackage2.DESCRIPTION
+Package: testpackage2
+Version: 1
+Title: 2nd Test Packages
+Depends: R, testpackage1
+License: Another weirdo license string
+Packaged: Mon May 08 22:00:00 2006; kugelfang
+EOF
+
+mkdir -p repo2
+cat <<EOF >> repo2/PACKAGES
+Package: testbundle
+Version: 1
+Title: Testbundle for bundlepkg1 and bundlepkg2
+Bundle: testbundle
+Contains: bundlepkg1 bundlepkg2
+EOF
+cat <<EOF >> repo2/testbundle.DESCRIPTION
+Bundle: testbundle
+Version: 1
+Date: 21 May 2006
+Title: Testbundle for bundlepkg1 and bundlepkg2
+Contains: bundlepkg1 bundlepkg2
+License: Weird obfuscation of GPL
+Packaged: Sun May 21 12:34:56 2006; kugelfang
+EOF
diff --git a/0.26.0_alpha1/paludis/repositories/cran/dep_spec_pretty_printer.cc b/0.26.0_alpha1/paludis/repositories/cran/dep_spec_pretty_printer.cc
new file mode 100644
index 000000000..78877b85c
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/dep_spec_pretty_printer.cc
@@ -0,0 +1,130 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/cran/dep_spec_pretty_printer.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/environment.hh>
+#include <paludis/query.hh>
+#include <paludis/package_database.hh>
+#include <ostream>
+#include <sstream>
+
+using namespace paludis;
+using namespace paludis::cranrepository;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<DepSpecPrettyPrinter>
+ {
+ std::stringstream s;
+ const Environment * const env;
+ GenericSpecTree::ItemFormatter formatter;
+ const unsigned indent;
+ const bool multiline;
+ bool need_comma;
+
+ Implementation(
+ const Environment * const e,
+ const GenericSpecTree::ItemFormatter & f,
+ const unsigned u,
+ const bool m) :
+ env(e),
+ formatter(f),
+ indent(u),
+ multiline(m),
+ need_comma(false)
+ {
+ }
+ };
+}
+
+DepSpecPrettyPrinter::DepSpecPrettyPrinter(const Environment * const e,
+ const GenericSpecTree::ItemFormatter & f, const unsigned initial_indent, const bool multiline) :
+ PrivateImplementationPattern<DepSpecPrettyPrinter>(new Implementation<DepSpecPrettyPrinter>(e, f, initial_indent, multiline))
+{
+}
+
+DepSpecPrettyPrinter::~DepSpecPrettyPrinter()
+{
+}
+
+void
+DepSpecPrettyPrinter::visit_leaf(const PackageDepSpec & p)
+{
+ if (_imp->multiline)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_comma)
+ _imp->s << ", ";
+ else
+ _imp->need_comma = true;
+
+ if (_imp->env)
+ {
+ if (! _imp->env->package_database()->query(query::Matches(p) &
+ query::InstalledAtRoot(_imp->env->root()), qo_whatever)->empty())
+ _imp->s << _imp->formatter.format(p, format::Installed());
+ else if (! _imp->env->package_database()->query(query::Matches(p) &
+ query::SupportsAction<InstallAction>() & query::NotMasked(), qo_whatever)->empty())
+ _imp->s << _imp->formatter.format(p, format::Installable());
+ else
+ _imp->s << _imp->formatter.format(p, format::Plain());
+ }
+ else
+ _imp->s << _imp->formatter.format(p, format::Plain());
+
+ if (_imp->multiline)
+ _imp->s << _imp->formatter.newline();
+}
+
+void
+DepSpecPrettyPrinter::visit_leaf(const BlockDepSpec &)
+{
+}
+
+void
+DepSpecPrettyPrinter::visit_leaf(const DependencyLabelsDepSpec &)
+{
+}
+
+void
+DepSpecPrettyPrinter::visit_leaf(const NamedSetDepSpec & p)
+{
+ if (_imp->multiline)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_comma)
+ _imp->s << ", ";
+ else
+ _imp->need_comma = true;
+
+ _imp->s << _imp->formatter.format(p, format::Plain());
+
+ if (_imp->multiline)
+ _imp->s << _imp->formatter.newline();
+}
+
+std::ostream &
+paludis::cranrepository::operator<< (std::ostream & s, const DepSpecPrettyPrinter & p)
+{
+ s << p._imp->s.str();
+ return s;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/dep_spec_pretty_printer.hh b/0.26.0_alpha1/paludis/repositories/cran/dep_spec_pretty_printer.hh
new file mode 100644
index 000000000..e0d7d138e
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/dep_spec_pretty_printer.hh
@@ -0,0 +1,90 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_CRAN_DEP_SPEC_PRETTY_PRINTER_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_CRAN_DEP_SPEC_PRETTY_PRINTER_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/dep_tree.hh>
+#include <paludis/dep_spec-fwd.hh>
+#include <paludis/formatter.hh>
+#include <paludis/environment-fwd.hh>
+#include <iosfwd>
+
+namespace paludis
+{
+ namespace cranrepository
+ {
+ /**
+ * Pretty printer for CRAN dep heirarchies.
+ *
+ * \ingroup grpcranrepository
+ */
+ class PALUDIS_VISIBLE DepSpecPrettyPrinter :
+ private PrivateImplementationPattern<DepSpecPrettyPrinter>,
+ public ConstVisitor<DependencySpecTree>,
+ public ConstVisitor<DependencySpecTree>::VisitConstSequence<DepSpecPrettyPrinter, AllDepSpec>,
+ public ConstVisitor<DependencySpecTree>::VisitConstSequence<DepSpecPrettyPrinter, UseDepSpec>,
+ public ConstVisitor<DependencySpecTree>::VisitConstSequence<DepSpecPrettyPrinter, AnyDepSpec>
+ {
+ friend std::ostream & operator<< (std::ostream &, const DepSpecPrettyPrinter &);
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ /**
+ * Constructor.
+ *
+ * \param env An optional environment, to use for formatting PackageDepSpec items
+ * as format::Installed() etc. May be null, in which case format::Plain() is
+ * always used.
+ *
+ * \param formatter The formatter to use. If no fancy formatting is required, use
+ * StringifyFormatter.
+ *
+ * \param initial_indent Amount of indenting to use. Should probably be 0 if
+ * use_newlines is false.
+ *
+ * \param use_newlines Whether to format over multiple lines.
+ */
+ DepSpecPrettyPrinter(
+ const Environment * const env,
+ const GenericSpecTree::ItemFormatter & formatter,
+ unsigned initial_indent,
+ bool use_newlines);
+
+ ~DepSpecPrettyPrinter();
+
+ ///\}
+
+ void visit_leaf(const PackageDepSpec &);
+
+ void visit_leaf(const BlockDepSpec &);
+
+ void visit_leaf(const DependencyLabelsDepSpec &);
+
+ void visit_leaf(const NamedSetDepSpec &);
+ };
+
+ std::ostream & operator<< (std::ostream & s, const DepSpecPrettyPrinter & p) PALUDIS_VISIBLE;
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/cran/description_file.cc b/0.26.0_alpha1/paludis/repositories/cran/description_file.cc
new file mode 100644
index 000000000..c5e68e924
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/description_file.cc
@@ -0,0 +1,113 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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 "description_file.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/stringify.hh>
+#include <istream>
+#include <map>
+
+using namespace paludis;
+using namespace paludis::cranrepository;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<DescriptionFile>
+ {
+ std::map<std::string, std::string> values;
+ };
+}
+
+DescriptionFile::DescriptionFile(const Source & s) :
+ ConfigFile(s),
+ PrivateImplementationPattern<DescriptionFile>(new Implementation<DescriptionFile>)
+{
+ Context c("When parsing CRAN description file '" + s.filename() + "':");
+
+ if (! s.stream())
+ throw ConfigFileError(s.filename(), "Cannot read input");
+
+ std::string line, line_full;
+ while (std::getline(s.stream(), line))
+ {
+ /* cran needs to be taken out and shot in the nuts for this... */
+ line = strip_trailing(line, "\r");
+
+ if ((! line.empty()) && (std::string::npos != std::string(" \t").find_first_of(line.at(0))))
+ {
+ if (line_full.empty())
+ throw ConfigFileError(s.filename(), "Unexpected continuation");
+
+ line_full += " ";
+ line_full += strip_leading(strip_trailing(line, " \t"), " \t");
+ }
+ else
+ {
+ if (! line_full.empty())
+ _line(line_full);
+
+ line_full = strip_leading(strip_trailing(line, " \t"), " \t");
+ }
+ }
+
+ if (! line_full.empty())
+ _line(line_full);
+}
+
+DescriptionFile::~DescriptionFile()
+{
+}
+
+void
+DescriptionFile::_line(const std::string & l)
+{
+ std::string::size_type p(l.find(':'));
+ if (std::string::npos == p)
+ Log::get_instance()->message(ll_warning, lc_context) << "No colon on line '" << l << "'";
+ else
+ {
+ std::string key(strip_leading(strip_trailing(l.substr(0, p), " \t"), " \t")),
+ value(strip_leading(strip_trailing(l.substr(p + 1), " \t"), " \t"));
+
+ if (key.empty())
+ ;
+ else if (value.empty())
+ ;
+ else
+ {
+ std::pair<std::map<std::string, std::string>::iterator, bool> r(_imp->values.insert(std::make_pair(key, value)));
+ if ((! r.second) && (r.first->second != value))
+ Log::get_instance()->message(ll_qa, lc_context) << "Key '" << key << "' already set to '"
+ << r.first->second << "', ignoring duplicate key value '" << value << "'";
+ }
+ }
+}
+
+std::string
+DescriptionFile::get(const std::string & k) const
+{
+ std::map<std::string, std::string>::const_iterator i(_imp->values.find(k));
+ if (i == _imp->values.end())
+ return "";
+ return i->second;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/description_file.hh b/0.26.0_alpha1/paludis/repositories/cran/description_file.hh
new file mode 100644
index 000000000..e38cd8e7f
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/description_file.hh
@@ -0,0 +1,49 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_CRAN_DESCRIPTION_FILE_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_CRAN_DESCRIPTION_FILE_HH 1
+
+#include <paludis/util/config_file.hh>
+#include <paludis/util/attributes.hh>
+
+namespace paludis
+{
+ namespace cranrepository
+ {
+ class PALUDIS_VISIBLE DescriptionFile :
+ public ConfigFile,
+ private PrivateImplementationPattern<DescriptionFile>
+ {
+ private:
+ void _line(const std::string &);
+
+ public:
+ DescriptionFile(const Source &);
+ ~DescriptionFile();
+
+ /**
+ * Fetch the value for a particular key, or an empty string.
+ */
+ std::string get(const std::string &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/cran/description_file_TEST.cc b/0.26.0_alpha1/paludis/repositories/cran/description_file_TEST.cc
new file mode 100644
index 000000000..a818a70f3
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/description_file_TEST.cc
@@ -0,0 +1,49 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/cran/description_file.hh>
+#include <test/test_runner.hh>
+#include <test/test_framework.hh>
+#include <sstream>
+
+using namespace paludis;
+using namespace paludis::cranrepository;
+using namespace test;
+
+namespace test_cases
+{
+ struct DescriptionTest : TestCase
+ {
+ DescriptionTest() : TestCase("description test") { }
+
+ void run()
+ {
+ std::stringstream s;
+ s << "Foo: bar bar" << std::endl;
+ s << " black sheep" << std::endl;
+ s << "Moo: cow" << std::endl;
+
+ DescriptionFile f(s);
+ TEST_CHECK_EQUAL(f.get("Foo"), "bar bar black sheep");
+ TEST_CHECK_EQUAL(f.get("Moo"), "cow");
+ TEST_CHECK_EQUAL(f.get("Oink"), "");
+ }
+ } test_description;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/keys.cc b/0.26.0_alpha1/paludis/repositories/cran/keys.cc
new file mode 100644
index 000000000..b30706497
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/keys.cc
@@ -0,0 +1,168 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/cran/keys.hh>
+#include <paludis/repositories/cran/cran_package_id.hh>
+#include <paludis/repositories/cran/cran_dep_parser.hh>
+#include <paludis/repositories/cran/dep_spec_pretty_printer.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/tr1_functional.hh>
+#include <paludis/dep_spec.hh>
+#include <paludis/stringify_formatter-impl.hh>
+#include <paludis/formatter.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+
+using namespace paludis;
+using namespace paludis::cranrepository;
+
+SimpleURIKey::SimpleURIKey(const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataSpecTreeKey<SimpleURISpecTree>(r, h, t),
+ _v(v)
+{
+}
+
+const tr1::shared_ptr<const SimpleURISpecTree::ConstItem>
+SimpleURIKey::value() const
+{
+ return make_shared_ptr(new TreeLeaf<SimpleURISpecTree, SimpleURIDepSpec>(make_shared_ptr(new SimpleURIDepSpec(_v))));
+}
+
+std::string
+SimpleURIKey::pretty_print(const SimpleURISpecTree::ItemFormatter & f) const
+{
+ return f.format(_v, format::Plain());
+}
+
+std::string
+SimpleURIKey::pretty_print_flat(const SimpleURISpecTree::ItemFormatter & f) const
+{
+ return f.format(_v, format::Plain());
+}
+
+StringKey::StringKey(const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataStringKey(r, h, t),
+ _v(v)
+{
+}
+
+const std::string
+StringKey::value() const
+{
+ return _v;
+}
+
+FSLocationKey::FSLocationKey(const std::string & r, const std::string & h,
+ const FSEntry & v, const MetadataKeyType t) :
+ MetadataFSEntryKey(r, h, t),
+ _v(v)
+{
+}
+
+const FSEntry
+FSLocationKey::value() const
+{
+ return _v;
+}
+
+PackageIDSequenceKey::PackageIDSequenceKey(const Environment * const e,
+ const std::string & r, const std::string & h, const MetadataKeyType t) :
+ MetadataSetKey<PackageIDSequence>(r, h, t),
+ _env(e),
+ _v(new PackageIDSequence)
+{
+}
+
+const tr1::shared_ptr<const PackageIDSequence>
+PackageIDSequenceKey::value() const
+{
+ return _v;
+}
+
+void
+PackageIDSequenceKey::push_back(const tr1::shared_ptr<const PackageID> & i)
+{
+ _v->push_back(i);
+}
+
+std::string
+PackageIDSequenceKey::pretty_print_flat(const Formatter<tr1::shared_ptr<const PackageID> > & f) const
+{
+ using namespace tr1::placeholders;
+ return join(value()->begin(), value()->end(), " ", tr1::bind(
+ static_cast<std::string (Formatter<tr1::shared_ptr<const PackageID> >::*)(
+ const tr1::shared_ptr<const PackageID> &, const format::Plain &) const>(
+ &Formatter<tr1::shared_ptr<const PackageID> >::format),
+ tr1::cref(f), _1, format::Plain()));
+}
+
+PackageIDKey::PackageIDKey(const std::string & r, const std::string & h,
+ const CRANPackageID * const v, const MetadataKeyType t) :
+ MetadataPackageIDKey(r, h, t),
+ _v(v)
+{
+}
+
+const tr1::shared_ptr<const PackageID>
+PackageIDKey::value() const
+{
+ return _v->shared_from_this();
+}
+
+DepKey::DepKey(const Environment * const e, const std::string & r, const std::string & h, const std::string & v,
+ const MetadataKeyType t) :
+ MetadataSpecTreeKey<DependencySpecTree>(r, h, t),
+ _env(e),
+ _v(v)
+{
+}
+
+const tr1::shared_ptr<const DependencySpecTree::ConstItem>
+DepKey::value() const
+{
+ Lock l(_m);
+ if (_c)
+ return _c;
+
+ Context context("When parsing CRAN dependency string:");
+ _c = parse_depends(_v);
+ return _c;
+}
+
+std::string
+DepKey::pretty_print(const DependencySpecTree::ItemFormatter & f) const
+{
+ StringifyFormatter ff(f);
+ DepSpecPrettyPrinter p(_env, ff, 12, true);
+ value()->accept(p);
+ return stringify(p);
+}
+
+std::string
+DepKey::pretty_print_flat(const DependencySpecTree::ItemFormatter & f) const
+{
+ StringifyFormatter ff(f);
+ DepSpecPrettyPrinter p(_env, ff, 0, false);
+ value()->accept(p);
+ return stringify(p);
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/keys.hh b/0.26.0_alpha1/paludis/repositories/cran/keys.hh
new file mode 100644
index 000000000..f499c81d5
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/keys.hh
@@ -0,0 +1,137 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_CRAN_KEYS_HH
+#define PALUDIS_GUARD_PALUDIS_PALUDIS_REPOSITORIES_CRAN_KEYS_HH 1
+
+#include <paludis/metadata_key.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/mutex.hh>
+#include <paludis/util/sequence.hh>
+
+namespace paludis
+{
+ namespace cranrepository
+ {
+ class CRANPackageID;
+
+ class SimpleURIKey :
+ public MetadataSpecTreeKey<SimpleURISpecTree>
+ {
+ private:
+ const std::string _v;
+
+ public:
+ SimpleURIKey(const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+
+ virtual const tr1::shared_ptr<const SimpleURISpecTree::ConstItem> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print(const SimpleURISpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print_flat(const SimpleURISpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class StringKey :
+ public MetadataStringKey
+ {
+ private:
+ const std::string _v;
+
+ public:
+ StringKey(const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+
+ virtual const std::string value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class FSLocationKey :
+ public MetadataFSEntryKey
+ {
+ private:
+ const FSEntry _v;
+
+ public:
+ FSLocationKey(const std::string &, const std::string &, const FSEntry &, const MetadataKeyType);
+
+ virtual const FSEntry value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class PackageIDSequenceKey :
+ public MetadataSetKey<PackageIDSequence>
+ {
+ private:
+ const Environment * const _env;
+ const tr1::shared_ptr<PackageIDSequence> _v;
+
+ public:
+ PackageIDSequenceKey(const Environment * const,
+ const std::string &, const std::string &, const MetadataKeyType);
+
+ virtual const tr1::shared_ptr<const PackageIDSequence> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ void push_back(const tr1::shared_ptr<const PackageID> &);
+
+ virtual std::string pretty_print_flat(const Formatter<tr1::shared_ptr<const PackageID> > &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class PackageIDKey :
+ public MetadataPackageIDKey
+ {
+ private:
+ const CRANPackageID * const _v;
+
+ public:
+ PackageIDKey(const std::string &, const std::string &, const CRANPackageID * const, const MetadataKeyType);
+
+ virtual const tr1::shared_ptr<const PackageID> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class DepKey :
+ public MetadataSpecTreeKey<DependencySpecTree>
+ {
+ private:
+ const Environment * const _env;
+ mutable Mutex _m;
+ mutable tr1::shared_ptr<DependencySpecTree::ConstItem> _c;
+ const std::string _v;
+
+ public:
+ DepKey(const Environment * const,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+
+ virtual const tr1::shared_ptr<const DependencySpecTree::ConstItem> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print(const DependencySpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print_flat(const DependencySpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/cran/masks.cc b/0.26.0_alpha1/paludis/repositories/cran/masks.cc
new file mode 100644
index 000000000..9bc1d48e8
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/masks.cc
@@ -0,0 +1,70 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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 "masks.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace paludis;
+using namespace paludis::cranrepository;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<BrokenMask>
+ {
+ const char key;
+ const std::string description;
+ const std::string explanation;
+
+ Implementation(const char k, const std::string & d, const std::string & e) :
+ key(k),
+ description(d),
+ explanation(e)
+ {
+ }
+ };
+}
+
+BrokenMask::BrokenMask(const char c, const std::string & d, const std::string & e) :
+ PrivateImplementationPattern<BrokenMask>(new Implementation<BrokenMask>(c, d, e))
+{
+}
+
+BrokenMask::~BrokenMask()
+{
+}
+
+const char
+BrokenMask::key() const
+{
+ return _imp->key;
+}
+
+const std::string
+BrokenMask::description() const
+{
+ return _imp->description;
+}
+
+const std::string
+BrokenMask::explanation() const
+{
+ return _imp->explanation;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/masks.hh b/0.26.0_alpha1/paludis/repositories/cran/masks.hh
new file mode 100644
index 000000000..ca3b35b31
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/masks.hh
@@ -0,0 +1,45 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_CRAN_MASKS_HH
+#define PALUDIS_GUARD_PALUDIS_PALUDIS_REPOSITORIES_CRAN_MASKS_HH 1
+
+#include <paludis/mask.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace paludis
+{
+ namespace cranrepository
+ {
+ class BrokenMask :
+ public UnsupportedMask,
+ private PrivateImplementationPattern<BrokenMask>
+ {
+ public:
+ BrokenMask(const char, const std::string &, const std::string &);
+ ~BrokenMask();
+
+ virtual const char key() const;
+ virtual const std::string description() const;
+ virtual const std::string explanation() const;
+ };
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/cran/normalise.cc b/0.26.0_alpha1/paludis/repositories/cran/normalise.cc
new file mode 100644
index 000000000..a84c37f6a
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/normalise.cc
@@ -0,0 +1,40 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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 "normalise.hh"
+#include <algorithm>
+
+using namespace paludis;
+
+std::string
+paludis::cranrepository::cran_name_to_internal(const std::string & s)
+{
+ std::string result(s);
+ std::replace(result.begin(),result.end(), '.', '-');
+ return result;
+}
+
+std::string
+paludis::cranrepository::cran_version_to_internal(const std::string & s)
+{
+ std::string result(s);
+ std::replace(result.begin(), result.end(), '-', '.');
+ return result;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/cran/normalise.hh b/0.26.0_alpha1/paludis/repositories/cran/normalise.hh
new file mode 100644
index 000000000..5b0637602
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/normalise.hh
@@ -0,0 +1,35 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_CRAN_NORMALISE_HH
+#define PALUDIS_GUARD_PALUDIS_PALUDIS_REPOSITORIES_CRAN_NORMALISE_HH 1
+
+#include <string>
+#include <paludis/util/attributes.hh>
+
+namespace paludis
+{
+ namespace cranrepository
+ {
+ std::string cran_name_to_internal(const std::string &) PALUDIS_ATTRIBUTE((warn_unused_result));
+ std::string cran_version_to_internal(const std::string &) PALUDIS_ATTRIBUTE((warn_unused_result));
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/cran/registration.cc b/0.26.0_alpha1/paludis/repositories/cran/registration.cc
new file mode 100644
index 000000000..9b5768e44
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/cran/registration.cc
@@ -0,0 +1,42 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/repository_maker.hh>
+#include <paludis/repositories/cran/cran_repository.hh>
+#include <paludis/repositories/cran/cran_installed_repository.hh>
+#include "config.h"
+
+using namespace paludis;
+
+#ifndef MONOLITHIC
+
+extern "C"
+{
+ void PALUDIS_VISIBLE register_repositories(RepositoryMaker * maker);
+}
+
+void register_repositories(RepositoryMaker * maker)
+{
+ maker->register_maker("cran", &CRANRepository::make_cran_repository);
+ maker->register_maker("cran_installed", &CRANInstalledRepository::make_cran_installed_repository);
+}
+
+#endif
+
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/Makefile.am b/0.26.0_alpha1/paludis/repositories/e/Makefile.am
new file mode 100644
index 000000000..4d1022717
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/Makefile.am
@@ -0,0 +1,521 @@
+SUBDIRS = eapis ebuild . qa
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda
+DISTCLEANFILES = \
+ glsa-sr.hh glsa-sr.cc \
+ e_repository_params-sr.hh e_repository_params-sr.cc \
+ e_repository_params-se.hh e_repository_params-se.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 \
+ eapi-sr.hh eapi-sr.cc \
+ dep_parser-se.hh dep_parser-se.cc \
+ manifest2_entry-sr.hh manifest2_entry-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 = \
+ aa_visitor.hh \
+ check_fetched_files_visitor.hh \
+ dep_lexer.hh \
+ dep_parser.hh \
+ dep_parser-se.hh \
+ dep_parser-fwd.hh \
+ dep_spec_pretty_printer.hh \
+ e_key.hh \
+ e_mask.hh \
+ e_repository.hh \
+ e_repository_entries.hh \
+ e_repository_exceptions.hh \
+ e_repository_id.hh \
+ e_repository_mask_file.hh \
+ e_repository_news.hh \
+ e_repository_params-sr.hh \
+ e_repository_params-se.hh \
+ e_repository_params.hh \
+ e_repository_profile.hh \
+ e_repository_profile_file.hh \
+ e_repository_sets.hh \
+ eapi.hh \
+ eapi-sr.hh \
+ eapi-fwd.hh \
+ eapi_phase.hh \
+ ebin-se.hh \
+ ebin-sr.hh \
+ ebin.hh \
+ ebin_entries.hh \
+ ebuild-sr.hh \
+ ebuild.hh \
+ ebuild_entries.hh \
+ ebuild_flat_metadata_cache.hh \
+ ebuild_id.hh \
+ eclass_mtimes.hh \
+ exheres_layout.hh \
+ fetch_visitor.hh \
+ glsa-sr.hh \
+ glsa.hh \
+ layout.hh \
+ make_ebin_repository.hh \
+ make_ebuild_repository.hh \
+ manifest2_entry-sr.hh \
+ manifest2_reader.hh \
+ source_uri_finder.hh \
+ traditional_layout.hh \
+ use_desc.hh \
+ vdb_id.hh \
+ vdb_merger-sr.hh \
+ vdb_merger.hh \
+ vdb_repository-sr.hh \
+ vdb_repository.hh \
+ vdb_unmerger-sr.hh \
+ vdb_unmerger.hh
+
+libpaludiserepository_la_SOURCES = \
+ aa_visitor.cc \
+ dep_lexer.cc \
+ check_fetched_files_visitor.cc \
+ dep_parser.cc \
+ dep_spec_pretty_printer.cc \
+ e_key.cc \
+ e_mask.cc \
+ e_repository.cc \
+ e_repository_entries.cc \
+ e_repository_exceptions.cc \
+ e_repository_id.cc \
+ e_repository_mask_file.cc \
+ e_repository_news.cc \
+ e_repository_params.cc \
+ e_repository_profile.cc \
+ e_repository_profile_file.cc \
+ e_repository_sets.cc \
+ eapi.cc \
+ eapi_phase.cc \
+ ebin.cc \
+ ebin_entries.cc \
+ ebuild.cc \
+ ebuild_entries.cc \
+ ebuild_flat_metadata_cache.cc \
+ ebuild_id.cc \
+ eclass_mtimes.cc \
+ exheres_layout.cc \
+ fetch_visitor.cc \
+ glsa.cc \
+ layout.cc \
+ make_ebin_repository.cc \
+ make_ebuild_repository.cc \
+ manifest2_reader.cc \
+ registration.cc \
+ source_uri_finder.cc \
+ traditional_layout.cc \
+ use_desc.cc \
+ vdb_id.cc \
+ vdb_merger.cc \
+ vdb_repository.cc \
+ vdb_unmerger.cc \
+ $(paludis_repositories_e_include_HEADERS)
+
+libpaludiserepository_la_LIBADD = \
+ $(top_builddir)/paludis/libpaludis.la \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(DYNAMIC_LD_LIBS)
+
+e_repository_TEST_SOURCES = e_repository_TEST.cc
+
+e_repository_TEST_LDADD = \
+ libpaludiserepository.la \
+ $(top_builddir)/paludis/repositories/fake/libpaludisfakerepository.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)
+
+e_repository_TEST_CXXFLAGS = $(AM_CXXFLAGS) -I$(top_srcdir)
+
+vdb_repository_TEST_SOURCES = vdb_repository_TEST.cc
+
+vdb_repository_TEST_LDADD = \
+ libpaludiserepository.la \
+ $(top_builddir)/paludis/repositories/fake/libpaludisfakerepository.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_repository_TEST_CXXFLAGS = $(AM_CXXFLAGS) -I$(top_srcdir)
+
+vdb_merger_TEST_SOURCES = vdb_merger_TEST.cc
+
+vdb_merger_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_merger_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)
+
+e_repository_sets_TEST_SOURCES = e_repository_sets_TEST.cc
+
+e_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)
+
+e_repository_sets_TEST_CXXFLAGS = $(AM_CXXFLAGS) -I$(top_srcdir)
+
+dep_spec_pretty_printer_TEST_SOURCES = dep_spec_pretty_printer_TEST.cc
+
+dep_spec_pretty_printer_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)
+
+dep_lexer_TEST_SOURCES = dep_lexer_TEST.cc
+
+dep_lexer_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)
+
+dep_parser_TEST_SOURCES = dep_parser_TEST.cc
+
+dep_parser_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)
+
+aa_visitor_TEST_SOURCES = aa_visitor_TEST.cc
+
+aa_visitor_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)
+
+fetch_visitor_TEST_SOURCES = fetch_visitor_TEST.cc
+
+fetch_visitor_TEST_LDADD = \
+ libpaludiserepository.la \
+ $(top_builddir)/paludis/repositories/fake/libpaludisfakerepository.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)
+
+source_uri_finder_TEST_SOURCES = source_uri_finder_TEST.cc
+
+source_uri_finder_TEST_LDADD = \
+ libpaludiserepository.la \
+ $(top_builddir)/paludis/repositories/fake/libpaludisfakerepository.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)
+
+EXTRA_DIST = \
+ aa_visitor_TEST.cc \
+ dep_lexer_TEST.cc \
+ dep_parser.se \
+ dep_parser-se.hh \
+ dep_parser-se.cc \
+ dep_parser_TEST.cc \
+ dep_spec_pretty_printer_TEST.cc \
+ eapi.sr \
+ eapi-sr.hh \
+ eapi-sr.cc \
+ 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 \
+ e_repository_TEST.cc \
+ e_repository_TEST_setup.sh \
+ e_repository_TEST_cleanup.sh \
+ e_repository_params-sr.hh \
+ e_repository_params-sr.cc \
+ e_repository_params.sr \
+ e_repository_params-se.hh \
+ e_repository_params-se.cc \
+ e_repository_params.se \
+ e_repository_sets_TEST.cc \
+ e_repository_sets_TEST_setup.sh \
+ e_repository_sets_TEST_cleanup.sh \
+ fetch_visitor_TEST.cc \
+ fetch_visitor_TEST_setup.sh \
+ fetch_visitor_TEST_cleanup.sh \
+ manifest2_entry.sr \
+ manifest2_entry-sr.hh \
+ manifest2_entry-sr.cc \
+ source_uri_finder_TEST.cc \
+ 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_merger_TEST.cc \
+ vdb_merger_TEST_setup.sh \
+ vdb_merger_TEST_cleanup.sh \
+ vdb_unmerger_TEST.cc \
+ vdb_unmerger_TEST_setup.sh \
+ vdb_unmerger_TEST_cleanup.sh
+
+BUILT_SOURCES = \
+ dep_parser-se.hh \
+ dep_parser-se.cc \
+ e_repository_params-sr.hh \
+ e_repository_params-sr.cc \
+ e_repository_params-se.hh \
+ e_repository_params-se.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 \
+ eapi-sr.hh \
+ eapi-sr.cc \
+ manifest2_entry-sr.hh \
+ manifest2_entry-sr.cc
+
+check_SCRIPTS = \
+ e_repository_TEST_setup.sh e_repository_TEST_cleanup.sh \
+ xml_things_TEST_setup.sh xml_things_TEST_cleanup.sh \
+ vdb_repository_TEST_setup.sh vdb_repository_TEST_cleanup.sh \
+ e_repository_sets_TEST_setup.sh e_repository_sets_TEST_cleanup.sh \
+ fetch_visitor_TEST_setup.sh fetch_visitor_TEST_cleanup.sh
+
+TESTS_ENVIRONMENT = env \
+ TEST_OUTPUT_WRAPPER="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/outputwrapper`" \
+ PALUDIS_OUTPUTWRAPPER_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/`" \
+ PALUDIS_EBUILD_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_srcdir)/paludis/repositories/e/ebuild/`" \
+ PALUDIS_EAPIS_DIR="$(top_srcdir)/paludis/repositories/e/eapis/" \
+ PALUDIS_DISTRIBUTIONS_DIR="$(top_srcdir)/paludis/distributions/" \
+ PALUDIS_DISTRIBUTION="gentoo" \
+ PALUDIS_FETCHERS_DIR="$(top_srcdir)/paludis/fetchers/" \
+ PALUDIS_SKIP_CONFIG="yes" \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ PALUDIS_REPOSITORY_SO_DIR="$(top_builddir)/paludis/repositories" \
+ PALUDIS_NO_CHOWN="yes" \
+ 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
+
+e_repository_params-sr.hh : e_repository_params.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/e_repository_params.sr > $@
+
+e_repository_params-sr.cc : e_repository_params.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/e_repository_params.sr > $@
+
+manifest2_entry-sr.hh : manifest2_entry.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/manifest2_entry.sr > $@
+
+manifest2_entry-sr.cc : manifest2_entry.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/manifest2_entry.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 > $@
+
+eapi-sr.hh : eapi.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --header $(srcdir)/eapi.sr > $@
+
+eapi-sr.cc : eapi.sr $(top_srcdir)/misc/make_sr.bash
+ $(top_srcdir)/misc/make_sr.bash --source $(srcdir)/eapi.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
+
+dep_parser-se.hh : dep_parser.se $(top_srcdir)/misc/make_se.bash
+ if ! $(top_srcdir)/misc/make_se.bash --header $(srcdir)/dep_parser.se > $@ ; then rm -f $@ ; exit 1 ; fi
+
+dep_parser-se.cc : dep_parser.se $(top_srcdir)/misc/make_se.bash
+ if ! $(top_srcdir)/misc/make_se.bash --source $(srcdir)/dep_parser.se > $@ ; then rm -f $@ ; exit 1 ; fi
+
+e_repository_params-se.hh : e_repository_params.se $(top_srcdir)/misc/make_se.bash
+ if ! $(top_srcdir)/misc/make_se.bash --header $(srcdir)/e_repository_params.se > $@ ; then rm -f $@ ; exit 1 ; fi
+
+e_repository_params-se.cc : e_repository_params.se $(top_srcdir)/misc/make_se.bash
+ if ! $(top_srcdir)/misc/make_se.bash --source $(srcdir)/e_repository_params.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 = \
+ $(top_builddir)/paludis/util/libpaludisutil.la \
+ $(top_builddir)/paludis/libpaludis.la \
+ @LIBXML2DEPS_LIBS@
+
+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
+
+paludis_datadir = $(datadir)/paludis
+
+dist_paludis_data_DATA = traditional.exclude
+
+TESTS = \
+ dep_lexer_TEST \
+ dep_parser_TEST \
+ dep_spec_pretty_printer_TEST \
+ e_repository_TEST \
+ vdb_merger_TEST \
+ vdb_unmerger_TEST \
+ $(GLSA_TESTS) \
+ e_repository_sets_TEST \
+ aa_visitor_TEST \
+ fetch_visitor_TEST \
+ source_uri_finder_TEST \
+ vdb_repository_TEST
+
+check_PROGRAMS = $(TESTS)
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+distcheck-deps-local : $(DISTCHECK_DEPS)
+
+distcheck-deps : distcheck-deps-subdirs
+
+distcheck-deps-subdirs :
+ for s in $(SUBDIRS) . ; do if test x$$s = x. ; then $(MAKE) distcheck-deps-local || exit 1 ; \
+ else $(MAKE) -C $$s distcheck-deps || exit 1 ; fi ; done
diff --git a/0.26.0_alpha1/paludis/repositories/e/aa_visitor.cc b/0.26.0_alpha1/paludis/repositories/e/aa_visitor.cc
new file mode 100644
index 000000000..85f665e2d
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/aa_visitor.cc
@@ -0,0 +1,75 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Mike Kelly <pioto@pioto.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/dep_spec.hh>
+#include <paludis/repositories/e/aa_visitor.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+
+/** \file
+ * Implementation of aa_visitor.hh
+ *
+ * \ingroup grpaavisitor
+ */
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<AAVisitor>
+ {
+ std::list<std::string> aa;
+ };
+}
+
+AAVisitor::AAVisitor() :
+ PrivateImplementationPattern<AAVisitor>(new Implementation<AAVisitor>)
+{
+}
+
+AAVisitor::~AAVisitor()
+{
+}
+
+void
+AAVisitor::visit_leaf(const FetchableURIDepSpec & p)
+{
+ _imp->aa.push_back(p.filename());
+}
+
+void
+AAVisitor::visit_leaf(const URILabelsDepSpec &)
+{
+}
+
+AAVisitor::ConstIterator
+AAVisitor::begin() const
+{
+ return ConstIterator(_imp->aa.begin());
+}
+
+AAVisitor::ConstIterator
+AAVisitor::end() const
+{
+ return ConstIterator(_imp->aa.end());
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/aa_visitor.hh b/0.26.0_alpha1/paludis/repositories/e/aa_visitor.hh
new file mode 100644
index 000000000..c69eb7ef8
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/aa_visitor.hh
@@ -0,0 +1,80 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Mike Kelly <pioto@pioto.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_AAVISITOR_HH
+#define PALUDIS_GUARD_PALUDIS_AAVISITOR_HH 1
+
+#include <paludis/dep_tree.hh>
+#include <paludis/dep_spec-fwd.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+/** \file
+ * Declarations for the AAVisitor class.
+ *
+ * \ingroup grpaavisitor
+ */
+
+namespace paludis
+{
+ namespace erepository
+ {
+ /**
+ * Get a list of all the URIs in a URIDepSpec, regardless of USE
+ * flag settings.
+ *
+ * \ingroup grpaavisitor
+ */
+ class PALUDIS_VISIBLE AAVisitor :
+ public ConstVisitor<FetchableURISpecTree>,
+ public ConstVisitor<FetchableURISpecTree>::VisitConstSequence<AAVisitor, AllDepSpec>,
+ public ConstVisitor<FetchableURISpecTree>::VisitConstSequence<AAVisitor, UseDepSpec>,
+ private PrivateImplementationPattern<AAVisitor>
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ AAVisitor();
+
+ ~AAVisitor();
+
+ ///\}
+
+ /// \name Visit functions
+ ///{
+
+ void visit_leaf(const FetchableURIDepSpec &);
+
+ void visit_leaf(const URILabelsDepSpec &);
+
+ ///}
+
+ /// \name Iterator functions
+ ///{
+
+ typedef libwrapiter::ForwardIterator<AAVisitor, const std::string> ConstIterator;
+
+ ConstIterator begin() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ ConstIterator end() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ ///}
+ };
+ }
+}
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/e/aa_visitor_TEST.cc b/0.26.0_alpha1/paludis/repositories/e/aa_visitor_TEST.cc
new file mode 100644
index 000000000..3589b09f4
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/aa_visitor_TEST.cc
@@ -0,0 +1,47 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Mike Kelly <pioto@pioto.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 "aa_visitor.hh"
+#include "dep_parser.hh"
+#include <paludis/util/join.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/repositories/e/eapi.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <test/test_runner.hh>
+#include <test/test_framework.hh>
+
+using namespace test;
+using namespace paludis;
+using namespace paludis::erepository;
+
+namespace test_cases
+{
+ struct AAVisitorTest : TestCase
+ {
+ AAVisitorTest() : TestCase("aa visitor") { }
+
+ void run()
+ {
+ AAVisitor p1;
+ parse_fetchable_uri("( a -> b c x? ( d e ) )", *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(p1);
+ TEST_CHECK_EQUAL(join(p1.begin(), p1.end(), " "), "b c d e");
+ }
+ } test_aa_visitor;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/check_fetched_files_visitor.cc b/0.26.0_alpha1/paludis/repositories/e/check_fetched_files_visitor.cc
new file mode 100644
index 000000000..b3ce913ab
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/check_fetched_files_visitor.cc
@@ -0,0 +1,399 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/check_fetched_files_visitor.hh>
+#include <paludis/repositories/e/source_uri_finder.hh>
+#include <paludis/repositories/e/e_repository_id.hh>
+#include <paludis/repositories/e/e_repository_params.hh>
+#include <paludis/dep_spec.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_id.hh>
+#include <paludis/repository.hh>
+#include <paludis/about.hh>
+#include <paludis/action.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/save.hh>
+#include <paludis/util/stringify.hh>
+
+#include <paludis/rmd160.hh>
+#include <paludis/sha256.hh>
+#include <paludis/md5.hh>
+
+#include <paludis/repositories/e/manifest2_reader.hh>
+
+#include <iostream>
+#include <fstream>
+#include <list>
+#include <set>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<CheckFetchedFilesVisitor>
+ {
+ const Environment * const env;
+ const tr1::shared_ptr<const PackageID> id;
+ const FSEntry distdir;
+ const bool check_unneeded;
+
+ std::set<std::string> done;
+ const tr1::shared_ptr<Sequence<FetchActionFailure> > failures;
+ bool need_nofetch;
+ bool in_nofetch;
+
+ const tr1::shared_ptr<Manifest2Reader> m2r;
+ const UseManifest use_manifest;
+
+ Implementation(
+ const Environment * const e,
+ const tr1::shared_ptr<const PackageID> & i,
+ const FSEntry & d,
+ const bool c,
+ const bool n,
+ const FSEntry & m2,
+ const UseManifest um) :
+ env(e),
+ id(i),
+ distdir(d),
+ check_unneeded(c),
+ failures(new Sequence<FetchActionFailure>),
+ need_nofetch(false),
+ in_nofetch(n),
+ m2r(new Manifest2Reader(m2)),
+ use_manifest(um)
+ {
+ }
+ };
+}
+
+CheckFetchedFilesVisitor::CheckFetchedFilesVisitor(
+ const Environment * const e,
+ const tr1::shared_ptr<const PackageID> & i,
+ const FSEntry & d,
+ const bool c,
+ const bool n,
+ const FSEntry & m2,
+ const UseManifest um) :
+ PrivateImplementationPattern<CheckFetchedFilesVisitor>(new Implementation<CheckFetchedFilesVisitor>(e, i, d, c, n, m2, um))
+{
+}
+
+CheckFetchedFilesVisitor::~CheckFetchedFilesVisitor()
+{
+}
+
+void
+CheckFetchedFilesVisitor::visit_sequence(const UseDepSpec & u,
+ FetchableURISpecTree::ConstSequenceIterator cur,
+ FetchableURISpecTree::ConstSequenceIterator end)
+{
+ Save<bool> save_in_nofetch(&_imp->in_nofetch, _imp->in_nofetch);
+ if ((_imp->check_unneeded) || (_imp->env->query_use(u.flag(), *_imp->id) ^ u.inverse()))
+ std::for_each(cur, end, accept_visitor(*this));
+}
+
+void
+CheckFetchedFilesVisitor::visit_sequence(const AllDepSpec &,
+ FetchableURISpecTree::ConstSequenceIterator cur,
+ FetchableURISpecTree::ConstSequenceIterator end)
+{
+ Save<bool> save_in_nofetch(&_imp->in_nofetch, _imp->in_nofetch);
+ std::for_each(cur, end, accept_visitor(*this));
+}
+
+namespace
+{
+ struct InNoFetchVisitor :
+ ConstVisitor<URILabelVisitorTypes>
+ {
+ bool result;
+
+ InNoFetchVisitor() :
+ result(false)
+ {
+ }
+
+ void visit(const URIMirrorsOnlyLabel &)
+ {
+ }
+
+ void visit(const URIManualOnlyLabel &)
+ {
+ result = true;
+ }
+
+ void visit(const URIMirrorsThenListedLabel &)
+ {
+ }
+
+ void visit(const URILocalMirrorsOnlyLabel &)
+ {
+ result = true;
+ }
+
+ void visit(const URIListedOnlyLabel &)
+ {
+ }
+
+ void visit(const URIListedThenMirrorsLabel &)
+ {
+ }
+ };
+}
+
+void
+CheckFetchedFilesVisitor::visit_leaf(const URILabelsDepSpec & l)
+{
+ InNoFetchVisitor v;
+ std::for_each(indirect_iterator(l.begin()), indirect_iterator(l.end()), accept_visitor(v));
+ _imp->in_nofetch = v.result;
+}
+
+bool
+CheckFetchedFilesVisitor::check_distfile_manifest(const FSEntry & distfile)
+{
+ if (_imp->m2r->begin() == _imp->m2r->end())
+ {
+ switch (_imp->use_manifest)
+ {
+ case manifest_use:
+ case manifest_ignore:
+ Log::get_instance()->message(ll_debug, lc_context) << "Empty or non-existent Manifest file";
+ return true;
+
+ case manifest_require:
+ case last_manifest:
+ _imp->failures->push_back(FetchActionFailure::create()
+ .target_file(stringify(distfile.basename()))
+ .failed_integrity_checks("No Manifest available")
+ .requires_manual_fetching(false)
+ .failed_automatic_fetching(false)
+ );
+ return false;
+
+ }
+ }
+
+ if (manifest_ignore == _imp->use_manifest)
+ return true;
+
+ bool found(false);
+
+ for (Manifest2Reader::ConstIterator m(_imp->m2r->begin()), m_end(_imp->m2r->end()) ;
+ m != m_end ; ++m)
+ {
+ if (distfile.basename() != m->name)
+ continue;
+ found = true;
+
+ Log::get_instance()->message(ll_debug, lc_context)
+ << "Actual size = " << distfile.file_size()
+ << "; Manifest file size = " << m->size;
+ if (distfile.file_size() != m->size)
+ {
+ Log::get_instance()->message(ll_debug, lc_context)
+ << "Malformed Manifest: no file size found";
+ std::cout << "incorrect size";
+ _imp->failures->push_back(FetchActionFailure::create()
+ .target_file(stringify(distfile.basename()))
+ .requires_manual_fetching(false)
+ .failed_integrity_checks("Incorrect file size")
+ .failed_automatic_fetching(false)
+ );
+ return false;
+ }
+
+ std::ifstream file_stream(stringify(distfile).c_str());
+ if (! file_stream)
+ {
+ std::cout << "unreadable file";
+ _imp->failures->push_back(FetchActionFailure::create()
+ .target_file(stringify(distfile.basename()))
+ .requires_manual_fetching(false)
+ .failed_integrity_checks("Unreadable file")
+ .failed_automatic_fetching(false)
+ );
+ return false;
+ }
+
+ if (! m->rmd160.empty())
+ {
+ RMD160 rmd160sum(file_stream);
+ if (rmd160sum.hexsum() != m->rmd160)
+ {
+ Log::get_instance()->message(ll_debug, lc_context)
+ << "Malformed Manifest: failed RMD160 checksum";
+ std::cout << "failed RMD160";
+ _imp->failures->push_back(FetchActionFailure::create()
+ .target_file(stringify(distfile.basename()))
+ .requires_manual_fetching(false)
+ .failed_integrity_checks("Failed RMD160 checksum")
+ .failed_automatic_fetching(false)
+ );
+ return false;
+ }
+ Log::get_instance()->message(ll_debug, lc_context)
+ << "Actual RMD160 = " << rmd160sum.hexsum();
+ file_stream.clear();
+ file_stream.seekg(0, std::ios::beg);
+ }
+
+ if (! m->sha256.empty())
+ {
+ SHA256 sha256sum(file_stream);
+ if (sha256sum.hexsum() != m->sha256)
+ {
+ Log::get_instance()->message(ll_debug, lc_context)
+ << "Malformed Manifest: failed SHA256 checksum";
+ std::cout << "failed SHA256";
+ _imp->failures->push_back(FetchActionFailure::create()
+ .target_file(stringify(distfile.basename()))
+ .requires_manual_fetching(false)
+ .failed_integrity_checks("Failed SHA256 checksum")
+ .failed_automatic_fetching(false)
+ );
+ return false;
+ }
+ Log::get_instance()->message(ll_debug, lc_context)
+ << "Actual SHA256 = " << sha256sum.hexsum();
+ file_stream.clear();
+ file_stream.seekg(0, std::ios::beg);
+ }
+
+ if (! m->md5.empty())
+ {
+ MD5 md5sum(file_stream);
+ if (md5sum.hexsum() != m->md5)
+ {
+ Log::get_instance()->message(ll_debug, lc_context)
+ << "Malformed Manifest: failed MD5 checksum";
+ std::cout << "failed MD5";
+ _imp->failures->push_back(FetchActionFailure::create()
+ .target_file(stringify(distfile.basename()))
+ .requires_manual_fetching(false)
+ .failed_integrity_checks("Failed MD5 checksum")
+ .failed_automatic_fetching(false)
+ );
+ return false;
+ }
+ Log::get_instance()->message(ll_debug, lc_context)
+ << "Actual MD5 = " << md5sum.hexsum();
+ }
+ }
+
+ if (! found)
+ {
+ std::cout << "not in Manifest";
+ _imp->failures->push_back(FetchActionFailure::create()
+ .target_file(stringify(distfile.basename()))
+ .requires_manual_fetching(false)
+ .failed_integrity_checks("Not in Manifest")
+ .failed_automatic_fetching(false)
+ );
+ return false;
+ }
+
+ return true;
+}
+
+void
+CheckFetchedFilesVisitor::visit_leaf(const FetchableURIDepSpec & u)
+{
+ Context context("When visiting URI dep spec '" + stringify(u.text()) + "':");
+
+ if (_imp->done.end() != _imp->done.find(u.filename()))
+ {
+ Log::get_instance()->message(ll_debug, lc_context) << "Already checked '" << u.filename() << "'";
+ return;
+ }
+ _imp->done.insert(u.filename());
+
+ std::cout << "Checking '" << u.filename() << "'... " << std::flush;
+
+ if (! (_imp->distdir / u.filename()).is_regular_file())
+ {
+ if (_imp->in_nofetch)
+ {
+ Log::get_instance()->message(ll_debug, lc_context) << "Manual fetch required for '" << u.filename() << "'";
+ std::cout << "requires manual fetch";
+ _imp->need_nofetch = true;
+ _imp->failures->push_back(FetchActionFailure::create()
+ .target_file(u.filename())
+ .requires_manual_fetching(true)
+ .failed_automatic_fetching(false)
+ .failed_integrity_checks("")
+ );
+ }
+ else
+ {
+ Log::get_instance()->message(ll_debug, lc_context) << "Automatic fetch failed for '" << u.filename() << "'";
+ std::cout << "does not exist";
+ _imp->failures->push_back(FetchActionFailure::create()
+ .target_file(u.filename())
+ .requires_manual_fetching(false)
+ .failed_automatic_fetching(true)
+ .failed_integrity_checks("")
+ );
+ }
+ }
+ else if (0 == (_imp->distdir / u.filename()).file_size())
+ {
+ Log::get_instance()->message(ll_debug, lc_context) << "Empty file for '" << u.filename() << "'";
+ std::cout << "empty file";
+ _imp->failures->push_back(FetchActionFailure::create()
+ .target_file(u.filename())
+ .requires_manual_fetching(false)
+ .failed_integrity_checks("SIZE (empty file)")
+ .failed_automatic_fetching(false)
+ );
+ }
+ else if (! check_distfile_manifest(_imp->distdir / u.filename()))
+ {
+ Log::get_instance()->message(ll_debug, lc_context)
+ << "Manifest check failed for '" << u.filename() << "'";
+ }
+ else
+ {
+ Log::get_instance()->message(ll_debug, lc_context) << "Success for '" << u.filename() << "'";
+ std::cout << "ok";
+ }
+
+ std::cout << std::endl;
+}
+
+const tr1::shared_ptr<const Sequence<FetchActionFailure> >
+CheckFetchedFilesVisitor::failures() const
+{
+ return _imp->failures;
+}
+
+bool
+CheckFetchedFilesVisitor::need_nofetch() const
+{
+ return _imp->need_nofetch;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/check_fetched_files_visitor.hh b/0.26.0_alpha1/paludis/repositories/e/check_fetched_files_visitor.hh
new file mode 100644
index 000000000..eac7d5aed
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/check_fetched_files_visitor.hh
@@ -0,0 +1,77 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_E_CHECK_FETCHED_FILES_VISITOR_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_CHECK_FETCHED_FILES_VISITOR_HH 1
+
+#include <paludis/repositories/e/e_repository_params.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/visitor-fwd.hh>
+#include <paludis/util/fs_entry-fwd.hh>
+#include <paludis/util/tr1_memory.hh>
+#include <paludis/dep_spec-fwd.hh>
+#include <paludis/dep_tree.hh>
+#include <paludis/package_id-fwd.hh>
+#include <paludis/environment-fwd.hh>
+#include <paludis/action-fwd.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ class PALUDIS_VISIBLE CheckFetchedFilesVisitor :
+ private PrivateImplementationPattern<CheckFetchedFilesVisitor>,
+ public ConstVisitor<FetchableURISpecTree>
+ {
+ private:
+ bool check_distfile_manifest(const FSEntry & distfile);
+
+ public:
+ CheckFetchedFilesVisitor(
+ const Environment * const,
+ const tr1::shared_ptr<const PackageID> &,
+ const FSEntry & distdir,
+ const bool check_unneeded,
+ const bool fetch_restrict,
+ const FSEntry & m2,
+ const UseManifest um);
+
+ ~CheckFetchedFilesVisitor();
+
+ void visit_sequence(const UseDepSpec &,
+ FetchableURISpecTree::ConstSequenceIterator,
+ FetchableURISpecTree::ConstSequenceIterator);
+
+ void visit_sequence(const AllDepSpec &,
+ FetchableURISpecTree::ConstSequenceIterator,
+ FetchableURISpecTree::ConstSequenceIterator);
+
+ void visit_leaf(const URILabelsDepSpec &);
+
+ void visit_leaf(const FetchableURIDepSpec &);
+
+ const tr1::shared_ptr<const Sequence<FetchActionFailure> > failures() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ bool need_nofetch() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/e/dep_lexer.cc b/0.26.0_alpha1/paludis/repositories/e/dep_lexer.cc
new file mode 100644
index 000000000..417cd7259
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/dep_lexer.cc
@@ -0,0 +1,117 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/dep_spec.hh>
+#include <paludis/repositories/e/dep_lexer.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/tokeniser.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <vector>
+#include <list>
+
+/** \file
+ * Implementation of dep_lexer.hh things.
+ *
+ * \ingroup grpdeplexer
+ */
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+namespace paludis
+{
+ /**
+ * Implementation data for DepLexer.
+ *
+ * \ingroup grpdeplexer
+ */
+ template<>
+ struct Implementation<DepLexer>
+ {
+ std::list<std::pair<DepLexerLexeme, std::string> > tokens;
+ };
+}
+
+DepStringLexError::DepStringLexError(const std::string & dep_string,
+ const std::string & our_message) throw () :
+ DepStringError(dep_string, "in lex phase: " + our_message)
+{
+}
+
+DepStringError::DepStringError(const std::string & d, const std::string & m) throw () :
+ Exception("Bad dependency string '" + d + "': " + m)
+{
+}
+
+DepLexer::DepLexer(const std::string & s) :
+ PrivateImplementationPattern<DepLexer>(new Implementation<DepLexer>)
+{
+ Context context("When lexing dependency string '" + s + "':");
+
+ std::vector<std::string> tokens;
+ Tokeniser<delim_kind::AnyOfTag, delim_mode::BoundaryTag>::tokenise(s, " \n\t", std::back_inserter(tokens));
+
+ for (std::vector<std::string>::const_iterator t(tokens.begin()), t_end(tokens.end()) ;
+ t != t_end ; ++t)
+ {
+ if (t->empty())
+ continue;
+
+ if (*t == "||")
+ _imp->tokens.push_back(std::make_pair(dpl_double_bar, *t));
+ else if ('|' == (*t)[0])
+ throw DepStringLexError(s, "'|' should be followed by '|'");
+ else if (*t == "->")
+ _imp->tokens.push_back(std::make_pair(dpl_arrow, *t));
+ else if (*t == "(")
+ _imp->tokens.push_back(std::make_pair(dpl_open_paren, *t));
+ else if ('(' == (*t)[0])
+ throw DepStringLexError(s, "'(' should be followed by whitespace");
+ else if (*t == ")")
+ _imp->tokens.push_back(std::make_pair(dpl_close_paren, *t));
+ else if (')' == (*t)[0])
+ throw DepStringLexError(s, "')' should be followed by whitespace");
+ else if (std::string::npos == t->find_first_not_of(" \t\n"))
+ _imp->tokens.push_back(std::make_pair(dpl_whitespace, *t));
+ else if (':' == (*t)[t->length() - 1])
+ _imp->tokens.push_back(std::make_pair(dpl_label, *t));
+ else if ('?' == (*t)[t->length() - 1])
+ _imp->tokens.push_back(std::make_pair(dpl_use_flag, *t));
+ else
+ _imp->tokens.push_back(std::make_pair(dpl_text, *t));
+ }
+}
+
+DepLexer::~DepLexer()
+{
+}
+
+DepLexer::ConstIterator
+DepLexer::begin() const
+{
+ return ConstIterator(_imp->tokens.begin());
+}
+
+DepLexer::ConstIterator
+DepLexer::end() const
+{
+ return ConstIterator(_imp->tokens.end());
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/dep_lexer.hh b/0.26.0_alpha1/paludis/repositories/e/dep_lexer.hh
new file mode 100644
index 000000000..e93559094
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/dep_lexer.hh
@@ -0,0 +1,129 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_E_DEP_LEXER_HH
+#define PALUDIS_GUARD_PALUDIS_E_DEP_LEXER_HH 1
+
+#include <paludis/util/exception.hh>
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <string>
+
+#include <libwrapiter/libwrapiter_forward_iterator-fwd.hh>
+
+/** \file
+ * Declarations for the DepLexer class.
+ *
+ * \ingroup grpdeplexer
+ */
+
+namespace paludis
+{
+ namespace erepository
+ {
+ /**
+ * A DepStringError descendent is thrown if an invalid depend string is
+ * encountered.
+ *
+ * \ingroup grpdeplexer
+ * \ingroup grpexceptions
+ */
+ class PALUDIS_VISIBLE DepStringError : public Exception
+ {
+ protected:
+ /**
+ * Constructor.
+ */
+ DepStringError(const std::string & dep_string,
+ const std::string & message) throw ();
+ };
+
+ /**
+ * A DepStringLexError is thrown if a lex-level error is encountered when
+ * parsing a dependency string.
+ *
+ * \ingroup grpdeplexer
+ * \ingroup grpexceptions
+ */
+ class PALUDIS_VISIBLE DepStringLexError : public DepStringError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ DepStringLexError(const std::string & dep_string,
+ const std::string & message) throw ();
+ };
+
+ /**
+ * Lexemes used by DepLexer.
+ *
+ * \see DepLexer
+ *
+ * \ingroup grpdeplexer
+ */
+ enum DepLexerLexeme
+ {
+ dpl_whitespace, ///< whitespace
+ dpl_text, ///< a package or item name
+ dpl_use_flag, ///< a use flag
+ dpl_double_bar, ///< a double bar ('any' marker)
+ dpl_open_paren, ///< open paren
+ dpl_close_paren, ///< close paren
+ dpl_arrow, ///< arrow
+ dpl_label ///< a label
+ };
+
+ /**
+ * Converts a dependency string into a sequence of tokens, which are
+ * then handled by DepParser.
+ *
+ * \see DepParser
+ * \ingroup grpdeplexer
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE DepLexer :
+ private InstantiationPolicy<DepLexer, instantiation_method::NonCopyableTag>,
+ private PrivateImplementationPattern<DepLexer>
+ {
+ public:
+ ///\name Iterate over our items
+ ///\{
+
+ typedef libwrapiter::ForwardIterator<DepLexer,
+ const std::pair<DepLexerLexeme, std::string> > ConstIterator;
+
+ ConstIterator begin() const;
+
+ ConstIterator end() const;
+
+ ///\}
+
+ ///\name Basic operations
+ ///\{
+
+ DepLexer(const std::string &);
+ ~DepLexer();
+
+ ///\}
+ };
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/e/dep_lexer_TEST.cc b/0.26.0_alpha1/paludis/repositories/e/dep_lexer_TEST.cc
new file mode 100644
index 000000000..b08a063dd
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/dep_lexer_TEST.cc
@@ -0,0 +1,244 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/dep_lexer.hh>
+#include <sstream>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+
+using namespace test;
+using namespace paludis;
+using namespace paludis::erepository;
+
+/** \file
+ * Test cases for DepLexer.
+ *
+ */
+
+namespace test_cases
+{
+ /**
+ * \test Test DepLexer with an empty input.
+ *
+ */
+ struct DepLexerEmptyTest : TestCase
+ {
+ DepLexerEmptyTest() : TestCase("empty") { }
+
+ void run()
+ {
+ DepLexer l("");
+ DepLexer::ConstIterator i(l.begin());
+ TEST_CHECK(i == l.end());
+ }
+ } test_dep_spec_parser_lexer_empty;
+
+ /**
+ * \test Test DepLexer with a blank input.
+ *
+ */
+ struct DepLexerBlankTest : TestCase
+ {
+ DepLexerBlankTest() : TestCase("blank") { }
+
+ void run()
+ {
+ DepLexer l(" \n \t");
+ DepLexer::ConstIterator i(l.begin());
+ TEST_CHECK(i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_whitespace);
+ TEST_CHECK_EQUAL(i->second, " \n \t");
+ TEST_CHECK(++i == l.end());
+ }
+ } test_dep_spec_parser_lexer_blank;
+
+ /**
+ * \test Test DepLexer with a package.
+ *
+ */
+ struct DepLexerPackageTest : TestCase
+ {
+ DepLexerPackageTest() : TestCase("package") { }
+
+ void run()
+ {
+ DepLexer l("app-editors/vim");
+ DepLexer::ConstIterator i(l.begin());
+ TEST_CHECK(i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_text);
+ TEST_CHECK_EQUAL(i->second, "app-editors/vim");
+ TEST_CHECK(++i == l.end());
+ }
+ } test_dep_spec_parser_lexer_package;
+
+ /**
+ * \test Test DepParser with a sequence of packages.
+ *
+ */
+ struct DepLexerPackagesTest : TestCase
+ {
+ DepLexerPackagesTest() : TestCase("packages") { }
+
+ void run()
+ {
+ DepLexer l("app-editors/vim app-misc/hilite \nsys-apps/findutils");
+ DepLexer::ConstIterator i(l.begin());
+
+ TEST_CHECK(i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_text);
+ TEST_CHECK_EQUAL(i->second, "app-editors/vim");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_whitespace);
+ TEST_CHECK_EQUAL(i->second, " ");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_text);
+ TEST_CHECK_EQUAL(i->second, "app-misc/hilite");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_whitespace);
+ TEST_CHECK_EQUAL(i->second, " \n");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_text);
+ TEST_CHECK_EQUAL(i->second, "sys-apps/findutils");
+
+ TEST_CHECK(++i == l.end());
+ }
+ } test_dep_spec_parser_lexer_packages;
+
+ /**
+ * \test Test DepLexer with an any group.
+ *
+ */
+ struct DepLexerAnyTest : TestCase
+ {
+ DepLexerAnyTest() : TestCase("any") { }
+
+ void run()
+ {
+ DepLexer l("|| ( one/one two/two )");
+ DepLexer::ConstIterator i(l.begin());
+
+ TEST_CHECK(i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_double_bar);
+ TEST_CHECK_EQUAL(i->second, "||");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_whitespace);
+ TEST_CHECK_EQUAL(i->second, " ");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_open_paren);
+ TEST_CHECK_EQUAL(i->second, "(");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_whitespace);
+ TEST_CHECK_EQUAL(i->second, " ");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_text);
+ TEST_CHECK_EQUAL(i->second, "one/one");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_whitespace);
+ TEST_CHECK_EQUAL(i->second, " ");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_text);
+ TEST_CHECK_EQUAL(i->second, "two/two");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_whitespace);
+ TEST_CHECK_EQUAL(i->second, " ");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_close_paren);
+ TEST_CHECK_EQUAL(i->second, ")");
+
+ TEST_CHECK(++i == l.end());
+ }
+ } test_dep_spec_parser_lexer_any;
+
+ /**
+ * \test Test DepLexer with a use group.
+ *
+ */
+ struct DepLexerUseTest : TestCase
+ {
+ DepLexerUseTest() : TestCase("use") { }
+
+ void run()
+ {
+ DepLexer l("foo? ( one/one )");
+ DepLexer::ConstIterator i(l.begin());
+
+ TEST_CHECK(i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_use_flag);
+ TEST_CHECK_EQUAL(i->second, "foo?");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_whitespace);
+ TEST_CHECK_EQUAL(i->second, " ");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_open_paren);
+ TEST_CHECK_EQUAL(i->second, "(");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_whitespace);
+ TEST_CHECK_EQUAL(i->second, " ");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_text);
+ TEST_CHECK_EQUAL(i->second, "one/one");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_whitespace);
+ TEST_CHECK_EQUAL(i->second, " ");
+
+ TEST_CHECK(++i != l.end());
+ TEST_CHECK_EQUAL(i->first, dpl_close_paren);
+ TEST_CHECK_EQUAL(i->second, ")");
+
+ TEST_CHECK(++i == l.end());
+ }
+ } test_dep_spec_parser_lexer_use;
+
+ /**
+ * \test Test DepLexer with bad input.
+ *
+ */
+ struct DepLexerBadTest : TestCase
+ {
+ DepLexerBadTest() : TestCase("bad") { }
+
+ void run()
+ {
+ TEST_CHECK_THROWS(DepLexer("(moo)"), DepStringError);
+ TEST_CHECK_THROWS(DepLexer("|foo"), DepStringError);
+ TEST_CHECK_THROWS(DepLexer("( moo )bar"), DepStringError);
+ }
+ } test_dep_spec_parser_lexer_bad;
+
+}
+
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/dep_parser-fwd.hh b/0.26.0_alpha1/paludis/repositories/e/dep_parser-fwd.hh
new file mode 100644
index 000000000..035906fc1
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/dep_parser-fwd.hh
@@ -0,0 +1,39 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_E_DEP_PARSER_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_E_DEP_PARSER_FWD_HH 1
+
+#include <iosfwd>
+#include <paludis/util/attributes.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ class DepStringNestingError;
+ class DepStringParseError;
+
+#include <paludis/repositories/e/dep_parser-se.hh>
+
+ }
+
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/e/dep_parser.cc b/0.26.0_alpha1/paludis/repositories/e/dep_parser.cc
new file mode 100644
index 000000000..361723b4d
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/dep_parser.cc
@@ -0,0 +1,835 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/dep_spec.hh>
+#include <paludis/repositories/e/eapi.hh>
+#include <paludis/repositories/e/dep_lexer.hh>
+#include <paludis/repositories/e/dep_parser.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/tr1_functional.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+#include <stack>
+#include <set>
+
+/** \file
+ * Implementation for dep_parser.hh things.
+ *
+ * \ingroup grpdepparser
+ */
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+#include <paludis/repositories/e/dep_parser-se.cc>
+
+DepStringParseError::DepStringParseError(const std::string & d,
+ const std::string & m) throw () :
+ DepStringError(d, "in parse phase: " + m)
+{
+}
+
+DepStringNestingError::DepStringNestingError(const std::string & dep_string) throw () :
+ DepStringParseError(dep_string, "improperly balanced parentheses")
+{
+}
+
+namespace
+{
+ struct LabelsAreURI;
+ struct LabelsAreDependency;
+
+ enum DepParserState
+ {
+ dps_initial,
+ dps_had_double_bar,
+ dps_had_double_bar_space,
+ dps_had_paren,
+ dps_had_use_flag,
+ dps_had_use_flag_space,
+ dps_had_text_arrow,
+ dps_had_text_arrow_space,
+ dps_had_text_arrow_text,
+ dps_had_label
+ };
+
+ using namespace tr1::placeholders;
+
+ struct ParsePackageDepSpec
+ {
+ PackageDepSpecParseMode _parse_mode;
+
+ ParsePackageDepSpec(PackageDepSpecParseMode m) :
+ _parse_mode(m)
+ {
+ }
+
+ template <typename H_>
+ void
+ add(const std::string & s, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> & p) const
+ {
+ p(tr1::shared_ptr<TreeLeaf<H_, PackageDepSpec> >(new TreeLeaf<H_, PackageDepSpec>(
+ tr1::shared_ptr<PackageDepSpec>(new PackageDepSpec(s, _parse_mode)))));
+ }
+
+ template <typename H_>
+ void
+ add_arrow(const std::string & lhs, const std::string & rhs, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> &) const
+ {
+ throw DepStringParseError(lhs + " -> " + rhs, "Arrows not allowed in this context");
+ }
+ };
+
+ struct ParsePackageOrBlockDepSpec
+ {
+ PackageDepSpecParseMode _parse_mode;
+
+ ParsePackageOrBlockDepSpec(PackageDepSpecParseMode m) :
+ _parse_mode(m)
+ {
+ }
+
+ template <typename H_>
+ void
+ add(const std::string & s, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> & p) const
+ {
+ if (s.empty() || '!' != s.at(0))
+ p(tr1::shared_ptr<TreeLeaf<H_, PackageDepSpec> >(new TreeLeaf<H_, PackageDepSpec>(
+ tr1::shared_ptr<PackageDepSpec>(new PackageDepSpec(s, _parse_mode)))));
+ else
+ p(tr1::shared_ptr<TreeLeaf<H_, BlockDepSpec> >(new TreeLeaf<H_, BlockDepSpec>(
+ tr1::shared_ptr<BlockDepSpec>(new BlockDepSpec(
+ tr1::shared_ptr<PackageDepSpec>(new PackageDepSpec(s.substr(1), _parse_mode)))))));
+ }
+
+ template <typename H_>
+ void
+ add_arrow(const std::string & lhs, const std::string & rhs, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> &) const
+ {
+ throw DepStringParseError(lhs + " -> " + rhs, "Arrows not allowed in this context");
+ }
+ };
+
+ struct ParseTextDepSpec
+ {
+ template <typename H_>
+ void
+ add(const std::string & s, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> & p) const
+ {
+ p(tr1::shared_ptr<TreeLeaf<H_, PlainTextDepSpec> >(new TreeLeaf<H_, PlainTextDepSpec>(
+ tr1::shared_ptr<PlainTextDepSpec>(new PlainTextDepSpec(s)))));
+ }
+
+ template <typename H_>
+ void
+ add_arrow(const std::string & lhs, const std::string & rhs, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> &) const
+ {
+ throw DepStringParseError(lhs + " -> " + rhs, "Arrows not allowed in this context");
+ }
+ };
+
+ struct ParseLicenseDepSpec
+ {
+ template <typename H_>
+ void
+ add(const std::string & s, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> & p) const
+ {
+ p(tr1::shared_ptr<TreeLeaf<H_, LicenseDepSpec> >(new TreeLeaf<H_, LicenseDepSpec>(
+ tr1::shared_ptr<LicenseDepSpec>(new LicenseDepSpec(s)))));
+ }
+
+ template <typename H_>
+ void
+ add_arrow(const std::string & lhs, const std::string & rhs, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> &) const
+ {
+ throw DepStringParseError(lhs + " -> " + rhs, "Arrows not allowed in this context");
+ }
+ };
+
+ struct ParseFetchableURIDepSpec
+ {
+ const bool _supports_arrow;
+
+ ParseFetchableURIDepSpec(bool a) :
+ _supports_arrow(a)
+ {
+ }
+
+ template <typename H_>
+ void
+ add(const std::string & s, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> & p) const
+ {
+ p(tr1::shared_ptr<TreeLeaf<H_, FetchableURIDepSpec> >(new TreeLeaf<H_, FetchableURIDepSpec>(
+ tr1::shared_ptr<FetchableURIDepSpec>(new FetchableURIDepSpec(s)))));
+ }
+
+ template <typename H_>
+ void
+ add_arrow(const std::string & lhs, const std::string & rhs, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> & p) const
+ {
+ if (_supports_arrow)
+ p(tr1::shared_ptr<TreeLeaf<H_, FetchableURIDepSpec> >(new TreeLeaf<H_, FetchableURIDepSpec>(
+ tr1::shared_ptr<FetchableURIDepSpec>(new FetchableURIDepSpec(lhs + " -> " + rhs)))));
+ else
+ throw DepStringParseError(lhs + " -> " + rhs, "Arrows not allowed in this EAPI");
+ }
+ };
+
+ struct ParseSimpleURIDepSpec
+ {
+ template <typename H_>
+ void
+ add(const std::string & s, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> & p) const
+ {
+ p(tr1::shared_ptr<TreeLeaf<H_, SimpleURIDepSpec> >(new TreeLeaf<H_, SimpleURIDepSpec>(
+ tr1::shared_ptr<SimpleURIDepSpec>(new SimpleURIDepSpec(s)))));
+ }
+
+ template <typename H_>
+ void
+ add_arrow(const std::string & lhs, const std::string & rhs, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> &) const
+ {
+ throw DepStringParseError(lhs + " -> " + rhs, "Arrows not allowed in this context");
+ }
+ };
+
+ template <typename H_, bool>
+ struct HandleUse
+ {
+ static void handle(const std::string & s, const std::string & i,
+ std::stack<std::pair<tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)>, bool> > & stack)
+ {
+ std::string f(i);
+ bool inv(f.length() && ('!' == f.at(0)));
+ if (inv)
+ f.erase(0, 1);
+
+ if (f.empty())
+ throw DepStringParseError(s,
+ "Bad use flag name '" + i + "'");
+ if ('?' != f.at(f.length() - 1))
+ throw DepStringParseError(s,
+ "Use flag name '" + i + "' missing '?'");
+
+ f.erase(f.length() - 1);
+ tr1::shared_ptr<ConstTreeSequence<H_, UseDepSpec> > a(
+ new ConstTreeSequence<H_, UseDepSpec>(tr1::shared_ptr<UseDepSpec>(
+ new UseDepSpec(UseFlagName(f), inv))));
+ stack.top().first(a);
+ stack.push(std::make_pair(tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)>(
+ tr1::bind(&ConstTreeSequence<H_, UseDepSpec>::add, a, _1)), false));
+ }
+ };
+
+ template <typename H_>
+ struct HandleUse<H_, false>
+ {
+ static void handle(const std::string & s, const std::string &,
+ std::stack<std::pair<tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)>, bool> > &)
+ {
+ throw DepStringParseError(s, "use? group is not allowed here");
+ }
+ };
+
+ template <typename H_, bool>
+ struct HandleAny
+ {
+ static void handle(const std::string &, std::stack<std::pair<tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)>, bool> > &
+ stack)
+ {
+ tr1::shared_ptr<ConstTreeSequence<H_, AnyDepSpec> > a(new ConstTreeSequence<H_, AnyDepSpec>(
+ tr1::shared_ptr<AnyDepSpec>(new AnyDepSpec)));
+ stack.top().first(a);
+ stack.push(std::make_pair(tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)>(
+ tr1::bind(&ConstTreeSequence<H_, AnyDepSpec>::add, a, _1)), true));
+ }
+ };
+
+ template <typename H_>
+ struct HandleAny<H_, false>
+ {
+ static void handle(const std::string & s, std::stack<std::pair<tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)>, bool> > &)
+ {
+ throw DepStringParseError(s, "|| is not allowed here");
+ }
+ };
+
+ template <typename H_, typename K_>
+ struct HandleLabel
+ {
+ static void add(const std::string & s, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> &,
+ const EAPI &)
+ {
+ throw DepStringParseError(s, "label is not allowed here");
+ }
+ };
+
+ template <typename H_>
+ struct HandleLabel<H_, LabelsAreURI>
+ {
+ static void add(const std::string & s, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> & p,
+ const EAPI & e)
+ {
+ if (e.supported && e.supported->uri_labels)
+ p(tr1::shared_ptr<TreeLeaf<H_, URILabelsDepSpec> >(
+ new TreeLeaf<H_, URILabelsDepSpec>(parse_uri_label(s, e))));
+ else
+ throw DepStringParseError(s, "URI labels not allowed in this EAPI");
+ }
+ };
+
+ template <typename H_>
+ struct HandleLabel<H_, LabelsAreDependency>
+ {
+ static void add(const std::string & s, tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)> & p,
+ const EAPI & e)
+ {
+ if (e.supported && e.supported->dependency_labels)
+ p(tr1::shared_ptr<TreeLeaf<H_, DependencyLabelsDepSpec> >(
+ new TreeLeaf<H_, DependencyLabelsDepSpec>(parse_dependency_label(s, e))));
+ else
+ throw DepStringParseError(s, "Dependency labels not allowed in this EAPI");
+ }
+ };
+
+ bool disallow_any_use(const DependencySpecTreeParseMode tree_mode)
+ {
+ switch (tree_mode)
+ {
+ case dst_pm_eapi_0:
+ return false;
+
+ case dst_pm_paludis_1:
+ case dst_pm_exheres_0:
+ return true;
+
+ case last_dst_pm:
+ ;
+ }
+
+ throw InternalError(PALUDIS_HERE, "bad _tree_mode");
+ }
+}
+
+namespace
+{
+ template <typename H_, typename I_, bool any_, bool use_, typename Label_>
+ tr1::shared_ptr<typename H_::ConstItem>
+ parse(const std::string & s, bool disallow_any_use, const I_ & p, const EAPI & e)
+ {
+ Context context("When parsing dependency string '" + s + "':");
+
+ tr1::shared_ptr<ConstTreeSequence<H_, AllDepSpec> > result(
+ new ConstTreeSequence<H_, AllDepSpec>(tr1::shared_ptr<AllDepSpec>(new AllDepSpec)));
+ std::stack<std::pair<tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)>, bool> > stack;
+ stack.push(std::make_pair(tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)>(
+ tr1::bind(&ConstTreeSequence<H_, AllDepSpec>::add, result, _1)), false));
+
+ std::string arrow_lhs;
+ DepParserState state(dps_initial);
+ DepLexer lexer(s);
+ DepLexer::ConstIterator i(lexer.begin()), i_end(lexer.end());
+
+ for ( ; i != i_end ; ++i)
+ {
+ Context local_context("When handling lexer token '" + i->second +
+ "' (" + stringify(i->first) + "):");
+ do
+ {
+ switch (state)
+ {
+ case dps_initial:
+ do
+ {
+ switch (i->first)
+ {
+ case dpl_whitespace:
+ continue;
+
+ case dpl_arrow:
+ throw DepStringParseError(s, "Arrow not allowed here");
+
+ case dpl_text:
+ {
+ if (i->second.empty())
+ throw DepStringParseError(i->second, "Empty text entry");
+
+ DepLexer::ConstIterator i_fwd(next(i));
+ if (i_fwd != i_end && i_fwd->first == dpl_whitespace && ++i_fwd != i_end
+ && i_fwd->first == dpl_arrow)
+ {
+ arrow_lhs = i->second;
+ i = i_fwd;
+ state = dps_had_text_arrow;
+ }
+ else
+ p.template add<H_>(i->second, stack.top().first);
+ }
+ continue;
+
+ case dpl_open_paren:
+ {
+ tr1::shared_ptr<ConstTreeSequence<H_, AllDepSpec> > a(new ConstTreeSequence<H_, AllDepSpec>(
+ tr1::shared_ptr<AllDepSpec>(new AllDepSpec)));
+ stack.top().first(a);
+ stack.push(std::make_pair(tr1::function<void (tr1::shared_ptr<ConstAcceptInterface<H_> >)>(
+ tr1::bind(&ConstTreeSequence<H_, AllDepSpec>::add, a, _1)), false));
+ state = dps_had_paren;
+ }
+ continue;
+
+ case dpl_close_paren:
+ if (stack.empty())
+ throw DepStringNestingError(s);
+ stack.pop();
+ if (stack.empty())
+ throw DepStringNestingError(s);
+ state = dps_had_paren;
+ continue;
+
+ case dpl_double_bar:
+ HandleAny<H_, any_>::handle(s, stack);
+ state = dps_had_double_bar;
+ continue;
+
+ case dpl_use_flag:
+ if (use_ && disallow_any_use && stack.top().second)
+ throw DepStringParseError(s, "use? group is not allowed immediately under a || ( )");
+ HandleUse<H_, use_>::handle(s, i->second, stack);
+ state = dps_had_use_flag;
+ continue;
+
+ case dpl_label:
+ HandleLabel<H_, Label_>::add(i->second, stack.top().first, e);
+ state = dps_had_label;
+ continue;
+ }
+ throw InternalError(PALUDIS_HERE,
+ "dps_initial: i->first is " + stringify(i->first));
+
+ } while (0);
+ continue;
+
+ case dps_had_double_bar:
+ do
+ {
+ switch (i->first)
+ {
+ case dpl_whitespace:
+ state = dps_had_double_bar_space;
+ continue;
+
+ case dpl_text:
+ case dpl_arrow:
+ case dpl_use_flag:
+ case dpl_double_bar:
+ case dpl_open_paren:
+ case dpl_close_paren:
+ case dpl_label:
+ throw DepStringParseError(s, "Expected space after '||'");
+ }
+ throw InternalError(PALUDIS_HERE,
+ "dps_had_double_bar: i->first is " + stringify(i->first));
+
+ } while (0);
+ continue;
+
+ case dps_had_double_bar_space:
+ do
+ {
+ switch (i->first)
+ {
+ case dpl_open_paren:
+ state = dps_initial;
+ continue;
+
+ case dpl_whitespace:
+ case dpl_text:
+ case dpl_use_flag:
+ case dpl_double_bar:
+ case dpl_close_paren:
+ case dpl_arrow:
+ case dpl_label:
+ throw DepStringParseError(s, "Expected '(' after '|| '");
+ }
+ throw InternalError(PALUDIS_HERE,
+ "dps_had_double_bar_space: i->first is " + stringify(i->first));
+ } while (0);
+ continue;
+
+ case dps_had_paren:
+ do
+ {
+ switch (i->first)
+ {
+ case dpl_whitespace:
+ state = dps_initial;
+ continue;
+
+ case dpl_text:
+ case dpl_use_flag:
+ case dpl_double_bar:
+ case dpl_open_paren:
+ case dpl_close_paren:
+ case dpl_arrow:
+ case dpl_label:
+ throw DepStringParseError(s, "Expected space after '(' or ')'");
+ }
+ throw InternalError(PALUDIS_HERE,
+ "dps_had_paren: i->first is " + stringify(i->first));
+ } while (0);
+ continue;
+
+ case dps_had_use_flag:
+ do
+ {
+ switch (i->first)
+ {
+ case dpl_whitespace:
+ state = dps_had_use_flag_space;
+ continue;
+
+ case dpl_text:
+ case dpl_use_flag:
+ case dpl_double_bar:
+ case dpl_open_paren:
+ case dpl_close_paren:
+ case dpl_arrow:
+ case dpl_label:
+ throw DepStringParseError(s, "Expected space after use flag");
+ }
+ throw InternalError(PALUDIS_HERE,
+ "dps_had_use_flag: i->first is " + stringify(i->first));
+ } while (0);
+ continue;
+
+ case dps_had_use_flag_space:
+ do
+ {
+ switch (i->first)
+ {
+ case dpl_open_paren:
+ state = dps_had_paren;
+ continue;
+
+ case dpl_whitespace:
+ case dpl_text:
+ case dpl_use_flag:
+ case dpl_double_bar:
+ case dpl_close_paren:
+ case dpl_arrow:
+ case dpl_label:
+ throw DepStringParseError(s, "Expected '(' after use flag");
+ }
+ throw InternalError(PALUDIS_HERE,
+ "dps_had_use_flag_space: i->first is " + stringify(i->first));
+ } while (0);
+ continue;
+
+ case dps_had_label:
+ do
+ {
+ switch (i->first)
+ {
+ case dpl_whitespace:
+ state = dps_initial;
+ continue;
+
+ case dpl_text:
+ case dpl_use_flag:
+ case dpl_double_bar:
+ case dpl_open_paren:
+ case dpl_close_paren:
+ case dpl_arrow:
+ case dpl_label:
+ throw DepStringParseError(s, "Expected space after label");
+ }
+ throw InternalError(PALUDIS_HERE,
+ "dps_had_label: i->first is " + stringify(i->first));
+ } while (0);
+ continue;
+
+ case dps_had_text_arrow:
+ do
+ {
+ switch (i->first)
+ {
+ case dpl_whitespace:
+ state = dps_had_text_arrow_space;
+ continue;
+
+ case dpl_text:
+ case dpl_open_paren:
+ case dpl_use_flag:
+ case dpl_double_bar:
+ case dpl_close_paren:
+ case dpl_arrow:
+ case dpl_label:
+ throw DepStringParseError(s, "Expected whitespace after arrow");
+ }
+ throw InternalError(PALUDIS_HERE,
+ "dps_had_text_arrow: i->first is " + stringify(i->first));
+ } while (0);
+ continue;
+
+ case dps_had_text_arrow_space:
+ do
+ {
+ switch (i->first)
+ {
+ case dpl_whitespace:
+ continue;
+
+ case dpl_text:
+ state = dps_had_text_arrow_text;
+ p.template add_arrow<H_>(arrow_lhs, i->second, stack.top().first);
+ continue;
+
+ case dpl_open_paren:
+ case dpl_use_flag:
+ case dpl_double_bar:
+ case dpl_close_paren:
+ case dpl_arrow:
+ case dpl_label:
+ throw DepStringParseError(s, "Expected text after whitespace after arrow");
+ }
+ throw InternalError(PALUDIS_HERE,
+ "dps_had_text_arrow_space: i->first is " + stringify(i->first));
+ } while (0);
+ continue;
+
+ case dps_had_text_arrow_text:
+ do
+ {
+ switch (i->first)
+ {
+ case dpl_whitespace:
+ state = dps_initial;
+ continue;
+
+ case dpl_text:
+ case dpl_open_paren:
+ case dpl_use_flag:
+ case dpl_close_paren:
+ case dpl_double_bar:
+ case dpl_arrow:
+ case dpl_label:
+ throw DepStringParseError(s, "Expected whitespace after text after whitespace after arrow");
+ }
+ throw InternalError(PALUDIS_HERE,
+ "dps_had_text_arrow_text: i->first is " + stringify(i->first));
+ }
+ while (0);
+ continue;
+ }
+ throw InternalError(PALUDIS_HERE,
+ "state is " + stringify(state));
+
+ } while (0);
+ }
+
+ if (stack.empty())
+ throw DepStringNestingError(s);
+
+ switch (state)
+ {
+ case dps_initial:
+ case dps_had_paren:
+ case dps_had_text_arrow_text:
+ case dps_had_text_arrow_space:
+ break;
+
+ case dps_had_double_bar_space:
+ case dps_had_double_bar:
+ case dps_had_use_flag:
+ case dps_had_use_flag_space:
+ case dps_had_text_arrow:
+ case dps_had_label:
+ throw DepStringParseError(s, "Unexpected end of string");
+ }
+
+ stack.pop();
+ if (! stack.empty())
+ throw DepStringNestingError(s);
+ return result;
+ }
+}
+
+tr1::shared_ptr<DependencySpecTree::ConstItem>
+paludis::erepository::parse_depend(const std::string & s, const EAPI & e)
+{
+ Context c("When parsing dependency string '" + s + "' using EAPI '" + e.name + "':");
+
+ if (! e.supported)
+ throw DepStringParseError(s, "Don't know how to parse EAPI '" + e.name + "' dependencies");
+
+ return parse<DependencySpecTree, ParsePackageOrBlockDepSpec, true, true, LabelsAreDependency>(s,
+ disallow_any_use(e.supported->dependency_spec_tree_parse_mode),
+ ParsePackageOrBlockDepSpec(e.supported->package_dep_spec_parse_mode), e);
+}
+
+tr1::shared_ptr<ProvideSpecTree::ConstItem>
+paludis::erepository::parse_provide(const std::string & s, const EAPI & e)
+{
+ Context c("When parsing provide string '" + s + "' using EAPI '" + e.name + "':");
+
+ if (! e.supported)
+ throw DepStringParseError(s, "Don't know how to parse EAPI '" + e.name + "' provides");
+
+ return parse<ProvideSpecTree, ParsePackageDepSpec, false, true, void>(s, false,
+ ParsePackageDepSpec(pds_pm_eapi_0), e);
+}
+
+tr1::shared_ptr<RestrictSpecTree::ConstItem>
+paludis::erepository::parse_restrict(const std::string & s, const EAPI & e)
+{
+ Context c("When parsing restrict string '" + s + "' using EAPI '" + e.name + "':");
+
+ if (! e.supported)
+ throw DepStringParseError(s, "Don't know how to parse EAPI '" + e.name + "' restrictions");
+
+ return parse<RestrictSpecTree, ParseTextDepSpec, false, true, void>(s, false,
+ ParseTextDepSpec(), e);
+}
+
+tr1::shared_ptr<FetchableURISpecTree::ConstItem>
+paludis::erepository::parse_fetchable_uri(const std::string & s, const EAPI & e)
+{
+ Context c("When parsing fetchable URI string '" + s + "' using EAPI '" + e.name + "':");
+
+ if (! e.supported)
+ throw DepStringParseError(s, "Don't know how to parse EAPI '" + e.name + "' URIs");
+
+ return parse<FetchableURISpecTree, ParseFetchableURIDepSpec, false, true, LabelsAreURI>(s, false,
+ ParseFetchableURIDepSpec(e.supported->uri_supports_arrow), e);
+}
+
+tr1::shared_ptr<SimpleURISpecTree::ConstItem>
+paludis::erepository::parse_simple_uri(const std::string & s, const EAPI & e)
+{
+ Context c("When parsing simple URI string '" + s + "' using EAPI '" + e.name + "':");
+
+ if (! e.supported)
+ throw DepStringParseError(s, "Don't know how to parse EAPI '" + e.name + "' URIs");
+
+ return parse<SimpleURISpecTree, ParseSimpleURIDepSpec, false, true, void>(s, false,
+ ParseSimpleURIDepSpec(), e);
+}
+
+tr1::shared_ptr<LicenseSpecTree::ConstItem>
+paludis::erepository::parse_license(const std::string & s, const EAPI & e)
+{
+ Context c("When parsing license string '" + s + "' using EAPI '" + e.name + "':");
+
+ if (! e.supported)
+ throw DepStringParseError(s, "Don't know how to parse EAPI '" + e.name + "' licenses");
+
+ return parse<LicenseSpecTree, ParseLicenseDepSpec, true, true, void>(s,
+ true, ParseLicenseDepSpec(), e);
+}
+
+tr1::shared_ptr<URILabelsDepSpec>
+paludis::erepository::parse_uri_label(const std::string & s, const EAPI & e)
+{
+ Context context("When parsing label string '" + s + "' using EAPI '" + e.name + "':");
+
+ if (s.empty())
+ throw DepStringParseError(s, "Empty label");
+
+ std::string c(e.supported->uri_labels->class_for_label(s.substr(0, s.length() - 1)));
+ if (c.empty())
+ throw DepStringParseError(s, "Unknown label");
+
+ tr1::shared_ptr<URILabelsDepSpec> l(new LabelsDepSpec<URILabelVisitorTypes>);
+
+ if (c == "URIMirrorsThenListedLabel")
+ l->add_label(make_shared_ptr(new URIMirrorsThenListedLabel(s.substr(0, s.length() - 1))));
+ else if (c == "URIMirrorsOnlyLabel")
+ l->add_label(make_shared_ptr(new URIMirrorsOnlyLabel(s.substr(0, s.length() - 1))));
+ else if (c == "URIListedOnlyLabel")
+ l->add_label(make_shared_ptr(new URIListedOnlyLabel(s.substr(0, s.length() - 1))));
+ else if (c == "URIListedThenMirrorsLabel")
+ l->add_label(make_shared_ptr(new URIListedThenMirrorsLabel(s.substr(0, s.length() - 1))));
+ else if (c == "URILocalMirrorsOnlyLabel")
+ l->add_label(make_shared_ptr(new URILocalMirrorsOnlyLabel(s.substr(0, s.length() - 1))));
+ else if (c == "URIManualOnlyLabel")
+ l->add_label(make_shared_ptr(new URIManualOnlyLabel(s.substr(0, s.length() - 1))));
+ else
+ throw DepStringParseError(s, "Label '" + s + "' maps to unknown class '" + c + "'");
+
+ return l;
+}
+
+tr1::shared_ptr<DependencyLabelsDepSpec>
+paludis::erepository::parse_dependency_label(const std::string & s, const EAPI & e)
+{
+ Context context("When parsing label string '" + s + "' using EAPI '" + e.name + "':");
+
+ if (s.empty())
+ throw DepStringParseError(s, "Empty label");
+
+ std::set<std::string> labels;
+ std::string label(s.substr(0, s.length() - 1));
+ Tokeniser<delim_kind::AnyOfTag>::tokenise(label, ",+", std::inserter(labels, labels.end()));
+
+ tr1::shared_ptr<DependencyLabelsDepSpec> l(new DependencyLabelsDepSpec);
+
+ for (std::set<std::string>::iterator it = labels.begin(), it_e = labels.end(); it != it_e; ++it)
+ {
+ std::string c(e.supported->dependency_labels->class_for_label(*it));
+ if (c.empty())
+ throw DepStringParseError(s, "Unknown label '" + *it + "'");
+
+ if (c == "DependencyHostLabel")
+ l->add_label(make_shared_ptr(new DependencyHostLabel(*it)));
+ else if (c == "DependencyTargetLabel")
+ l->add_label(make_shared_ptr(new DependencyTargetLabel(*it)));
+ else if (c == "DependencyBuildLabel")
+ l->add_label(make_shared_ptr(new DependencyBuildLabel(*it)));
+ else if (c == "DependencyRunLabel")
+ l->add_label(make_shared_ptr(new DependencyRunLabel(*it)));
+ else if (c == "DependencyInstallLabel")
+ l->add_label(make_shared_ptr(new DependencyInstallLabel(*it)));
+ else if (c == "DependencyCompileLabel")
+ l->add_label(make_shared_ptr(new DependencyCompileLabel(*it)));
+ else if (c == "DependencySuggestedLabel")
+ l->add_label(make_shared_ptr(new DependencySuggestedLabel(*it)));
+ else if (c == "DependencyRecommendedLabel")
+ l->add_label(make_shared_ptr(new DependencyRecommendedLabel(*it)));
+ else if (c == "DependencyRequiredLabel")
+ l->add_label(make_shared_ptr(new DependencyRequiredLabel(*it)));
+ else if (c == "DependencyAnyLabel")
+ l->add_label(make_shared_ptr(new DependencyAnyLabel(*it)));
+ else if (c == "DependencyMineLabel")
+ l->add_label(make_shared_ptr(new DependencyMineLabel(*it)));
+ else if (c == "DependencyPrimaryLabel")
+ l->add_label(make_shared_ptr(new DependencyPrimaryLabel(*it)));
+ else if (c == "DependencyABILabel")
+ l->add_label(make_shared_ptr(new DependencyABILabel(*it)));
+ else
+ throw DepStringParseError(s, "Label '" + *it + "' maps to unknown class '" + c + "'");
+ }
+
+ return l;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/dep_parser.hh b/0.26.0_alpha1/paludis/repositories/e/dep_parser.hh
new file mode 100644
index 000000000..80dae0171
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/dep_parser.hh
@@ -0,0 +1,124 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_E_DEP_PARSER_HH
+#define PALUDIS_GUARD_PALUDIS_E_DEP_PARSER_HH 1
+
+#include <paludis/repositories/e/dep_parser-fwd.hh>
+#include <paludis/dep_tree.hh>
+#include <paludis/repositories/e/dep_lexer.hh>
+#include <paludis/repositories/e/eapi-fwd.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/instantiation_policy.hh>
+#include <string>
+
+/** \file
+ * Declarations for the DepParser routines.
+ *
+ * \ingroup grpdepparser
+ */
+
+namespace paludis
+{
+ namespace erepository
+ {
+ /**
+ * A DepStringParseError is thrown if an error is encountered when parsing
+ * a dependency string.
+ *
+ * \ingroup grpexceptions
+ * \ingroup grpdepparser
+ */
+ class PALUDIS_VISIBLE DepStringParseError : public DepStringError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ DepStringParseError(const std::string & dep_string,
+ const std::string & message) throw ();
+ };
+
+ /**
+ * A DepStringNestingError is thrown if a dependency string does not have
+ * properly balanced parentheses.
+ *
+ * \ingroup grpexceptions
+ * \ingroup grpdepparser
+ */
+ class PALUDIS_VISIBLE DepStringNestingError : public DepStringParseError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ DepStringNestingError(const std::string & dep_string) throw ();
+ };
+
+ /**
+ * Parse a dependency heirarchy.
+ */
+ tr1::shared_ptr<DependencySpecTree::ConstItem> parse_depend(const std::string & s,
+ const EAPI &) PALUDIS_VISIBLE;
+
+ /**
+ * Parse a dep spec label.
+ */
+ tr1::shared_ptr<DependencyLabelsDepSpec> parse_dependency_label(const std::string & s,
+ const EAPI &) PALUDIS_VISIBLE;
+
+ /**
+ * Parse a provide heirarchy.
+ */
+ tr1::shared_ptr<ProvideSpecTree::ConstItem> parse_provide(const std::string & s,
+ const EAPI &) PALUDIS_VISIBLE;
+
+ /**
+ * Parse a restrict.
+ */
+ tr1::shared_ptr<RestrictSpecTree::ConstItem> parse_restrict(const std::string & s,
+ const EAPI &) PALUDIS_VISIBLE;
+
+ /**
+ * Parse a fetchable uri heirarchy.
+ */
+ tr1::shared_ptr<FetchableURISpecTree::ConstItem> parse_fetchable_uri(const std::string & s,
+ const EAPI &) PALUDIS_VISIBLE;
+
+ /**
+ * Parse a simple uri heirarchy.
+ */
+ tr1::shared_ptr<SimpleURISpecTree::ConstItem> parse_simple_uri(const std::string & s,
+ const EAPI &) PALUDIS_VISIBLE;
+
+ /**
+ * Parse a license heirarchy.
+ */
+ tr1::shared_ptr<LicenseSpecTree::ConstItem> parse_license(const std::string & s,
+ const EAPI &) PALUDIS_VISIBLE;
+
+ /**
+ * Parse a URI label.
+ */
+ tr1::shared_ptr<URILabelsDepSpec> parse_uri_label(const std::string & s,
+ const EAPI &) PALUDIS_VISIBLE;
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/e/dep_parser.se b/0.26.0_alpha1/paludis/repositories/e/dep_parser.se
new file mode 100644
index 000000000..df9c782e8
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/dep_parser.se
@@ -0,0 +1,23 @@
+#!/bin/bash
+# vim: set sw=4 sts=4 et ft=sh :
+
+make_enum_DependencySpecTreeParseMode()
+{
+ prefix dst_pm
+ want_destringify
+ namespace paludis::erepository
+
+ key dst_pm_eapi_0 "EAPI 0"
+ key dst_pm_exheres_0 "EAPI exheres-0"
+ key dst_pm_paludis_1 "EAPI paludis-1"
+
+ doxygen_comment << "END"
+ /**
+ * How DepParser should parse a DependencySpecTree string.
+ *
+ * \see DepParser
+ * \ingroup grpdepspecs
+ */
+END
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/dep_parser_TEST.cc b/0.26.0_alpha1/paludis/repositories/e/dep_parser_TEST.cc
new file mode 100644
index 000000000..33d55e890
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/dep_parser_TEST.cc
@@ -0,0 +1,352 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/dep_spec_pretty_printer.hh>
+#include <paludis/repositories/e/dep_parser.hh>
+#include <paludis/repositories/e/eapi.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/stringify_formatter.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <sstream>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace test;
+using namespace paludis;
+using namespace paludis::erepository;
+
+/** \file
+ * Test cases for DepParser.
+ *
+ */
+
+namespace test_cases
+{
+ /**
+ * \test Test DepParser with an empty input.
+ *
+ */
+ struct DepParserEmptyTest : TestCase
+ {
+ DepParserEmptyTest() : TestCase("empty") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+ DepSpecPrettyPrinter d(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend("",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d);
+ TEST_CHECK_EQUAL(stringify(d), "");
+ }
+ } test_dep_spec_parser_empty;
+
+ /**
+ * \test Test DepParser with a blank input.
+ *
+ */
+ struct DepParserBlankTest : TestCase
+ {
+ DepParserBlankTest() : TestCase("blank") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+ DepSpecPrettyPrinter d(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend(" \n \t",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d);
+ TEST_CHECK_EQUAL(stringify(d), "");
+ }
+ } test_dep_spec_parser_blank;
+
+ /**
+ * \test Test DepParser with a package.
+ *
+ */
+ struct DepParserPackageTest : TestCase
+ {
+ DepParserPackageTest() : TestCase("package") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+ DepSpecPrettyPrinter d(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend("app-editors/vim",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d);
+ TEST_CHECK_EQUAL(stringify(d), "app-editors/vim");
+ }
+ } test_dep_spec_parser_package;
+
+ /**
+ * \test Test DepParser with a decorated package.
+ *
+ */
+ struct DepParserDecoratedPackageTest : TestCase
+ {
+ DepParserDecoratedPackageTest() : TestCase("decorated package") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+
+ DepSpecPrettyPrinter d1(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend(">=app-editors/vim-6.4_alpha",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d1);
+ TEST_CHECK_EQUAL(stringify(d1), ">=app-editors/vim-6.4_alpha");
+
+ DepSpecPrettyPrinter d2(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend("=app-editors/vim-6.4_alpha-r1",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d2);
+ TEST_CHECK_EQUAL(stringify(d2), "=app-editors/vim-6.4_alpha-r1");
+
+ DepSpecPrettyPrinter d3(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend(">=app-editors/vim-6.4_alpha:one",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d3);
+ TEST_CHECK_EQUAL(stringify(d3), ">=app-editors/vim-6.4_alpha:one");
+ }
+ } test_dep_spec_parser_decorated_package;
+
+ /**
+ * \test Test DepParser with a sequence of packages.
+ *
+ */
+ struct DepParserPackagesTest : TestCase
+ {
+ DepParserPackagesTest() : TestCase("packages") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+
+ DepSpecPrettyPrinter d(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend("app-editors/vim app-misc/hilite \nsys-apps/findutils",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d);
+ TEST_CHECK_EQUAL(stringify(d), "app-editors/vim app-misc/hilite sys-apps/findutils");
+ }
+ } test_dep_spec_parser_packages;
+
+ struct DepParserAnyTest : TestCase
+ {
+ DepParserAnyTest() : TestCase("any") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+
+ DepSpecPrettyPrinter d(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend("|| ( one/one two/two )",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d);
+ TEST_CHECK_EQUAL(stringify(d), "|| ( one/one two/two )");
+ }
+ } test_dep_spec_parser_any;
+
+ struct DepParserAnyUseTest : TestCase
+ {
+ DepParserAnyUseTest() : TestCase("any use") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+
+ DepSpecPrettyPrinter d(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend("|| ( one/one foo? ( two/two ) )",
+ *EAPIData::get_instance()->eapi_from_string("0"))->accept(d);
+ TEST_CHECK_EQUAL(stringify(d), "|| ( one/one foo? ( two/two ) )");
+
+ TEST_CHECK_THROWS(parse_depend("|| ( one/one foo? ( two/two ) )",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+
+ DepSpecPrettyPrinter e(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend("|| ( one/one ( foo? ( two/two ) ) )",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(e);
+ TEST_CHECK_EQUAL(stringify(e), "|| ( one/one ( foo? ( two/two ) ) )");
+ }
+ } test_dep_spec_parser_any_use;
+
+ /**
+ * \test Test DepParser with an all group.
+ *
+ */
+ struct DepParserAllTest : TestCase
+ {
+ DepParserAllTest() : TestCase("all") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+
+ DepSpecPrettyPrinter d(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend(" ( one/one two/two ) ",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d);
+ TEST_CHECK_EQUAL(stringify(d), "one/one two/two");
+ }
+ } test_dep_spec_parser_all;
+
+ /**
+ * \test Test DepParser with a use group.
+ *
+ */
+ struct DepParserUseTest : TestCase
+ {
+ DepParserUseTest() : TestCase("use") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+
+ DepSpecPrettyPrinter d(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend("foo? ( one/one )", *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d);
+ TEST_CHECK_EQUAL(stringify(d), "foo? ( one/one )");
+ }
+ } test_dep_spec_parser_use;
+
+ /**
+ * \test Test DepParser with an inverse use group.
+ *
+ */
+ struct DepParserInvUseTest : TestCase
+ {
+ DepParserInvUseTest() : TestCase("!use") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+
+ DepSpecPrettyPrinter d(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend("!foo? ( one/one )", *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d);
+ TEST_CHECK_EQUAL(stringify(d), "!foo? ( one/one )");
+ }
+ } test_dep_spec_parser_inv_use;
+
+ struct DepParserURITest : TestCase
+ {
+ DepParserURITest() : TestCase("uri") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+
+ DepSpecPrettyPrinter d(0, tr1::shared_ptr<const PackageID>(), ff, 0, true);
+ parse_fetchable_uri("a\n->\tb", *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d);
+ TEST_CHECK_EQUAL(stringify(d), "a -> b\n");
+
+ DepSpecPrettyPrinter e(0, tr1::shared_ptr<const PackageID>(), ff, 0, true);
+ parse_fetchable_uri("a-> b", *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(e);
+ TEST_CHECK_EQUAL(stringify(e), "a->\nb\n");
+
+ TEST_CHECK_THROWS(parse_fetchable_uri("a -> b",
+ *EAPIData::get_instance()->eapi_from_string("0"))->accept(d), DepStringError);
+ }
+ } test_dep_spec_parser_uri;
+
+ /**
+ * \test Test DepParser nesting errors.
+ *
+ */
+ struct DepParserBadNestingTest : TestCase
+ {
+ DepParserBadNestingTest() : TestCase("bad nesting") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+
+ DepSpecPrettyPrinter d(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ TEST_CHECK_THROWS(parse_depend("!foo? ( one/one",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_depend("!foo? ( one/one ) )",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_depend("( ( ( ) )",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_depend("( ( ( ) ) ) )",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_depend(")",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ }
+ } test_dep_spec_parser_bad_nesting;
+
+ /**
+ * \test Test DepParser weird errors.
+ *
+ */
+ struct DepParserBadValuesTest : TestCase
+ {
+ DepParserBadValuesTest() : TestCase("bad values") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+
+ DepSpecPrettyPrinter d(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ TEST_CHECK_THROWS(parse_depend("||",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_depend("|| ",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_depend("foo?",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_depend("!foo? ||",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_depend("(((",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_depend(")",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_depend("(foo/bar)",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_license("a -> b",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+
+ TEST_CHECK_THROWS(parse_fetchable_uri("( -> )",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_fetchable_uri("( -> )",
+ *EAPIData::get_instance()->eapi_from_string("0"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_fetchable_uri("foo? -> bar",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_fetchable_uri("a ->",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_fetchable_uri("a -> ( )",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_fetchable_uri("a -> )",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_fetchable_uri("a -> || ( )",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ TEST_CHECK_THROWS(parse_fetchable_uri("a -> foo? ( )",
+ *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(d), DepStringError);
+ }
+ } test_dep_spec_parser_bad_values;
+
+ /**
+ * \test Test DepParser label handling
+ */
+ struct DepParserLabelsTest : TestCase
+ {
+ DepParserLabelsTest() : TestCase("label handling") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+
+ DepSpecPrettyPrinter d(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend("build: one/one",
+ *EAPIData::get_instance()->eapi_from_string("exheres-0"))->accept(d);
+ TEST_CHECK_EQUAL(stringify(d), "build: one/one");
+ TEST_CHECK_THROWS(parse_depend("build: one/one",
+ *EAPIData::get_instance()->eapi_from_string("0"))->accept(d), DepStringParseError);
+ }
+ } test_dep_spec_parser_labels;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/dep_spec_pretty_printer.cc b/0.26.0_alpha1/paludis/repositories/e/dep_spec_pretty_printer.cc
new file mode 100644
index 000000000..86f803e1f
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/dep_spec_pretty_printer.cc
@@ -0,0 +1,402 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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 <algorithm>
+#include <sstream>
+#include <paludis/dep_spec.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/formatter.hh>
+#include <paludis/repositories/e/dep_spec_pretty_printer.hh>
+#include <paludis/util/save.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/environment.hh>
+#include <paludis/query.hh>
+#include <paludis/package_database.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+
+/** \file
+ * Implementation of dep_spec_pretty_printer.hh.
+ *
+ * \ingroup grpdepspecprettyprinter
+ */
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+namespace paludis
+{
+ template<>
+ struct Implementation<DepSpecPrettyPrinter>
+ {
+ std::stringstream s;
+ const Environment * const env;
+ const tr1::shared_ptr<const PackageID> id;
+ GenericSpecTree::ItemFormatter formatter;
+ unsigned indent;
+ bool extra_label_indent;
+ bool use_newlines;
+ bool outer_block;
+ bool need_space;
+
+ Implementation(
+ const Environment * const e,
+ const tr1::shared_ptr<const PackageID> & i,
+ const GenericSpecTree::ItemFormatter & f,
+ unsigned in,
+ bool b) :
+ env(e),
+ id(i),
+ formatter(f),
+ indent(in),
+ extra_label_indent(false),
+ use_newlines(b),
+ outer_block(true),
+ need_space(false)
+ {
+ }
+ };
+}
+
+DepSpecPrettyPrinter::DepSpecPrettyPrinter(
+ const Environment * const e,
+ const tr1::shared_ptr<const PackageID> & id,
+ const GenericSpecTree::ItemFormatter & f,
+ unsigned i,
+ bool b) :
+ PrivateImplementationPattern<DepSpecPrettyPrinter>(new Implementation<DepSpecPrettyPrinter>(e, id, f, i, b))
+{
+}
+
+DepSpecPrettyPrinter::~DepSpecPrettyPrinter()
+{
+}
+
+std::ostream &
+paludis::erepository::operator<< (std::ostream & s, const DepSpecPrettyPrinter & p)
+{
+ s << p._imp->s.str();
+ return s;
+}
+
+void
+DepSpecPrettyPrinter::visit_sequence(const AllDepSpec &,
+ GenericSpecTree::ConstSequenceIterator cur,
+ GenericSpecTree::ConstSequenceIterator end)
+{
+ if (! _imp->outer_block)
+ {
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+ _imp->s << "(";
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+ }
+
+ {
+ Save<unsigned> old_indent(&_imp->indent, _imp->outer_block ? _imp->indent : _imp->indent + 1);
+ Save<bool> extra_label_indent(&_imp->extra_label_indent, _imp->outer_block ? _imp->extra_label_indent : false);
+ std::for_each(cur, end, accept_visitor(*this));
+ }
+
+ if (! _imp->outer_block)
+ {
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+ _imp->s << ")";
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+ }
+}
+
+void
+DepSpecPrettyPrinter::visit_sequence(const AnyDepSpec &,
+ GenericSpecTree::ConstSequenceIterator cur,
+ GenericSpecTree::ConstSequenceIterator end)
+{
+ Save<bool> old_outer(&_imp->outer_block, false);
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+ _imp->s << "|| (";
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+
+ {
+ Save<unsigned> old_indent(&_imp->indent, _imp->indent + 1);
+ Save<bool> extra_label_indent(&_imp->extra_label_indent, false);
+ std::for_each(cur, end, accept_visitor(*this));
+ }
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+ _imp->s << ")";
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+}
+
+void
+DepSpecPrettyPrinter::visit_sequence(const UseDepSpec & a,
+ GenericSpecTree::ConstSequenceIterator cur,
+ GenericSpecTree::ConstSequenceIterator end)
+{
+ Save<bool> old_outer(&_imp->outer_block, false);
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+
+ if (_imp->env && _imp->id)
+ {
+ if (_imp->env->query_use(a.flag(), *_imp->id))
+ _imp->s << _imp->formatter.format(a, format::Enabled()) << " (";
+ else
+ _imp->s << _imp->formatter.format(a, format::Disabled()) << " (";
+ }
+ else
+ _imp->s << _imp->formatter.format(a, format::Plain()) << " (";
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+
+ {
+ Save<unsigned> old_indent(&_imp->indent, _imp->indent + 1);
+ Save<bool> extra_label_indent(&_imp->extra_label_indent, false);
+ std::for_each(cur, end, accept_visitor(*this));
+ }
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+ _imp->s << ")";
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+}
+
+void
+DepSpecPrettyPrinter::visit_leaf(const PackageDepSpec & p)
+{
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+
+ if (_imp->env)
+ {
+ if (! _imp->env->package_database()->query(query::Matches(p) &
+ query::InstalledAtRoot(_imp->env->root()), qo_whatever)->empty())
+ _imp->s << _imp->formatter.format(p, format::Installed());
+ else if (! _imp->env->package_database()->query(query::Matches(p) &
+ query::SupportsAction<InstallAction>() & query::NotMasked(), qo_whatever)->empty())
+ _imp->s << _imp->formatter.format(p, format::Installable());
+ else
+ _imp->s << _imp->formatter.format(p, format::Plain());
+ }
+ else
+ _imp->s << _imp->formatter.format(p, format::Plain());
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+}
+
+void
+DepSpecPrettyPrinter::visit_leaf(const PlainTextDepSpec & p)
+{
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+
+ _imp->s << _imp->formatter.format(p, format::Plain());
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+}
+
+void
+DepSpecPrettyPrinter::visit_leaf(const NamedSetDepSpec & p)
+{
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+
+ _imp->s << _imp->formatter.format(p, format::Plain());
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+}
+
+void
+DepSpecPrettyPrinter::visit_leaf(const LicenseDepSpec & p)
+{
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+
+ if (_imp->env && _imp->id)
+ {
+ if (_imp->env->accept_license(p.text(), *_imp->id))
+ _imp->s << _imp->formatter.format(p, format::Accepted());
+ else
+ _imp->s << _imp->formatter.format(p, format::Unaccepted());
+ }
+ else
+ _imp->s << _imp->formatter.format(p, format::Plain());
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+}
+
+void
+DepSpecPrettyPrinter::visit_leaf(const FetchableURIDepSpec & p)
+{
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+
+ _imp->s << _imp->formatter.format(p, format::Plain());
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+}
+
+void
+DepSpecPrettyPrinter::visit_leaf(const SimpleURIDepSpec & p)
+{
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+
+ _imp->s << _imp->formatter.format(p, format::Plain());
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+}
+
+void
+DepSpecPrettyPrinter::visit_leaf(const BlockDepSpec & b)
+{
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+
+ _imp->s << _imp->formatter.format(b, format::Plain());
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+}
+
+void
+DepSpecPrettyPrinter::visit_leaf(const URILabelsDepSpec & l)
+{
+ if (_imp->extra_label_indent)
+ {
+ _imp->extra_label_indent = false;
+ _imp->indent -= 1;
+ }
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+
+ _imp->s << _imp->formatter.format(l, format::Plain());
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+
+ if (! _imp->extra_label_indent)
+ {
+ _imp->extra_label_indent = true;
+ _imp->indent += 1;
+ }
+}
+
+void
+DepSpecPrettyPrinter::visit_leaf(const DependencyLabelsDepSpec & l)
+{
+ if (_imp->extra_label_indent)
+ {
+ _imp->extra_label_indent = false;
+ _imp->indent -= 1;
+ }
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.indent(_imp->indent);
+ else if (_imp->need_space)
+ _imp->s << " ";
+
+ _imp->s << _imp->formatter.format(l, format::Plain());
+
+ if (_imp->use_newlines)
+ _imp->s << _imp->formatter.newline();
+ else
+ _imp->need_space = true;
+
+ if (!_imp->extra_label_indent)
+ {
+ _imp->extra_label_indent = true;
+ _imp->indent += 1;
+ }
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/dep_spec_pretty_printer.hh b/0.26.0_alpha1/paludis/repositories/e/dep_spec_pretty_printer.hh
new file mode 100644
index 000000000..48871cc33
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/dep_spec_pretty_printer.hh
@@ -0,0 +1,129 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_DEP_ATOM_PRETTY_PRINTER_HH
+#define PALUDIS_GUARD_PALUDIS_DEP_ATOM_PRETTY_PRINTER_HH 1
+
+#include <iosfwd>
+#include <paludis/dep_spec.hh>
+#include <paludis/dep_tree.hh>
+#include <paludis/metadata_key-fwd.hh>
+#include <paludis/environment-fwd.hh>
+#include <paludis/package_id-fwd.hh>
+
+/** \file
+ * Declarations for the paludis::erepository::DepSpecPrettyPrinter class.
+ *
+ * \ingroup grperepository
+ */
+
+namespace paludis
+{
+ namespace erepository
+ {
+ /**
+ * Pretty print dependency specs.
+ *
+ * \ingroup grperepository
+ */
+ class PALUDIS_VISIBLE DepSpecPrettyPrinter :
+ public ConstVisitor<GenericSpecTree>,
+ private PrivateImplementationPattern<DepSpecPrettyPrinter>
+ {
+ friend std::ostream & operator<< (std::ostream &, const DepSpecPrettyPrinter &);
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ /**
+ * Constructor.
+ *
+ * \param env An optional environment, to use for formatting PackageDepSpec items
+ * as format::Installed() etc. May be null, in which case format::Plain() is
+ * always used.
+ *
+ * \param id The ID to use for determining use flag formatting. May be null, in
+ * which case format::Plain() is used.
+ *
+ * \param formatter The formatter to use. If no fancy formatting is required, use
+ * StringifyFormatter.
+ *
+ * \param initial_indent Amount of indenting to use. Should probably be 0 if
+ * use_newlines is false.
+ *
+ * \param use_newlines Whether to format over multiple lines.
+ */
+ DepSpecPrettyPrinter(
+ const Environment * const env,
+ const tr1::shared_ptr<const PackageID> & id,
+ const GenericSpecTree::ItemFormatter & formatter,
+ unsigned initial_indent,
+ bool use_newlines);
+
+ ~DepSpecPrettyPrinter();
+
+ ///\}
+
+ /// \name Visit functions
+ ///{
+
+ void visit_sequence(const AllDepSpec &,
+ GenericSpecTree::ConstSequenceIterator,
+ GenericSpecTree::ConstSequenceIterator);
+
+ void visit_sequence(const AnyDepSpec &,
+ GenericSpecTree::ConstSequenceIterator,
+ GenericSpecTree::ConstSequenceIterator);
+
+ void visit_sequence(const UseDepSpec &,
+ GenericSpecTree::ConstSequenceIterator,
+ GenericSpecTree::ConstSequenceIterator);
+
+ void visit_leaf(const PackageDepSpec &);
+
+ void visit_leaf(const PlainTextDepSpec &);
+
+ void visit_leaf(const BlockDepSpec &);
+
+ void visit_leaf(const FetchableURIDepSpec &);
+
+ void visit_leaf(const SimpleURIDepSpec &);
+
+ void visit_leaf(const LicenseDepSpec &);
+
+ void visit_leaf(const URILabelsDepSpec &);
+
+ void visit_leaf(const DependencyLabelsDepSpec &);
+
+ void visit_leaf(const NamedSetDepSpec &);
+
+ ///}
+ };
+
+ /**
+ * Output a DepSpecPrettyPrinter to an ostream.
+ *
+ * \ingroup grperepository
+ */
+ std::ostream & operator<< (std::ostream & s, const DepSpecPrettyPrinter & p) PALUDIS_VISIBLE;
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/e/dep_spec_pretty_printer_TEST.cc b/0.26.0_alpha1/paludis/repositories/e/dep_spec_pretty_printer_TEST.cc
new file mode 100644
index 000000000..41f59639c
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/dep_spec_pretty_printer_TEST.cc
@@ -0,0 +1,103 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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 "dep_spec_pretty_printer.hh"
+#include <paludis/repositories/e/dep_parser.hh>
+#include <paludis/repositories/e/eapi.hh>
+#include <paludis/stringify_formatter.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <test/test_runner.hh>
+#include <test/test_framework.hh>
+
+using namespace test;
+using namespace paludis;
+using namespace paludis::erepository;
+
+namespace test_cases
+{
+ struct PrettyPrinterNoIndentTest : TestCase
+ {
+ PrettyPrinterNoIndentTest() : TestCase("pretty printer no indent") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+
+ DepSpecPrettyPrinter p1(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend("foo/bar bar/baz", *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(p1);
+ TEST_CHECK_STRINGIFY_EQUAL(p1, "foo/bar bar/baz");
+
+ DepSpecPrettyPrinter p2(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend("foo/bar moo? ( bar/baz )", *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(p2);
+ TEST_CHECK_STRINGIFY_EQUAL(p2, "foo/bar moo? ( bar/baz )");
+
+ DepSpecPrettyPrinter p3(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_depend("|| ( a/b ( c/d e/f ) )", *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(p3);
+ TEST_CHECK_STRINGIFY_EQUAL(p3, "|| ( a/b ( c/d e/f ) )");
+
+ DepSpecPrettyPrinter p4(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_license("( ( ( ) a ) b )", *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(p4);
+ TEST_CHECK_STRINGIFY_EQUAL(p4, "a b");
+
+ DepSpecPrettyPrinter p5(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_fetchable_uri("( a -> b c x? ( d e ) )", *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(p5);
+ TEST_CHECK_STRINGIFY_EQUAL(p5, "a -> b c x? ( d e )");
+
+ DepSpecPrettyPrinter p6(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ parse_fetchable_uri("a manual: b x? ( c mirrors-first: d manual: e ) f",
+ *EAPIData::get_instance()->eapi_from_string("exheres-0"))->accept(p6);
+ TEST_CHECK_STRINGIFY_EQUAL(p6, "a manual: b x? ( c mirrors-first: d manual: e ) f");
+ }
+ } test_pretty_printer_no_indent;
+
+ struct PrettyPrinterIndentTest : TestCase
+ {
+ PrettyPrinterIndentTest() : TestCase("pretty printer indent") { }
+
+ void run()
+ {
+ StringifyFormatter ff;
+
+ DepSpecPrettyPrinter p1(0, tr1::shared_ptr<const PackageID>(), ff, 1, true);
+ parse_depend("foo/bar bar/baz", *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(p1);
+ TEST_CHECK_STRINGIFY_EQUAL(p1, " foo/bar\n bar/baz\n");
+
+ DepSpecPrettyPrinter p2(0, tr1::shared_ptr<const PackageID>(), ff, 1, true);
+ parse_depend("foo/bar moo? ( bar/baz )", *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(p2);
+ TEST_CHECK_STRINGIFY_EQUAL(p2, " foo/bar\n moo? (\n bar/baz\n )\n");
+
+ DepSpecPrettyPrinter p3(0, tr1::shared_ptr<const PackageID>(), ff, 1, true);
+ parse_depend("|| ( a/b ( c/d e/f ) )", *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(p3);
+ TEST_CHECK_STRINGIFY_EQUAL(p3, " || (\n a/b\n (\n c/d\n"
+ " e/f\n )\n )\n");
+
+ DepSpecPrettyPrinter p4(0, tr1::shared_ptr<const PackageID>(), ff, 1, true);
+ parse_license("( ( ( ) a ) b )", *EAPIData::get_instance()->eapi_from_string("paludis-1"))->accept(p4);
+ TEST_CHECK_STRINGIFY_EQUAL(p4, " a\n b\n");
+
+ DepSpecPrettyPrinter p5(0, tr1::shared_ptr<const PackageID>(), ff, 1, true);
+ parse_fetchable_uri("a manual: b x? ( c mirrors-first: d manual: e ) f",
+ *EAPIData::get_instance()->eapi_from_string("exheres-0"))->accept(p5);
+ TEST_CHECK_STRINGIFY_EQUAL(p5, " a\n manual:\n b\n x? (\n c\n"
+ " mirrors-first:\n d\n manual:\n e\n )\n f\n");
+ }
+ } test_pretty_printer_indent;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_key.cc b/0.26.0_alpha1/paludis/repositories/e/e_key.cc
new file mode 100644
index 000000000..87ca92772
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_key.cc
@@ -0,0 +1,1229 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/repositories/e/dep_parser.hh>
+#include <paludis/repositories/e/eapi.hh>
+#include <paludis/repositories/e/dep_spec_pretty_printer.hh>
+
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/iterator.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/mutex.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/tr1_functional.hh>
+#include <paludis/util/idle_action_pool.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/visitor-impl.hh>
+
+#include <paludis/contents.hh>
+#include <paludis/repository.hh>
+#include <paludis/environment.hh>
+#include <paludis/stringify_formatter-impl.hh>
+#include <paludis/dep_spec_flattener.hh>
+
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+
+#include <list>
+#include <vector>
+#include <fstream>
+#include <map>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+EStringKey::EStringKey(const tr1::shared_ptr<const ERepositoryID> &,
+ 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;
+}
+
+EMutableRepositoryMaskInfoKey::EMutableRepositoryMaskInfoKey(const tr1::shared_ptr<const ERepositoryID> &,
+ const std::string & r, const std::string & h, tr1::shared_ptr<const RepositoryMaskInfo> v, const MetadataKeyType t) :
+ MetadataRepositoryMaskInfoKey(r, h, t),
+ _value(v)
+{
+}
+
+EMutableRepositoryMaskInfoKey::~EMutableRepositoryMaskInfoKey()
+{
+}
+
+const tr1::shared_ptr<const RepositoryMaskInfo>
+EMutableRepositoryMaskInfoKey::value() const
+{
+ return _value;
+}
+
+void
+EMutableRepositoryMaskInfoKey::set_value(tr1::shared_ptr<const RepositoryMaskInfo> v)
+{
+ _value = v;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EDependenciesKey>
+ {
+ const Environment * const env;
+ const tr1::shared_ptr<const ERepositoryID> id;
+ const std::string string_value;
+ mutable Mutex value_mutex;
+ mutable tr1::shared_ptr<const DependencySpecTree::ConstItem> value;
+ mutable tr1::function<void () throw ()> value_used;
+
+ Implementation(
+ const Environment * const e,
+ const tr1::shared_ptr<const ERepositoryID> & i, const std::string & v) :
+ env(e),
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+EDependenciesKey::EDependenciesKey(
+ const Environment * const e,
+ const tr1::shared_ptr<const ERepositoryID> & 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>(e, id, v)),
+ _imp(PrivateImplementationPattern<EDependenciesKey>::_imp.get())
+{
+}
+
+EDependenciesKey::~EDependenciesKey()
+{
+}
+
+const tr1::shared_ptr<const DependencySpecTree::ConstItem>
+EDependenciesKey::value() const
+{
+ Lock l(_imp->value_mutex);
+ if (_imp->value)
+ {
+ if (_imp->value_used)
+ {
+ _imp->value_used();
+ _imp->value_used = tr1::function<void () throw ()>();
+ }
+ return _imp->value;
+ }
+
+ IdleActionPool::get_instance()->increase_unprepared_stat();
+
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ _imp->value = parse_depend(_imp->string_value, *_imp->id->eapi());
+ return _imp->value;
+}
+
+std::string
+EDependenciesKey::pretty_print(const DependencySpecTree::ItemFormatter & f) const
+{
+ StringifyFormatter ff(f);
+ DepSpecPrettyPrinter p(_imp->env, _imp->id, ff, 0, true);
+ value()->accept(p);
+ return stringify(p);
+}
+
+std::string
+EDependenciesKey::pretty_print_flat(const DependencySpecTree::ItemFormatter & f) const
+{
+ StringifyFormatter ff(f);
+ DepSpecPrettyPrinter p(_imp->env, _imp->id, ff, 0, false);
+ value()->accept(p);
+ return stringify(p);
+}
+
+IdleActionResult
+EDependenciesKey::idle_load() const
+{
+ TryLock l(_imp->value_mutex);
+ if (l() && ! _imp->value)
+ {
+ try
+ {
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "' as idle action:");
+ _imp->value = parse_depend(_imp->string_value, *_imp->id->eapi());
+ _imp->value_used = tr1::bind(tr1::mem_fn(&IdleActionPool::increase_used_stat), IdleActionPool::get_instance());
+ return iar_success;
+ }
+ catch (...)
+ {
+ // the exception will be repeated in the relevant thread
+ return iar_failure;
+ }
+ }
+
+ return iar_already_completed;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<ELicenseKey>
+ {
+ const Environment * const env;
+ const tr1::shared_ptr<const ERepositoryID> id;
+ const std::string string_value;
+ mutable Mutex value_mutex;
+ mutable tr1::shared_ptr<const LicenseSpecTree::ConstItem> value;
+ mutable tr1::function<void () throw ()> value_used;
+
+ Implementation(const Environment * const e,
+ const tr1::shared_ptr<const ERepositoryID> & i, const std::string & v) :
+ env(e),
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+ELicenseKey::ELicenseKey(
+ const Environment * const e,
+ const tr1::shared_ptr<const ERepositoryID> & 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>(e, id, v)),
+ _imp(PrivateImplementationPattern<ELicenseKey>::_imp.get())
+{
+}
+
+ELicenseKey::~ELicenseKey()
+{
+}
+
+const tr1::shared_ptr<const LicenseSpecTree::ConstItem>
+ELicenseKey::value() const
+{
+ Lock l(_imp->value_mutex);
+ if (_imp->value)
+ {
+ if (_imp->value_used)
+ {
+ _imp->value_used();
+ _imp->value_used = tr1::function<void () throw ()>();
+ }
+ return _imp->value;
+ }
+
+ IdleActionPool::get_instance()->increase_unprepared_stat();
+
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ _imp->value = parse_license(_imp->string_value, *_imp->id->eapi());
+ return _imp->value;
+}
+
+std::string
+ELicenseKey::pretty_print(const LicenseSpecTree::ItemFormatter & f) const
+{
+ StringifyFormatter ff(f);
+ DepSpecPrettyPrinter p(_imp->env, _imp->id, ff, 0, true);
+ value()->accept(p);
+ return stringify(p);
+}
+
+std::string
+ELicenseKey::pretty_print_flat(const LicenseSpecTree::ItemFormatter & f) const
+{
+ StringifyFormatter ff(f);
+ DepSpecPrettyPrinter p(_imp->env, _imp->id, ff, 0, false);
+ value()->accept(p);
+ return stringify(p);
+}
+
+IdleActionResult
+ELicenseKey::idle_load() const
+{
+ TryLock l(_imp->value_mutex);
+ if (l() && ! _imp->value)
+ {
+ try
+ {
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "' as idle action:");
+ _imp->value = parse_license(_imp->string_value, *_imp->id->eapi());
+ _imp->value_used = tr1::bind(tr1::mem_fn(&IdleActionPool::increase_used_stat), IdleActionPool::get_instance());
+ return iar_success;
+ }
+ catch (...)
+ {
+ // the exception will be repeated in the relevant thread
+ return iar_failure;
+ }
+ }
+
+ return iar_already_completed;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EFetchableURIKey>
+ {
+ const Environment * const env;
+ const tr1::shared_ptr<const ERepositoryID> id;
+ const std::string string_value;
+ mutable Mutex value_mutex;
+ mutable tr1::shared_ptr<const FetchableURISpecTree::ConstItem> value;
+ mutable tr1::shared_ptr<const URILabel> initial_label;
+
+ Implementation(const Environment * const e, const tr1::shared_ptr<const ERepositoryID> & i, const std::string & v) :
+ env(e),
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+EFetchableURIKey::EFetchableURIKey(const Environment * const e,
+ const tr1::shared_ptr<const ERepositoryID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataSpecTreeKey<FetchableURISpecTree>(r, h, t),
+ PrivateImplementationPattern<EFetchableURIKey>(new Implementation<EFetchableURIKey>(e, id, v)),
+ _imp(PrivateImplementationPattern<EFetchableURIKey>::_imp.get())
+{
+}
+
+EFetchableURIKey::~EFetchableURIKey()
+{
+}
+
+const tr1::shared_ptr<const FetchableURISpecTree::ConstItem>
+EFetchableURIKey::value() const
+{
+ Lock l(_imp->value_mutex);
+
+ if (_imp->value)
+ return _imp->value;
+
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ _imp->value = parse_fetchable_uri(_imp->string_value, *_imp->id->eapi());
+ return _imp->value;
+}
+
+std::string
+EFetchableURIKey::pretty_print(const FetchableURISpecTree::ItemFormatter & f) const
+{
+ StringifyFormatter ff(f);
+ DepSpecPrettyPrinter p(_imp->env, _imp->id, ff, 0, true);
+ value()->accept(p);
+ return stringify(p);
+}
+
+std::string
+EFetchableURIKey::pretty_print_flat(const FetchableURISpecTree::ItemFormatter & f) const
+{
+ StringifyFormatter ff(f);
+ DepSpecPrettyPrinter p(_imp->env, _imp->id, ff, 0, false);
+ value()->accept(p);
+ return stringify(p);
+}
+
+const tr1::shared_ptr<const URILabel>
+EFetchableURIKey::initial_label() const
+{
+ Lock l(_imp->value_mutex);
+
+ if (! _imp->initial_label)
+ {
+ DepSpecFlattener<RestrictSpecTree, PlainTextDepSpec> f(_imp->env, *_imp->id);
+ if (_imp->id->restrict_key())
+ _imp->id->restrict_key()->value()->accept(f);
+ for (DepSpecFlattener<RestrictSpecTree, PlainTextDepSpec>::ConstIterator i(f.begin()), i_end(f.end()) ;
+ i != i_end ; ++i)
+ {
+ if (_imp->id->eapi()->supported->ebuild_options->restrict_fetch->end() !=
+ std::find(_imp->id->eapi()->supported->ebuild_options->restrict_fetch->begin(),
+ _imp->id->eapi()->supported->ebuild_options->restrict_fetch->end(), (*i)->text()))
+ _imp->initial_label = *parse_uri_label("default-restrict-fetch:", *_imp->id->eapi())->begin();
+
+ else if (_imp->id->eapi()->supported->ebuild_options->restrict_fetch->end() !=
+ std::find(_imp->id->eapi()->supported->ebuild_options->restrict_fetch->begin(),
+ _imp->id->eapi()->supported->ebuild_options->restrict_fetch->end(), (*i)->text()))
+ _imp->initial_label = *parse_uri_label("default-restrict-mirror:", *_imp->id->eapi())->begin();
+ }
+
+ if (! _imp->initial_label)
+ _imp->initial_label = *parse_uri_label("default:", *_imp->id->eapi())->begin();
+ }
+
+ return _imp->initial_label;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<ESimpleURIKey>
+ {
+ const Environment * const env;
+ const tr1::shared_ptr<const ERepositoryID> id;
+ const std::string string_value;
+ mutable Mutex value_mutex;
+ mutable tr1::shared_ptr<const SimpleURISpecTree::ConstItem> value;
+
+ Implementation(const Environment * const e, const tr1::shared_ptr<const ERepositoryID> & i, const std::string & v) :
+ env(e),
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+ESimpleURIKey::ESimpleURIKey(const Environment * const e,
+ const tr1::shared_ptr<const ERepositoryID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataSpecTreeKey<SimpleURISpecTree>(r, h, t),
+ PrivateImplementationPattern<ESimpleURIKey>(new Implementation<ESimpleURIKey>(e, id, v)),
+ _imp(PrivateImplementationPattern<ESimpleURIKey>::_imp.get())
+{
+}
+
+ESimpleURIKey::~ESimpleURIKey()
+{
+}
+
+const tr1::shared_ptr<const SimpleURISpecTree::ConstItem>
+ESimpleURIKey::value() const
+{
+ Lock l(_imp->value_mutex);
+
+ if (_imp->value)
+ return _imp->value;
+
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ _imp->value = parse_simple_uri(_imp->string_value, *_imp->id->eapi());
+ return _imp->value;
+}
+
+std::string
+ESimpleURIKey::pretty_print(const SimpleURISpecTree::ItemFormatter & f) const
+{
+ StringifyFormatter ff(f);
+ DepSpecPrettyPrinter p(_imp->env, _imp->id, ff, 0, true);
+ value()->accept(p);
+ return stringify(p);
+}
+
+std::string
+ESimpleURIKey::pretty_print_flat(const SimpleURISpecTree::ItemFormatter & f) const
+{
+ StringifyFormatter ff(f);
+ DepSpecPrettyPrinter p(_imp->env, _imp->id, ff, 0, false);
+ value()->accept(p);
+ return stringify(p);
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<ERestrictKey>
+ {
+ const Environment * const env;
+ const tr1::shared_ptr<const ERepositoryID> id;
+ const std::string string_value;
+ mutable Mutex value_mutex;
+ mutable tr1::shared_ptr<const RestrictSpecTree::ConstItem> value;
+
+ Implementation(const Environment * const e, const tr1::shared_ptr<const ERepositoryID> & i, const std::string & v) :
+ env(e),
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+ERestrictKey::ERestrictKey(const Environment * const e,
+ const tr1::shared_ptr<const ERepositoryID> & 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>(e, id, v)),
+ _imp(PrivateImplementationPattern<ERestrictKey>::_imp.get())
+{
+}
+
+ERestrictKey::~ERestrictKey()
+{
+}
+
+const tr1::shared_ptr<const RestrictSpecTree::ConstItem>
+ERestrictKey::value() const
+{
+ Lock l(_imp->value_mutex);
+
+ if (_imp->value)
+ return _imp->value;
+
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ _imp->value = parse_restrict(_imp->string_value, *_imp->id->eapi());
+ return _imp->value;
+}
+
+std::string
+ERestrictKey::pretty_print(const RestrictSpecTree::ItemFormatter & f) const
+{
+ StringifyFormatter ff(f);
+ DepSpecPrettyPrinter p(_imp->env, _imp->id, ff, 0, true);
+ value()->accept(p);
+ return stringify(p);
+}
+
+std::string
+ERestrictKey::pretty_print_flat(const RestrictSpecTree::ItemFormatter & f) const
+{
+ StringifyFormatter ff(f);
+ DepSpecPrettyPrinter p(_imp->env, _imp->id, ff, 0, false);
+ value()->accept(p);
+ return stringify(p);
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EProvideKey>
+ {
+ const Environment * const env;
+ const tr1::shared_ptr<const ERepositoryID> id;
+ const std::string string_value;
+ mutable Mutex value_mutex;
+ mutable tr1::shared_ptr<const ProvideSpecTree::ConstItem> value;
+
+ Implementation(const Environment * const e, const tr1::shared_ptr<const ERepositoryID> & i, const std::string & v) :
+ env(e),
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+EProvideKey::EProvideKey(const Environment * const e, const tr1::shared_ptr<const ERepositoryID> & 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>(e, id, v)),
+ _imp(PrivateImplementationPattern<EProvideKey>::_imp.get())
+{
+}
+
+EProvideKey::~EProvideKey()
+{
+}
+
+const tr1::shared_ptr<const ProvideSpecTree::ConstItem>
+EProvideKey::value() const
+{
+ Lock l(_imp->value_mutex);
+
+ if (_imp->value)
+ return _imp->value;
+
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ _imp->value = parse_provide(_imp->string_value, *_imp->id->eapi());
+ return _imp->value;
+}
+
+std::string
+EProvideKey::pretty_print(const ProvideSpecTree::ItemFormatter & f) const
+{
+ StringifyFormatter ff(f);
+ DepSpecPrettyPrinter p(_imp->env, _imp->id, ff, 0, true);
+ value()->accept(p);
+ return stringify(p);
+}
+
+std::string
+EProvideKey::pretty_print_flat(const ProvideSpecTree::ItemFormatter & f) const
+{
+ StringifyFormatter ff(f);
+ DepSpecPrettyPrinter p(_imp->env, _imp->id, ff, 0, false);
+ value()->accept(p);
+ return stringify(p);
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EIUseKey>
+ {
+ const tr1::shared_ptr<const ERepositoryID> id;
+ const Environment * const env;
+ const std::string string_value;
+ mutable Mutex value_mutex;
+ mutable tr1::shared_ptr<IUseFlagSet> value;
+ mutable tr1::function<void () throw ()> value_used;
+
+ Implementation(const tr1::shared_ptr<const ERepositoryID> & i, const Environment * const e, const std::string & v) :
+ id(i),
+ env(e),
+ string_value(v)
+ {
+ }
+ };
+}
+
+EIUseKey::EIUseKey(
+ const Environment * const e,
+ const tr1::shared_ptr<const ERepositoryID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataSetKey<IUseFlagSet>(r, h, t),
+ PrivateImplementationPattern<EIUseKey>(new Implementation<EIUseKey>(id, e, v)),
+ _imp(PrivateImplementationPattern<EIUseKey>::_imp.get())
+{
+}
+
+EIUseKey::~EIUseKey()
+{
+}
+
+const tr1::shared_ptr<const IUseFlagSet>
+EIUseKey::value() const
+{
+ Lock l(_imp->value_mutex);
+ if (_imp->value)
+ {
+ if (_imp->value_used)
+ {
+ _imp->value_used();
+ _imp->value_used = tr1::function<void () throw ()>();
+ }
+ return _imp->value;
+ }
+
+ IdleActionPool::get_instance()->increase_unprepared_stat();
+
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ _imp->value.reset(new IUseFlagSet);
+ std::list<std::string> tokens;
+ WhitespaceTokeniser::tokenise(_imp->string_value, std::back_inserter(tokens));
+
+ tr1::shared_ptr<const UseFlagNameSet> prefixes;
+ if (_imp->id->repository()->use_interface)
+ prefixes = _imp->id->repository()->use_interface->use_expand_prefixes();
+ else
+ prefixes.reset(new UseFlagNameSet);
+
+ for (std::list<std::string>::const_iterator t(tokens.begin()), t_end(tokens.end()) ;
+ t != t_end ; ++t)
+ {
+ IUseFlag f(*t, _imp->id->eapi()->supported->iuse_flag_parse_mode, std::string::npos);
+ for (UseFlagNameSet::ConstIterator p(prefixes->begin()), p_end(prefixes->end()) ;
+ p != p_end ; ++p)
+ if (0 == stringify(f.flag).compare(0, stringify(*p).length(), stringify(*p), 0, stringify(*p).length()))
+ f.prefix_delim_pos = stringify(*p).length();
+ _imp->value->insert(f);
+ }
+
+ return _imp->value;
+}
+
+IdleActionResult
+EIUseKey::idle_load() const
+{
+ TryLock l(_imp->value_mutex);
+ if (l() && ! _imp->value)
+ {
+ try
+ {
+ tr1::shared_ptr<const IUseFlagSet> PALUDIS_ATTRIBUTE((unused)) a(value());
+ }
+ catch (...)
+ {
+ // the exception will be repeated in the relevant thread
+ _imp->value.reset();
+ return iar_failure;
+ }
+
+ return iar_success;
+ }
+
+ return iar_already_completed;
+}
+
+std::string
+EIUseKey::pretty_print_flat(const Formatter<IUseFlag> & f) const
+{
+ std::string result;
+ std::multimap<std::string, IUseFlag> prefixes;
+ for (IUseFlagSet::ConstIterator i(value()->begin()), i_end(value()->end()) ;
+ i != i_end ; ++i)
+ {
+ if (std::string::npos != i->prefix_delim_pos)
+ {
+ prefixes.insert(std::make_pair(stringify(i->flag).substr(0, i->prefix_delim_pos), *i));
+ continue;
+ }
+
+ if (! result.empty())
+ result.append(" ");
+
+ if (_imp->id->repository()->use_interface && _imp->id->repository()->use_interface->query_use_mask(i->flag, *_imp->id))
+ result.append(f.format(*i, format::Masked()));
+ else if (_imp->id->repository()->use_interface && _imp->id->repository()->use_interface->query_use_force(i->flag, *_imp->id))
+ result.append(f.format(*i, format::Forced()));
+ else if (_imp->env->query_use(i->flag, *_imp->id))
+ result.append(f.format(*i, format::Enabled()));
+ else
+ result.append(f.format(*i, format::Disabled()));
+ }
+
+ for (std::multimap<std::string, IUseFlag>::const_iterator j(prefixes.begin()), j_end(prefixes.end()) ;
+ j != j_end ; ++j)
+ {
+ if (! result.empty())
+ result.append(" ");
+
+ if (_imp->id->repository()->use_interface && _imp->id->repository()->use_interface->query_use_mask(j->second.flag, *_imp->id))
+ result.append(f.format(j->second, format::Masked()));
+ else if (_imp->id->repository()->use_interface && _imp->id->repository()->use_interface->query_use_force(j->second.flag, *_imp->id))
+ result.append(f.format(j->second, format::Forced()));
+ else if (_imp->env->query_use(j->second.flag, *_imp->id))
+ result.append(f.format(j->second, format::Enabled()));
+ else
+ result.append(f.format(j->second, format::Disabled()));
+ }
+
+ return result;
+}
+
+std::string
+EIUseKey::pretty_print_flat_with_comparison(
+ const Environment * const env,
+ const tr1::shared_ptr<const PackageID> & id,
+ const Formatter<IUseFlag> & f) const
+{
+ std::string result;
+ std::multimap<std::string, IUseFlag> prefixes;
+ for (IUseFlagSet::ConstIterator i(value()->begin()), i_end(value()->end()) ;
+ i != i_end ; ++i)
+ {
+ if (std::string::npos != i->prefix_delim_pos)
+ {
+ prefixes.insert(std::make_pair(stringify(i->flag).substr(0, i->prefix_delim_pos), *i));
+ continue;
+ }
+
+ if (! result.empty())
+ result.append(" ");
+
+ std::string l;
+ bool n;
+
+ if (_imp->id->repository()->use_interface && _imp->id->repository()->use_interface->query_use_mask(i->flag, *_imp->id))
+ {
+ l = f.format(*i, format::Masked());
+ n = false;
+ }
+ else if (_imp->id->repository()->use_interface && _imp->id->repository()->use_interface->query_use_force(i->flag, *_imp->id))
+ {
+ l = f.format(*i, format::Forced());
+ n = true;
+ }
+ else if (_imp->env->query_use(i->flag, *_imp->id))
+ {
+ l = f.format(*i, format::Enabled());
+ n = true;
+ }
+ else
+ {
+ l = f.format(*i, format::Disabled());
+ n = false;
+ }
+
+ if (! id->iuse_key())
+ l = f.decorate(*i, l, format::Added());
+ else
+ {
+ using namespace tr1::placeholders;
+ IUseFlagSet::ConstIterator p(std::find_if(id->iuse_key()->value()->begin(), id->iuse_key()->value()->end(),
+ tr1::bind(std::equal_to<UseFlagName>(), i->flag, tr1::bind<const UseFlagName>(&IUseFlag::flag, _1))));
+
+ if (p == id->iuse_key()->value()->end())
+ l = f.decorate(*i, l, format::Added());
+ else if (n != env->query_use(i->flag, *id))
+ l = f.decorate(*i, l, format::Changed());
+ }
+
+ result.append(l);
+ }
+
+ for (std::multimap<std::string, IUseFlag>::const_iterator j(prefixes.begin()), j_end(prefixes.end()) ;
+ j != j_end ; ++j)
+ {
+ if (! result.empty())
+ result.append(" ");
+
+ std::string l;
+ bool n;
+
+ if (_imp->id->repository()->use_interface && _imp->id->repository()->use_interface->query_use_mask(j->second.flag, *_imp->id))
+ {
+ l = f.format(j->second, format::Masked());
+ n = false;
+ }
+ else if (_imp->id->repository()->use_interface && _imp->id->repository()->use_interface->query_use_force(j->second.flag, *_imp->id))
+ {
+ l = f.format(j->second, format::Forced());
+ n = true;
+ }
+ else if (_imp->env->query_use(j->second.flag, *_imp->id))
+ {
+ l = f.format(j->second, format::Enabled());
+ n = true;
+ }
+ else
+ {
+ l = f.format(j->second, format::Disabled());
+ n = false;
+ }
+
+ if (! id->iuse_key())
+ l = f.decorate(j->second, l, format::Added());
+ else
+ {
+ using namespace tr1::placeholders;
+ IUseFlagSet::ConstIterator p(std::find_if(id->iuse_key()->value()->begin(), id->iuse_key()->value()->end(),
+ tr1::bind(std::equal_to<UseFlagName>(), j->second.flag, tr1::bind<const UseFlagName>(&IUseFlag::flag, _1))));
+
+ if (p == id->iuse_key()->value()->end())
+ l = f.decorate(j->second, l, format::Added());
+ else if (n != env->query_use(j->second.flag, *id))
+ l = f.decorate(j->second, l, format::Changed());
+ }
+
+ result.append(l);
+ }
+
+ return result;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EKeywordsKey>
+ {
+ const tr1::shared_ptr<const ERepositoryID> id;
+ const Environment * const env;
+ const std::string string_value;
+ mutable Mutex value_mutex;
+ mutable tr1::shared_ptr<KeywordNameSet> value;
+ mutable tr1::function<void () throw ()> value_used;
+
+ Implementation(const tr1::shared_ptr<const ERepositoryID> & i, const Environment * const e, const std::string & v) :
+ id(i),
+ env(e),
+ string_value(v)
+ {
+ }
+ };
+}
+
+EKeywordsKey::EKeywordsKey(const Environment * const e, const tr1::shared_ptr<const ERepositoryID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataSetKey<KeywordNameSet>(r, h, t),
+ PrivateImplementationPattern<EKeywordsKey>(new Implementation<EKeywordsKey>(id, e, v)),
+ _imp(PrivateImplementationPattern<EKeywordsKey>::_imp.get())
+{
+}
+
+EKeywordsKey::~EKeywordsKey()
+{
+}
+
+const tr1::shared_ptr<const KeywordNameSet>
+EKeywordsKey::value() const
+{
+ Lock l(_imp->value_mutex);
+ if (_imp->value)
+ {
+ if (_imp->value_used)
+ {
+ _imp->value_used();
+ _imp->value_used = tr1::function<void () throw ()>();
+ }
+ return _imp->value;
+ }
+
+ IdleActionPool::get_instance()->increase_unprepared_stat();
+
+ _imp->value.reset(new KeywordNameSet);
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ WhitespaceTokeniser::tokenise(_imp->string_value, create_inserter<KeywordName>(_imp->value->inserter()));
+ return _imp->value;
+}
+
+IdleActionResult
+EKeywordsKey::idle_load() const
+{
+ TryLock l(_imp->value_mutex);
+ if (l() && ! _imp->value)
+ {
+ try
+ {
+ _imp->value.reset(new KeywordNameSet);
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "' as idle action:");
+ WhitespaceTokeniser::tokenise(_imp->string_value, create_inserter<KeywordName>(_imp->value->inserter()));
+ _imp->value_used = tr1::bind(tr1::mem_fn(&IdleActionPool::increase_used_stat), IdleActionPool::get_instance());
+ return iar_success;
+ }
+ catch (...)
+ {
+ // the exception will be repeated in the relevant thread
+ _imp->value.reset();
+ return iar_failure;
+ }
+ }
+
+ return iar_already_completed;
+}
+
+std::string
+EKeywordsKey::pretty_print_flat(const Formatter<KeywordName> & f) const
+{
+ std::string result;
+ for (KeywordNameSet::ConstIterator i(value()->begin()), i_end(value()->end()) ;
+ i != i_end ; ++i)
+ {
+ if (! result.empty())
+ result.append(" ");
+
+ tr1::shared_ptr<KeywordNameSet> k(new KeywordNameSet);
+ k->insert(*i);
+ if (_imp->env->accept_keywords(k, *_imp->id))
+ result.append(f.format(*i, format::Accepted()));
+ else
+ result.append(f.format(*i, format::Unaccepted()));
+ }
+
+ return result;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EUseKey>
+ {
+ const tr1::shared_ptr<const ERepositoryID> id;
+ const Environment * const env;
+ const std::string string_value;
+ mutable Mutex value_mutex;
+ mutable tr1::shared_ptr<UseFlagNameSet> value;
+
+ Implementation(const tr1::shared_ptr<const ERepositoryID> & i, const Environment * const e, const std::string & v) :
+ id(i),
+ env(e),
+ string_value(v)
+ {
+ }
+ };
+}
+
+EUseKey::EUseKey(const Environment * const e, const tr1::shared_ptr<const ERepositoryID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataSetKey<UseFlagNameSet>(r, h, t),
+ PrivateImplementationPattern<EUseKey>(new Implementation<EUseKey>(id, e, v)),
+ _imp(PrivateImplementationPattern<EUseKey>::_imp.get())
+{
+}
+
+EUseKey::~EUseKey()
+{
+}
+
+const tr1::shared_ptr<const UseFlagNameSet>
+EUseKey::value() const
+{
+ Lock l(_imp->value_mutex);
+
+ if (_imp->value)
+ return _imp->value;
+
+ _imp->value.reset(new UseFlagNameSet);
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ std::list<std::string> tokens;
+ WhitespaceTokeniser::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;
+}
+
+std::string
+EUseKey::pretty_print_flat(const Formatter<UseFlagName> & f) const
+{
+ std::string result;
+ for (UseFlagNameSet::ConstIterator i(value()->begin()), i_end(value()->end()) ;
+ i != i_end ; ++i)
+ {
+ if (! result.empty())
+ result.append(" ");
+
+ if (_imp->id->repository()->use_interface && _imp->id->repository()->use_interface->query_use_mask(*i, *_imp->id))
+ result.append(f.format(*i, format::Masked()));
+ else if (_imp->id->repository()->use_interface && _imp->id->repository()->use_interface->query_use_force(*i, *_imp->id))
+ result.append(f.format(*i, format::Forced()));
+ else if (_imp->env->query_use(*i, *_imp->id))
+ result.append(f.format(*i, format::Enabled()));
+ else
+ result.append(f.format(*i, format::Disabled()));
+ }
+
+ return result;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EInheritedKey>
+ {
+ const tr1::shared_ptr<const ERepositoryID> id;
+ const std::string string_value;
+ mutable Mutex value_mutex;
+ mutable tr1::shared_ptr<Set<std::string> > value;
+
+ Implementation(const tr1::shared_ptr<const ERepositoryID> & i, const std::string & v) :
+ id(i),
+ string_value(v)
+ {
+ }
+ };
+}
+
+EInheritedKey::EInheritedKey(const tr1::shared_ptr<const ERepositoryID> & id,
+ const std::string & r, const std::string & h, const std::string & v, const MetadataKeyType t) :
+ MetadataSetKey<Set<std::string> >(r, h, t),
+ PrivateImplementationPattern<EInheritedKey>(new Implementation<EInheritedKey>(id, v)),
+ _imp(PrivateImplementationPattern<EInheritedKey>::_imp.get())
+{
+}
+
+EInheritedKey::~EInheritedKey()
+{
+}
+
+const tr1::shared_ptr<const Set<std::string> >
+EInheritedKey::value() const
+{
+ Lock l(_imp->value_mutex);
+
+ if (_imp->value)
+ return _imp->value;
+
+ _imp->value.reset(new Set<std::string>);
+ Context context("When parsing metadata key '" + raw_name() + "' from '" + stringify(*_imp->id) + "':");
+ WhitespaceTokeniser::tokenise(_imp->string_value, _imp->value->inserter());
+ return _imp->value;
+}
+
+std::string
+EInheritedKey::pretty_print_flat(const Formatter<std::string> &) const
+{
+ return join(value()->begin(), value()->end(), " ");
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EContentsKey>
+ {
+ const tr1::shared_ptr<const ERepositoryID> id;
+ const FSEntry filename;
+ mutable Mutex value_mutex;
+ mutable tr1::shared_ptr<Contents> value;
+
+ Implementation(const tr1::shared_ptr<const ERepositoryID> & i, const FSEntry & v) :
+ id(i),
+ filename(v)
+ {
+ }
+ };
+}
+
+EContentsKey::EContentsKey(const tr1::shared_ptr<const ERepositoryID> & 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
+{
+ Lock l(_imp->value_mutex);
+
+ 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::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 ERepositoryID> id;
+ const FSEntry filename;
+ mutable Mutex value_mutex;
+ mutable tr1::shared_ptr<time_t> value;
+
+ Implementation(const tr1::shared_ptr<const ERepositoryID> & i, const FSEntry & v) :
+ id(i),
+ filename(v)
+ {
+ }
+ };
+}
+
+ECTimeKey::ECTimeKey(const tr1::shared_ptr<const ERepositoryID> & 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
+{
+ Lock l(_imp->value_mutex);
+
+ 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;
+}
+
+EFSLocationKey::EFSLocationKey(const tr1::shared_ptr<const ERepositoryID> &,
+ const std::string & r, const std::string & h, const FSEntry & v, const MetadataKeyType t) :
+ MetadataFSEntryKey(r, h, t),
+ _value(v)
+{
+}
+
+EFSLocationKey::~EFSLocationKey()
+{
+}
+
+const FSEntry
+EFSLocationKey::value() const
+{
+ return _value;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_key.hh b/0.26.0_alpha1/paludis/repositories/e/e_key.hh
new file mode 100644
index 000000000..bdad1ac37
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_key.hh
@@ -0,0 +1,356 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/idle_action_pool-fwd.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/set.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ class ERepositoryID;
+
+ class EStringKey :
+ public MetadataStringKey
+ {
+ private:
+ const std::string _value;
+
+ public:
+ EStringKey(const tr1::shared_ptr<const ERepositoryID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~EStringKey();
+
+ virtual const std::string value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EMutableRepositoryMaskInfoKey :
+ public MetadataRepositoryMaskInfoKey
+ {
+ private:
+ tr1::shared_ptr<const RepositoryMaskInfo> _value;
+
+ public:
+ EMutableRepositoryMaskInfoKey(const tr1::shared_ptr<const ERepositoryID> &,
+ const std::string &, const std::string &, tr1::shared_ptr<const RepositoryMaskInfo>, const MetadataKeyType);
+ ~EMutableRepositoryMaskInfoKey();
+
+ virtual const tr1::shared_ptr<const RepositoryMaskInfo> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ void set_value(tr1::shared_ptr<const RepositoryMaskInfo>);
+ };
+
+ class EDependenciesKey :
+ public MetadataSpecTreeKey<DependencySpecTree>,
+ private PrivateImplementationPattern<EDependenciesKey>
+ {
+ private:
+ Implementation<EDependenciesKey> * const _imp;
+
+ public:
+ EDependenciesKey(
+ const Environment * const,
+ const tr1::shared_ptr<const ERepositoryID> &,
+ 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));
+
+ virtual std::string pretty_print(const DependencySpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print_flat(const DependencySpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ IdleActionResult idle_load() const;
+ };
+
+ class EFetchableURIKey :
+ public MetadataSpecTreeKey<FetchableURISpecTree>,
+ private PrivateImplementationPattern<EFetchableURIKey>
+ {
+ private:
+ Implementation<EFetchableURIKey> * const _imp;
+
+ public:
+ EFetchableURIKey(const Environment * const,
+ const tr1::shared_ptr<const ERepositoryID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~EFetchableURIKey();
+
+ virtual const tr1::shared_ptr<const FetchableURISpecTree::ConstItem> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print(const FetchableURISpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print_flat(const FetchableURISpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual const tr1::shared_ptr<const URILabel> initial_label() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class ESimpleURIKey :
+ public MetadataSpecTreeKey<SimpleURISpecTree>,
+ private PrivateImplementationPattern<ESimpleURIKey>
+ {
+ private:
+ Implementation<ESimpleURIKey> * const _imp;
+
+ public:
+ ESimpleURIKey(const Environment * const,
+ const tr1::shared_ptr<const ERepositoryID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~ESimpleURIKey();
+
+ virtual const tr1::shared_ptr<const SimpleURISpecTree::ConstItem> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print(const SimpleURISpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print_flat(const SimpleURISpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class ERestrictKey :
+ public MetadataSpecTreeKey<RestrictSpecTree>,
+ private PrivateImplementationPattern<ERestrictKey>
+ {
+ private:
+ Implementation<ERestrictKey> * const _imp;
+
+ public:
+ ERestrictKey(const Environment * const,
+ const tr1::shared_ptr<const ERepositoryID> &,
+ 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));
+
+ virtual std::string pretty_print(const RestrictSpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print_flat(const RestrictSpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EProvideKey :
+ public MetadataSpecTreeKey<ProvideSpecTree>,
+ private PrivateImplementationPattern<EProvideKey>
+ {
+ private:
+ Implementation<EProvideKey> * const _imp;
+
+ public:
+ EProvideKey(const Environment * const,
+ const tr1::shared_ptr<const ERepositoryID> &,
+ 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));
+
+ virtual std::string pretty_print(const ProvideSpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print_flat(const ProvideSpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class ELicenseKey :
+ public MetadataSpecTreeKey<LicenseSpecTree>,
+ private PrivateImplementationPattern<ELicenseKey>
+ {
+ private:
+ Implementation<ELicenseKey> * const _imp;
+
+ public:
+ ELicenseKey(
+ const Environment * const,
+ const tr1::shared_ptr<const ERepositoryID> &,
+ 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));
+
+ IdleActionResult idle_load() const;
+
+ virtual std::string pretty_print(const LicenseSpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print_flat(const LicenseSpecTree::ItemFormatter &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EIUseKey :
+ public MetadataSetKey<IUseFlagSet>,
+ private PrivateImplementationPattern<EIUseKey>
+ {
+ private:
+ Implementation<EIUseKey> * const _imp;
+
+ public:
+ EIUseKey(
+ const Environment * const,
+ const tr1::shared_ptr<const ERepositoryID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~EIUseKey();
+
+ const tr1::shared_ptr<const IUseFlagSet> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ IdleActionResult idle_load() const;
+
+ virtual std::string pretty_print_flat(const Formatter<IUseFlag> &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print_flat_with_comparison(
+ const Environment * const,
+ const tr1::shared_ptr<const PackageID> &,
+ const Formatter<IUseFlag> &
+ ) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EKeywordsKey :
+ public MetadataSetKey<KeywordNameSet>,
+ private PrivateImplementationPattern<EKeywordsKey>
+ {
+ private:
+ Implementation<EKeywordsKey> * const _imp;
+
+ public:
+ EKeywordsKey(
+ const Environment * const,
+ const tr1::shared_ptr<const ERepositoryID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~EKeywordsKey();
+
+ const tr1::shared_ptr<const KeywordNameSet> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ IdleActionResult idle_load() const;
+
+ virtual std::string pretty_print_flat(const Formatter<KeywordName> &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EUseKey :
+ public MetadataSetKey<UseFlagNameSet>,
+ private PrivateImplementationPattern<EUseKey>
+ {
+ private:
+ Implementation<EUseKey> * const _imp;
+
+ public:
+ EUseKey(
+ const Environment * const,
+ const tr1::shared_ptr<const ERepositoryID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~EUseKey();
+
+ const tr1::shared_ptr<const UseFlagNameSet> value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print_flat(const Formatter<UseFlagName> &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EInheritedKey :
+ public MetadataSetKey<Set<std::string> >,
+ private PrivateImplementationPattern<EInheritedKey>
+ {
+ private:
+ Implementation<EInheritedKey> * const _imp;
+
+ public:
+ EInheritedKey(const tr1::shared_ptr<const ERepositoryID> &,
+ const std::string &, const std::string &, const std::string &, const MetadataKeyType);
+ ~EInheritedKey();
+
+ const tr1::shared_ptr<const Set<std::string> > value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string pretty_print_flat(const Formatter<std::string> &) 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 ERepositoryID> &,
+ 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 ERepositoryID> &,
+ const std::string &, const std::string &, const FSEntry &, const MetadataKeyType);
+ ~ECTimeKey();
+
+ const time_t value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class EFSLocationKey :
+ public MetadataFSEntryKey
+ {
+ private:
+ const FSEntry _value;
+
+ public:
+ EFSLocationKey(const tr1::shared_ptr<const ERepositoryID> &,
+ const std::string &, const std::string &, const FSEntry &, const MetadataKeyType);
+ ~EFSLocationKey();
+
+ const FSEntry value() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_mask.cc b/0.26.0_alpha1/paludis/repositories/e/e_mask.cc
new file mode 100644
index 000000000..8e843b0e3
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_mask.cc
@@ -0,0 +1,162 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_mask.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EUnacceptedMask>
+ {
+ const char key;
+ const std::string description;
+ const tr1::shared_ptr<const MetadataKey> unaccepted_key;
+
+ Implementation(const char k, const std::string & d, const tr1::shared_ptr<const MetadataKey> & u) :
+ key(k),
+ description(d),
+ unaccepted_key(u)
+ {
+ }
+ };
+}
+
+EUnacceptedMask::EUnacceptedMask(const char k, const std::string & d, const tr1::shared_ptr<const MetadataKey> & u) :
+ PrivateImplementationPattern<EUnacceptedMask>(new Implementation<EUnacceptedMask>(k, d, u))
+{
+}
+
+EUnacceptedMask::~EUnacceptedMask()
+{
+}
+
+const char
+EUnacceptedMask::key() const
+{
+ return _imp->key;
+}
+
+const std::string
+EUnacceptedMask::description() const
+{
+ return _imp->description;
+}
+
+const tr1::shared_ptr<const MetadataKey>
+EUnacceptedMask::unaccepted_key() const
+{
+ return _imp->unaccepted_key;
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<EUnsupportedMask>
+ {
+ const char key;
+ const std::string description;
+ const std::string eapi_name;
+
+ Implementation(const char k, const std::string & d, const std::string & n) :
+ key(k),
+ description(d),
+ eapi_name(n)
+ {
+ }
+ };
+}
+
+EUnsupportedMask::EUnsupportedMask(const char k, const std::string & d, const std::string & n) :
+ PrivateImplementationPattern<EUnsupportedMask>(new Implementation<EUnsupportedMask>(k, d, n))
+{
+}
+
+EUnsupportedMask::~EUnsupportedMask()
+{
+}
+
+const char
+EUnsupportedMask::key() const
+{
+ return _imp->key;
+}
+
+const std::string
+EUnsupportedMask::description() const
+{
+ return _imp->description;
+}
+
+const std::string
+EUnsupportedMask::explanation() const
+{
+ if (_imp->eapi_name == "UNKNOWN")
+ return "Unsupported EAPI 'UNKNOWN' (likely a broken package or configuration error)";
+ return "Unsupported EAPI '" + _imp->eapi_name + "'";
+}
+
+namespace paludis
+{
+ template <>
+ struct Implementation<ERepositoryMask>
+ {
+ const char key;
+ const std::string description;
+ const tr1::shared_ptr<const MetadataKey> mask_key;
+
+ Implementation(const char k, const std::string & d, const tr1::shared_ptr<const MetadataKey> & m) :
+ key(k),
+ description(d),
+ mask_key(m)
+ {
+ }
+ };
+}
+
+ERepositoryMask::ERepositoryMask(const char k, const std::string & d, const tr1::shared_ptr<const MetadataKey> & m) :
+ PrivateImplementationPattern<ERepositoryMask>(new Implementation<ERepositoryMask>(k, d, m))
+{
+}
+
+ERepositoryMask::~ERepositoryMask()
+{
+}
+
+const char
+ERepositoryMask::key() const
+{
+ return _imp->key;
+}
+
+const std::string
+ERepositoryMask::description() const
+{
+ return _imp->description;
+}
+
+const tr1::shared_ptr<const MetadataKey>
+ERepositoryMask::mask_key() const
+{
+ return _imp->mask_key;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_mask.hh b/0.26.0_alpha1/paludis/repositories/e/e_mask.hh
new file mode 100644
index 000000000..9991af109
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_mask.hh
@@ -0,0 +1,71 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_E_E_MASK_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_E_MASK_HH 1
+
+#include <paludis/mask.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ class EUnacceptedMask :
+ public UnacceptedMask,
+ private PrivateImplementationPattern<EUnacceptedMask>
+ {
+ public:
+ EUnacceptedMask(const char, const std::string &, const tr1::shared_ptr<const MetadataKey> &);
+ ~EUnacceptedMask();
+
+ const char key() const;
+ const std::string description() const;
+ const tr1::shared_ptr<const MetadataKey> unaccepted_key() const;
+ };
+
+ class EUnsupportedMask :
+ public UnsupportedMask,
+ private PrivateImplementationPattern<EUnsupportedMask>
+ {
+ public:
+ EUnsupportedMask(const char, const std::string &, const std::string &);
+ ~EUnsupportedMask();
+
+ virtual const char key() const;
+ virtual const std::string description() const;
+ virtual const std::string explanation() const;
+ };
+
+ class ERepositoryMask :
+ public RepositoryMask,
+ private PrivateImplementationPattern<ERepositoryMask>
+ {
+ public:
+ ERepositoryMask(const char, const std::string &, const tr1::shared_ptr<const MetadataKey> &);
+ ~ERepositoryMask();
+
+ const char key() const;
+ const std::string description() const;
+ const tr1::shared_ptr<const MetadataKey> mask_key() const;
+ };
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository.cc b/0.26.0_alpha1/paludis/repositories/e/e_repository.cc
new file mode 100644
index 000000000..648b2e2c0
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository.cc
@@ -0,0 +1,1258 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ * 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/aa_visitor.hh>
+#include <paludis/repositories/e/e_key.hh>
+#include <paludis/repositories/e/e_repository.hh>
+#include <paludis/repositories/e/e_repository_mask_file.hh>
+#include <paludis/repositories/e/e_repository_profile.hh>
+#include <paludis/repositories/e/e_repository_news.hh>
+#include <paludis/repositories/e/e_repository_sets.hh>
+#include <paludis/repositories/e/e_repository_exceptions.hh>
+#include <paludis/repositories/e/e_repository_entries.hh>
+#include <paludis/repositories/e/eapi.hh>
+#include <paludis/repositories/e/use_desc.hh>
+#include <paludis/repositories/e/layout.hh>
+
+#ifdef ENABLE_QA
+# include <paludis/repositories/e/qa/qa_controller.hh>
+#endif
+
+#include <paludis/repository_info.hh>
+#include <paludis/util/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/action.hh>
+#include <paludis/mask.hh>
+#include <paludis/qa.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/options.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/map.hh>
+#include <paludis/util/mutex.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/tr1_functional.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/is_file_with_extension.hh>
+
+#include <paludis/rmd160.hh>
+#include <paludis/sha256.hh>
+
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+
+#include <map>
+#include <set>
+#include <functional>
+#include <algorithm>
+#include <vector>
+#include <list>
+#include <fstream>
+
+#include <strings.h>
+#include <ctype.h>
+
+#include <dlfcn.h>
+#include <stdint.h>
+
+#define STUPID_CAST(type, val) reinterpret_cast<type>(reinterpret_cast<uintptr_t>(val))
+
+/** \file
+ * Implementation of ERepository.
+ *
+ * \ingroup grperepository
+ */
+
+using namespace paludis;
+
+typedef MakeHashedMap<QualifiedPackageName, std::list<std::pair<tr1::shared_ptr<const PackageDepSpec>, tr1::shared_ptr<const RepositoryMaskInfo> > > >::Type RepositoryMaskMap;
+typedef MakeHashedMultiMap<std::string, std::string>::Type MirrorMap;
+typedef MakeHashedMap<QualifiedPackageName, tr1::shared_ptr<const PackageDepSpec> >::Type VirtualsMap;
+typedef std::list<RepositoryEInterface::ProfilesDescLine> ProfilesDesc;
+
+namespace paludis
+{
+ /**
+ * Implementation data for a ERepository.
+ *
+ * \ingroup grperepository
+ */
+ template <>
+ struct Implementation<ERepository>
+ {
+ struct Mutexes
+ {
+ Mutex repo_mask_mutex;
+ Mutex arch_flags_mutex;
+ Mutex mirrors_mutex;
+ Mutex profiles_desc_mutex;
+ Mutex use_desc_mutex;
+ Mutex profile_ptr_mutex;
+ Mutex news_ptr_mutex;
+ };
+
+ ERepository * const repo;
+ const ERepositoryParams params;
+
+ const tr1::shared_ptr<Mutexes> mutexes;
+
+ tr1::shared_ptr<RepositoryNameCache> names_cache;
+
+ mutable RepositoryMaskMap repo_mask;
+ mutable bool has_repo_mask;
+
+ const std::map<QualifiedPackageName, QualifiedPackageName> provide_map;
+
+ mutable tr1::shared_ptr<UseFlagNameSet> 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<ERepositoryProfile> profile_ptr;
+
+ mutable tr1::shared_ptr<ERepositoryNews> news_ptr;
+
+ mutable tr1::shared_ptr<ERepositorySets> sets_ptr;
+ mutable tr1::shared_ptr<erepository::ERepositoryEntries> entries_ptr;
+ mutable tr1::shared_ptr<erepository::Layout> layout;
+
+ Implementation(ERepository * const, const ERepositoryParams &, tr1::shared_ptr<Mutexes> = make_shared_ptr(new Mutexes));
+ ~Implementation();
+
+ void need_profiles() const;
+ void need_profiles_desc() const;
+ };
+
+ Implementation<ERepository>::Implementation(ERepository * const r,
+ const ERepositoryParams & p, tr1::shared_ptr<Mutexes> m) :
+ repo(r),
+ params(p),
+ mutexes(m),
+ names_cache(new RepositoryNameCache(p.names_cache, r)),
+ has_repo_mask(false),
+ has_mirrors(false),
+ has_profiles_desc(false),
+ sets_ptr(new ERepositorySets(params.environment, r, p)),
+ entries_ptr(erepository::ERepositoryEntriesMaker::get_instance()->find_maker(
+ params.entry_format)(params.environment, r, p)),
+ layout(erepository::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<ERepository>::~Implementation()
+ {
+ }
+
+ void
+ Implementation<ERepository>::need_profiles() const
+ {
+ Lock l(mutexes->profile_ptr_mutex);
+
+ if (profile_ptr)
+ return;
+
+ profile_ptr.reset(new ERepositoryProfile(
+ params.environment, repo, repo->name(), *params.profiles,
+ erepository::EAPIData::get_instance()->eapi_from_string(
+ params.eapi_when_unknown)->supported->ebuild_environment_variables->env_arch));
+ }
+
+ void
+ Implementation<ERepository>::need_profiles_desc() const
+ {
+ if (has_profiles_desc)
+ return;
+
+ Lock l(mutexes->profiles_desc_mutex);
+
+ if (has_profiles_desc)
+ return;
+
+ Context context("When loading profiles.desc:");
+
+ bool found_one(false);
+ tr1::shared_ptr<const FSEntrySequence> profiles_desc_files(layout->profiles_desc_files());
+ for (FSEntrySequence::ConstIterator 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::ConstIterator line(f.begin()), line_end(f.end()) ; line != line_end ; ++line)
+ {
+ std::vector<std::string> tokens;
+ WhitespaceTokeniser::tokenise(*line,
+ std::back_inserter(tokens));
+ if (tokens.size() < 3)
+ continue;
+
+ FSEntrySequence profiles;
+ profiles.push_back(layout->profiles_base_dir() / tokens.at(1));
+ profiles_desc.push_back(RepositoryEInterface::ProfilesDescLine::create()
+ .arch(tokens.at(0))
+ .path(*profiles.begin())
+ .status(tokens.at(2))
+ .profile(tr1::shared_ptr<ERepositoryProfile>(new ERepositoryProfile(
+ params.environment, repo, repo->name(), profiles,
+ erepository::EAPIData::get_instance()->eapi_from_string(
+ params.eapi_when_unknown)->supported->ebuild_environment_variables->env_arch))));
+ }
+ }
+
+ if (! found_one)
+ throw ERepositoryConfigurationError("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);
+ }
+}
+
+ERepository::ERepository(const ERepositoryParams & p) :
+ Repository(fetch_repo_name(p.location),
+ RepositoryCapabilities::create()
+ .installed_interface(0)
+ .sets_interface(this)
+ .syncable_interface(this)
+ .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)
+ .destination_interface(p.enable_destinations ? this : 0)
+ .licenses_interface(this)
+ .make_virtuals_interface(0)
+ .e_interface(this)
+#ifdef ENABLE_QA
+ .qa_interface(this)
+#else
+ .qa_interface(0)
+#endif
+ .hook_interface(this)
+ .manifest_interface(this),
+ p.entry_format),
+ PrivateImplementationPattern<ERepository>(new Implementation<ERepository>(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("cache", stringify(_imp->params.cache));
+ config_info->add_kv("write_cache", stringify(_imp->params.write_cache));
+ config_info->add_kv("append_repository_name_to_write_cache", stringify(_imp->params.append_repository_name_to_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("eclassdirs", join(_imp->params.eclassdirs->begin(),
+ _imp->params.eclassdirs->end(), " "));
+ 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("sync", _imp->params.sync);
+ config_info->add_kv("sync_options", _imp->params.sync_options);
+ config_info->add_kv("builddir", stringify(_imp->params.builddir));
+ if (_imp->params.master_repository)
+ config_info->add_kv("master_repository", stringify(_imp->params.master_repository->name()));
+ config_info->add_kv("format", _imp->params.entry_format);
+ config_info->add_kv("layout", _imp->params.layout);
+ config_info->add_kv("eapi_when_unknown", _imp->params.eapi_when_unknown);
+ config_info->add_kv("eapi_when_unspecified", _imp->params.eapi_when_unspecified);
+ config_info->add_kv("profile_eapi", _imp->params.profile_eapi);
+
+ _info->add_section(config_info);
+}
+
+ERepository::~ERepository()
+{
+}
+
+bool
+ERepository::do_has_category_named(const CategoryNamePart & c) const
+{
+ return _imp->layout->has_category_named(c);
+}
+
+bool
+ERepository::do_has_package_named(const QualifiedPackageName & q) const
+{
+ return _imp->layout->has_package_named(q);
+}
+
+tr1::shared_ptr<const CategoryNamePartSet>
+ERepository::do_category_names() const
+{
+ return _imp->layout->category_names();
+}
+
+tr1::shared_ptr<const QualifiedPackageNameSet>
+ERepository::do_package_names(const CategoryNamePart & c) const
+{
+ return _imp->layout->package_names(c);
+}
+
+tr1::shared_ptr<const PackageIDSequence>
+ERepository::do_package_ids(const QualifiedPackageName & n) const
+{
+ return _imp->layout->package_ids(n);
+}
+
+tr1::shared_ptr<const RepositoryMaskInfo>
+ERepository::repository_masked(const PackageID & id) const
+{
+ Lock l(_imp->mutexes->repo_mask_mutex);
+
+ if (! _imp->has_repo_mask)
+ {
+ Context context("When querying repository mask for '" + stringify(id) + "':");
+
+ tr1::shared_ptr<const FSEntrySequence> repository_mask_files(_imp->layout->repository_mask_files());
+ for (FSEntrySequence::ConstIterator 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())
+ {
+ erepository::MaskFile ff(*p, LineConfigFileOptions());
+ for (erepository::MaskFile::ConstIterator line(ff.begin()), line_end(ff.end()) ;
+ line != line_end ; ++line)
+ {
+ try
+ {
+ tr1::shared_ptr<const PackageDepSpec> a(new PackageDepSpec(line->first, pds_pm_eapi_0));
+ if (a->package_ptr())
+ _imp->repo_mask[*a->package_ptr()].push_back(std::make_pair(a, line->second));
+ else
+ Log::get_instance()->message(ll_warning, lc_context, "Loading package mask spec '"
+ + stringify(line->first) + "' 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->first) + "' 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 tr1::shared_ptr<const RepositoryMaskInfo>();
+ else
+ for (std::list<std::pair<tr1::shared_ptr<const PackageDepSpec>, tr1::shared_ptr<const RepositoryMaskInfo> > >::const_iterator
+ k(r->second.begin()), k_end(r->second.end()) ; k != k_end ; ++k)
+ if (match_package(*_imp->params.environment, *k->first, id))
+ return k->second;
+
+ return tr1::shared_ptr<const RepositoryMaskInfo>();
+}
+
+UseFlagState
+ERepository::do_query_use(const UseFlagName & f, const PackageID & e) const
+{
+ _imp->need_profiles();
+ return _imp->profile_ptr->use_state_ignoring_masks(f, e);
+}
+
+bool
+ERepository::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
+ERepository::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 UseFlagNameSet>
+ERepository::do_arch_flags() const
+{
+ Lock l(_imp->mutexes->arch_flags_mutex);
+ if (! _imp->arch_flags)
+ {
+ Context context("When loading arch list:");
+ _imp->arch_flags.reset(new UseFlagNameSet);
+
+ bool found_one(false);
+ tr1::shared_ptr<const FSEntrySequence> arch_list_files(_imp->layout->arch_list_files());
+ for (FSEntrySequence::ConstIterator 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>
+ERepository::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
+ERepository::need_mirrors() const
+{
+ Lock l(_imp->mutexes->mirrors_mutex);
+
+ if (! _imp->has_mirrors)
+ {
+ bool found_one(false);
+ tr1::shared_ptr<const FSEntrySequence> mirror_files(_imp->layout->mirror_files());
+ for (FSEntrySequence::ConstIterator p(mirror_files->begin()), p_end(mirror_files->end()) ;
+ p != p_end ; ++p)
+ {
+ if (p->exists())
+ {
+ LineConfigFile mirrors(*p, LineConfigFileOptions());
+ for (LineConfigFile::ConstIterator line(mirrors.begin()) ; line != mirrors.end() ; ++line)
+ {
+ std::vector<std::string> ee;
+ WhitespaceTokeniser::tokenise(*line, std::back_inserter(ee));
+ if (! ee.empty())
+ {
+ /* pick up to five random mirrors only */
+ static Random r;
+ std::random_shuffle(next(ee.begin()), ee.end(), r);
+ if (ee.size() > 6)
+ ee.resize(6);
+ for (std::vector<std::string>::const_iterator e(next(ee.begin())),
+ e_end(ee.end()) ; e != e_end ; ++e)
+ _imp->mirrors.insert(std::make_pair(ee.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;
+ }
+}
+
+tr1::shared_ptr<SetSpecTree::ConstItem>
+ERepository::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 SetNameSet>
+ERepository::sets_list() const
+{
+ return _imp->sets_ptr->sets_list();
+}
+
+bool
+ERepository::do_sync() const
+{
+ Context context("When syncing repository '" + stringify(name()) + "':");
+
+ if (_imp->params.sync.empty())
+ return false;
+
+ std::list<std::string> sync_list;
+ WhitespaceTokeniser::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, _imp->layout->sync_filter_file());
+ 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
+ERepository::invalidate()
+{
+ _imp.reset(new Implementation<ERepository>(this, _imp->params, _imp->mutexes));
+}
+
+void
+ERepository::invalidate_masks()
+{
+ _imp->layout->invalidate_masks();
+
+ if (DistributionData::get_instance()->distribution_from_string(_imp->params.environment->default_distribution())->support_old_style_virtuals)
+ if (_imp->params.environment->package_database()->has_repository_named(RepositoryName("virtuals")))
+ _imp->params.environment->package_database()->fetch_repository(
+ RepositoryName("virtuals"))->invalidate_masks();
+}
+
+void
+ERepository::update_news() const
+{
+ Lock l(_imp->mutexes->news_ptr_mutex);
+
+ if (! _imp->news_ptr)
+ _imp->news_ptr.reset(new ERepositoryNews(_imp->params.environment, this, _imp->params));
+
+ _imp->news_ptr->update_news();
+}
+
+const tr1::shared_ptr<const erepository::Layout>
+ERepository::layout() const
+{
+ return _imp->layout;
+}
+
+const tr1::shared_ptr<const ERepositoryProfile>
+ERepository::profile() const
+{
+ _imp->need_profiles();
+ return _imp->profile_ptr;
+}
+
+const tr1::shared_ptr<const erepository::ERepositoryEntries>
+ERepository::entries() const
+{
+ return _imp->entries_ptr;
+}
+
+std::string
+ERepository::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(tr1::static_pointer_cast<const erepository::ERepositoryID>(for_package),
+ var, _imp->profile_ptr);
+}
+
+tr1::shared_ptr<const RepositoryInfo>
+ERepository::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::SectionConstIterator 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
+ERepository::profile_variable(const std::string & s) const
+{
+ _imp->need_profiles();
+
+ return _imp->profile_ptr->environment_variable(s);
+}
+
+ERepository::MirrorsConstIterator
+ERepository::begin_mirrors(const std::string & s) const
+{
+ need_mirrors();
+ return MirrorsConstIterator(_imp->mirrors.equal_range(s).first);
+}
+
+ERepository::MirrorsConstIterator
+ERepository::end_mirrors(const std::string & s) const
+{
+ need_mirrors();
+ return MirrorsConstIterator(_imp->mirrors.equal_range(s).second);
+}
+
+tr1::shared_ptr<const ERepository::VirtualsSequence>
+ERepository::virtual_packages() const
+{
+ Context context("When loading virtual packages for repository '" +
+ stringify(name()) + "'");
+
+ _imp->need_profiles();
+
+ tr1::shared_ptr<VirtualsSequence> result(new VirtualsSequence);
+
+ for (ERepositoryProfile::VirtualsConstIterator 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 UseFlagNameSet>
+ERepository::do_use_expand_flags() const
+{
+ _imp->need_profiles();
+
+ std::string expand_sep(stringify(erepository::EAPIData::get_instance()->eapi_from_string(_imp->params.profile_eapi
+ )->supported->ebuild_options->use_expand_separator));
+ tr1::shared_ptr<UseFlagNameSet> result(new UseFlagNameSet);
+ for (ERepositoryProfile::UseExpandConstIterator 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::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) + expand_sep + *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 UseFlagNameSet>
+ERepository::do_use_expand_prefixes() const
+{
+ _imp->need_profiles();
+
+ tr1::shared_ptr<UseFlagNameSet> result(new UseFlagNameSet);
+ for (ERepositoryProfile::UseExpandConstIterator 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 UseFlagNameSet>
+ERepository::do_use_expand_hidden_prefixes() const
+{
+ _imp->need_profiles();
+
+ tr1::shared_ptr<UseFlagNameSet> result(new UseFlagNameSet);
+ for (ERepositoryProfile::UseExpandConstIterator 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->data().end(), std::back_inserter(lower_i), &::tolower);
+ result->insert(UseFlagName(lower_i));
+ }
+
+ return result;
+}
+
+void
+ERepository::regenerate_cache() const
+{
+ _imp->names_cache->regenerate_cache();
+}
+
+tr1::shared_ptr<const CategoryNamePartSet>
+ERepository::do_category_names_containing_package(const PackageNamePart & p) const
+{
+ if (! _imp->names_cache->usable())
+ return Repository::do_category_names_containing_package(p);
+
+ tr1::shared_ptr<const CategoryNamePartSet> result(
+ _imp->names_cache->category_names_containing_package(p));
+
+ return result ? result : Repository::do_category_names_containing_package(p);
+}
+
+ERepository::ProfilesConstIterator
+ERepository::begin_profiles() const
+{
+ _imp->need_profiles_desc();
+ return ProfilesConstIterator(_imp->profiles_desc.begin());
+}
+
+ERepository::ProfilesConstIterator
+ERepository::end_profiles() const
+{
+ _imp->need_profiles_desc();
+ return ProfilesConstIterator(_imp->profiles_desc.end());
+}
+
+ERepository::ProfilesConstIterator
+ERepository::find_profile(const FSEntry & location) const
+{
+ _imp->need_profiles_desc();
+ for (ProfilesDesc::const_iterator i(_imp->profiles_desc.begin()),
+ i_end(_imp->profiles_desc.end()) ; i != i_end ; ++i)
+ if (i->path == location)
+ return ProfilesConstIterator(i);
+ return ProfilesConstIterator(_imp->profiles_desc.end());
+}
+
+void
+ERepository::set_profile(const ProfilesConstIterator & iter)
+{
+ Context context("When setting profile by iterator:");
+
+ _imp->profile_ptr = iter->profile;
+
+ if (DistributionData::get_instance()->distribution_from_string(_imp->params.environment->default_distribution())->support_old_style_virtuals)
+ if (_imp->params.environment->package_database()->has_repository_named(RepositoryName("virtuals")))
+ _imp->params.environment->package_database()->fetch_repository(
+ RepositoryName("virtuals"))->invalidate();
+
+ invalidate_masks();
+}
+
+void
+ERepository::set_profile_by_arch(const UseFlagName & arch)
+{
+ Context context("When setting profile by arch '" + stringify(arch) + "':");
+
+ for (ProfilesConstIterator p(begin_profiles()), p_end(end_profiles()) ; p != p_end ; ++p)
+ if (p->arch == stringify(arch) && p->status == "stable")
+ {
+ set_profile(p);
+ return;
+ }
+
+ for (ProfilesConstIterator p(begin_profiles()), p_end(end_profiles()) ; p != p_end ; ++p)
+ if (p->arch == stringify(arch))
+ {
+ set_profile(p);
+ return;
+ }
+
+ throw ConfigurationError("Cannot find a profile appropriate for '" + stringify(arch) + "'");
+}
+
+std::string
+ERepository::do_describe_use_flag(const UseFlagName & f,
+ const PackageID & e) const
+{
+ Lock l(_imp->mutexes->use_desc_mutex);
+
+ if (_imp->use_desc.empty())
+ {
+ std::string expand_sep(stringify(erepository::EAPIData::get_instance()->eapi_from_string(
+ _imp->params.profile_eapi)->supported->ebuild_options->use_expand_separator));
+ tr1::shared_ptr<const FSEntrySequence> use_desc_dirs(_imp->layout->use_desc_dirs());
+ for (FSEntrySequence::ConstIterator p(use_desc_dirs->begin()), p_end(use_desc_dirs->end()) ;
+ p != p_end ; ++p)
+ _imp->use_desc.push_back(tr1::shared_ptr<UseDesc>(new UseDesc(*p, expand_sep)));
+ }
+
+ std::string result;
+ for (std::list<tr1::shared_ptr<UseDesc> >::const_iterator i(_imp->use_desc.begin()),
+ i_end(_imp->use_desc.end()) ; i != i_end ; ++i)
+ {
+ std::string new_result((*i)->describe(f, e));
+ if (! new_result.empty())
+ result = new_result;
+ }
+ return result;
+}
+
+const ERepositoryParams &
+ERepository::params() const
+{
+ return _imp->params;
+}
+
+bool
+ERepository::is_suitable_destination_for(const PackageID & e) const
+{
+ std::string f(e.repository()->format());
+ return f == "ebuild" || f == "ebin";
+}
+
+bool
+ERepository::is_default_destination() const
+{
+ return false;
+}
+
+bool
+ERepository::want_pre_post_phases() const
+{
+ return false;
+}
+
+void
+ERepository::merge(const MergeOptions & o)
+{
+ _imp->entries_ptr->merge(o);
+}
+
+HookResult
+ERepository::perform_hook(const Hook & hook) const
+{
+ Context context("When performing hook '" + stringify(hook.name()) + "' for repository '"
+ + stringify(name()) + "':");
+
+ if (hook.name() == "sync_all_post"
+ || hook.name() == "install_all_post"
+ || hook.name() == "uninstall_all_post")
+ update_news();
+
+ return HookResult(0, "");
+}
+
+tr1::shared_ptr<const CategoryNamePartSet>
+ERepository::unimportant_category_names() const
+{
+ tr1::shared_ptr<CategoryNamePartSet> result(make_shared_ptr(new CategoryNamePartSet));
+ result->insert(CategoryNamePart("virtual"));
+ return result;
+}
+
+#ifdef ENABLE_QA
+namespace
+{
+ struct LibQAHandle
+ {
+ Mutex mutex;
+ void * handle;
+ void (* qa_checks_handle)(
+ const Environment * const,
+ const tr1::shared_ptr<const ERepository> &,
+ const QACheckProperties & ignore_if,
+ const QACheckProperties & ignore_unless,
+ const QAMessageLevel minimum_level,
+ QAReporter & reporter,
+ const FSEntry & dir);
+
+ LibQAHandle() :
+ handle(0),
+ qa_checks_handle(0)
+ {
+ }
+
+ ~LibQAHandle()
+ {
+ if (0 != handle)
+ dlclose(handle);
+ }
+
+ } libqahandle;
+}
+#endif
+
+void
+ERepository::check_qa(
+ QAReporter & reporter,
+ const QACheckProperties & ignore_if,
+ const QACheckProperties & ignore_unless,
+ const QAMessageLevel minimum_level,
+ const FSEntry & dir
+ ) const
+{
+#ifdef ENABLE_QA
+ Context c("When performing QA checks for '" + stringify(dir) + "':");
+
+ {
+ Lock lock(libqahandle.mutex);
+
+ if (0 == libqahandle.handle)
+ libqahandle.handle = dlopen(getenv_with_default("PALUDIS_E_REPOSITORY_QA_SO",
+ "libpaludiserepositoryqa.so").c_str(), RTLD_NOW | RTLD_GLOBAL);
+ if (0 == libqahandle.handle)
+ {
+ reporter.message(QAMessage(dir, qaml_severe, "check_qa", "Got error '" + stringify(dlerror()) +
+ "' when dlopen(" + getenv_with_default("PALUDIS_E_REPOSITORY_QA_SO",
+ "libpaludiserepositoryqa.so") + ")"));
+ return;
+ }
+
+ if (0 == libqahandle.qa_checks_handle)
+ libqahandle.qa_checks_handle = STUPID_CAST(void (*)(
+ const Environment * const,
+ const tr1::shared_ptr<const ERepository> &,
+ const QACheckProperties &,
+ const QACheckProperties &,
+ const QAMessageLevel,
+ QAReporter &,
+ const FSEntry &),
+ dlsym(libqahandle.handle, "check_qa"));
+ if (0 == libqahandle.qa_checks_handle)
+ {
+ reporter.message(QAMessage(dir, qaml_severe, "check_qa", "Got error '" + stringify(dlerror) +
+ "' when dlsym(libpaludisqa.so, \"check_qa\")"));
+ return;
+ }
+ }
+
+ (*libqahandle.qa_checks_handle)(_imp->params.environment, shared_from_this(), ignore_if, ignore_unless,
+ minimum_level, reporter, dir);
+#endif
+}
+
+namespace
+{
+ struct SupportsActionQuery :
+ ConstVisitor<SupportsActionTestVisitorTypes>
+ {
+ bool result;
+
+ SupportsActionQuery() :
+ result(false)
+ {
+ }
+
+ void visit(const SupportsActionTest<InstalledAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<InstallAction> &)
+ {
+ result = true;
+ }
+
+ void visit(const SupportsActionTest<ConfigAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<PretendAction> &)
+ {
+ result = true;
+ }
+
+ void visit(const SupportsActionTest<FetchAction> &)
+ {
+ result = true;
+ }
+
+ void visit(const SupportsActionTest<UninstallAction> &)
+ {
+ }
+
+ void visit(const SupportsActionTest<InfoAction> &)
+ {
+ result = true;
+ }
+ };
+}
+
+bool
+ERepository::do_some_ids_might_support_action(const SupportsActionTestBase & a) const
+{
+ SupportsActionQuery q;
+ a.accept(q);
+ return q.result;
+}
+
+void
+ERepository::make_manifest(const QualifiedPackageName & qpn)
+{
+ FSEntry package_dir = _imp->layout->package_directory(qpn);
+
+ FSEntry(package_dir / "Manifest").unlink();
+ std::ofstream manifest(stringify(FSEntry(package_dir
+ / "Manifest")).c_str());
+ if (! manifest)
+ throw ERepositoryConfigurationError("Couldn't open Manifest for writing.");
+
+ tr1::shared_ptr<Map<FSEntry, std::string> > files = _imp->layout->manifest_files(qpn);
+
+ for (Map<FSEntry, std::string>::ConstIterator f(files->begin()) ;
+ f != files->end() ; ++f)
+ {
+ FSEntry file(f->first);
+ std::string filename = file.basename();
+ std::string file_type(f->second);
+
+ if ("AUX" == file_type)
+ {
+ filename = stringify(file).substr(stringify(package_dir / "files").length()+1);
+ }
+
+ std::ifstream file_stream(stringify(file).c_str());
+ if (! file_stream)
+ throw ERepositoryConfigurationError("Couldn't read "
+ + stringify(file));
+
+ RMD160 rmd160sum(file_stream);
+ manifest << file_type << " " << filename << " "
+ << file.file_size() << " RMD160 " << rmd160sum.hexsum();
+
+ file_stream.clear();
+ file_stream.seekg(0, std::ios::beg);
+ SHA256 sha256sum(file_stream);
+ manifest << " SHA256 " << sha256sum.hexsum() << std::endl;
+ }
+
+ tr1::shared_ptr<const PackageIDSequence> versions;
+ versions = package_ids(qpn);
+
+ std::set<std::string> done_files;
+
+ for (PackageIDSequence::ConstIterator v(versions->begin()),
+ v_end(versions->end()) ;
+ v != v_end ; ++v)
+ {
+ tr1::shared_ptr<const PackageID> id = (*v);
+ if (! id->fetches_key())
+ continue;
+ paludis::erepository::AAVisitor aa;
+ id->fetches_key()->value()->accept(aa);
+
+ for (paludis::erepository::AAVisitor::ConstIterator d(aa.begin()) ;
+ d != aa.end() ; ++d)
+ {
+ if (done_files.count(*d))
+ continue;
+ done_files.insert(*d);
+
+ FSEntry f(params().distdir / *d);
+
+ std::ifstream file_stream(stringify(f).c_str());
+ if (! file_stream)
+ throw ERepositoryConfigurationError("Couldn't read "
+ + stringify(f));
+
+ RMD160 rmd160sum(file_stream);
+ manifest << "DIST " << f.basename() << " "
+ << f.file_size()
+ << " RMD160 " << rmd160sum.hexsum();
+
+ file_stream.clear();
+ file_stream.seekg(0, std::ios::beg);
+ SHA256 sha256sum(file_stream);
+ manifest << " SHA256 " << sha256sum.hexsum()
+ << std::endl;
+ }
+ }
+}
+
+std::string
+ERepository::accept_keywords_variable() const
+{
+ return erepository::EAPIData::get_instance()->eapi_from_string(
+ params().profile_eapi)->supported->ebuild_environment_variables->env_accept_keywords;
+}
+
+std::string
+ERepository::arch_variable() const
+{
+ return erepository::EAPIData::get_instance()->eapi_from_string(
+ params().profile_eapi)->supported->ebuild_environment_variables->env_arch;
+}
+
+FSEntry
+ERepository::info_variables_file(const FSEntry & f) const
+{
+ return layout()->info_variables_file(f);
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository.hh b/0.26.0_alpha1/paludis/repositories/e/e_repository.hh
new file mode 100644
index 000000000..d265c88b1
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository.hh
@@ -0,0 +1,245 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_E_REPOSITORY_HH
+#define PALUDIS_GUARD_PALUDIS_E_REPOSITORY_HH 1
+
+#include <paludis/repository.hh>
+#include <paludis/package_database.hh>
+#include <paludis/mask-fwd.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/tr1_memory.hh>
+#include <paludis/repositories/e/e_repository_params.hh>
+#include <paludis/repositories/e/e_repository_profile.hh>
+#include <paludis/repositories/e/layout.hh>
+#include <string>
+
+/** \file
+ * Declaration for the ERepository class.
+ *
+ * \ingroup grperepository
+ */
+
+namespace paludis
+{
+ class ERepositoryProfile;
+ class ERepositoryNews;
+
+ /**
+ * A ERepository is a Repository that handles the layout used by
+ * Portage for the main Gentoo tree.
+ *
+ * \ingroup grperepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE ERepository :
+ public Repository,
+ public RepositoryUseInterface,
+ public RepositorySyncableInterface,
+ public RepositorySetsInterface,
+ public RepositoryEnvironmentVariableInterface,
+ public RepositoryMirrorsInterface,
+ public RepositoryVirtualsInterface,
+ public RepositoryDestinationInterface,
+ public RepositoryLicensesInterface,
+ public RepositoryEInterface,
+ public RepositoryHookInterface,
+ public RepositoryQAInterface,
+ public RepositoryManifestInterface,
+ public tr1::enable_shared_from_this<ERepository>,
+ private PrivateImplementationPattern<ERepository>
+ {
+ private:
+ void need_mirrors() const;
+
+ protected:
+ /* RepositoryLicensesInterface */
+
+ virtual tr1::shared_ptr<FSEntry> do_license_exists(
+ const std::string & license) const;
+
+ /* RepositorySetsInterface */
+
+ virtual tr1::shared_ptr<SetSpecTree::ConstItem> do_package_set(const SetName & id) const;
+
+ virtual tr1::shared_ptr<const SetNameSet> sets_list() const;
+
+ /* RepositorySyncableInterface */
+
+ virtual bool do_sync() const;
+
+ /* RepositoryUseInterface */
+
+ virtual UseFlagState do_query_use(const UseFlagName &, const PackageID &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool do_query_use_mask(const UseFlagName &, const PackageID &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool do_query_use_force(const UseFlagName &, const PackageID &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const UseFlagNameSet> do_arch_flags() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const UseFlagNameSet> do_use_expand_flags() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const UseFlagNameSet> do_use_expand_hidden_prefixes() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const UseFlagNameSet> do_use_expand_prefixes() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual std::string do_describe_use_flag(const UseFlagName &,
+ const PackageID &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /* RepositoryEnvironmentVariableInterface */
+
+ virtual std::string get_environment_variable(
+ const tr1::shared_ptr<const PackageID> & for_package,
+ const std::string & var) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /* Repository */
+
+ virtual tr1::shared_ptr<const PackageIDSequence> do_package_ids(
+ const QualifiedPackageName &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const QualifiedPackageNameSet> do_package_names(
+ const CategoryNamePart &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const CategoryNamePartSet> do_category_names() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const CategoryNamePartSet> do_category_names_containing_package(
+ const PackageNamePart &) const;
+
+ virtual bool do_has_package_named(const QualifiedPackageName &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool do_has_category_named(const CategoryNamePart &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool do_some_ids_might_support_action(const SupportsActionTestBase &) const;
+
+ public:
+ virtual tr1::shared_ptr<const RepositoryInfo> info(bool verbose) const;
+
+ /**
+ * Constructor.
+ */
+ ERepository(const ERepositoryParams &);
+
+ /**
+ * Destructor.
+ */
+ ~ERepository();
+
+ virtual void invalidate();
+
+ virtual void invalidate_masks();
+
+ /* RepositoryMirrorsInterface */
+
+ virtual MirrorsConstIterator begin_mirrors(const std::string & s) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual MirrorsConstIterator end_mirrors(const std::string & s) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /* RepositoryVirtualsInterface */
+
+ virtual tr1::shared_ptr<const VirtualsSequence> virtual_packages() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /* RepositoryDestinationInterface */
+
+ virtual bool is_suitable_destination_for(const PackageID &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool is_default_destination() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual bool want_pre_post_phases() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual void merge(const MergeOptions &);
+
+ virtual void check_qa(
+ QAReporter &,
+ const QACheckProperties &,
+ const QACheckProperties &,
+ const QAMessageLevel,
+ const FSEntry &
+ ) const;
+
+ /* RepositoryManifestInterface */
+ virtual void make_manifest(const QualifiedPackageName & qpn);
+
+ ///\name Information about ERepository
+ ///\{
+
+ std::string profile_variable(const std::string &) const;
+ virtual std::string accept_keywords_variable() const;
+ virtual std::string arch_variable() const;
+
+ const ERepositoryParams & params() const;
+
+ virtual FSEntry info_variables_file(const FSEntry &) const;
+
+ ///\}
+
+ ///\name Profile setting and querying functions
+ ///\{
+
+ ProfilesConstIterator begin_profiles() const;
+ ProfilesConstIterator end_profiles() const;
+
+ ProfilesConstIterator find_profile(const FSEntry & location) const;
+ void set_profile(const ProfilesConstIterator & iter);
+ void set_profile_by_arch(const UseFlagName &);
+
+ ///\}
+
+ HookResult perform_hook(const Hook &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ virtual tr1::shared_ptr<const CategoryNamePartSet> unimportant_category_names() const;
+
+ /**
+ * Update GLEP 42 news files.
+ */
+ void update_news() const;
+
+ const tr1::shared_ptr<const erepository::Layout> layout() const;
+ const tr1::shared_ptr<const erepository::ERepositoryEntries> entries() const;
+ const tr1::shared_ptr<const ERepositoryProfile> profile() const;
+
+ tr1::shared_ptr<const RepositoryMaskInfo> repository_masked(const PackageID &) const;
+
+ void regenerate_cache() const;
+ };
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository_TEST.cc b/0.26.0_alpha1/paludis/repositories/e/e_repository_TEST.cc
new file mode 100644
index 000000000..be8b30f42
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository_TEST.cc
@@ -0,0 +1,1219 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_repository.hh>
+#include <paludis/repositories/e/e_repository_id.hh>
+#include <paludis/repositories/e/make_ebuild_repository.hh>
+#include <paludis/repositories/e/eapi.hh>
+#include <paludis/repositories/e/dep_spec_pretty_printer.hh>
+#include <paludis/repositories/fake/fake_installed_repository.hh>
+#include <paludis/environments/test/test_environment.hh>
+#include <paludis/util/system.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/visitor_cast.hh>
+#include <paludis/util/tr1_functional.hh>
+#include <paludis/util/map.hh>
+#include <paludis/util/set.hh>
+#include <paludis/package_id.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/query.hh>
+#include <paludis/action.hh>
+#include <paludis/stringify_formatter.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+#include <libwrapiter/libwrapiter_output_iterator.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+#include <set>
+#include <fstream>
+#include <string>
+
+using namespace test;
+using namespace paludis;
+
+/** \file
+ * Test cases for ERepository.
+ *
+ */
+
+namespace test_cases
+{
+ /**
+ * \test Test ERepository repository names.
+ *
+ */
+ struct ERepositoryRepoNameTest : TestCase
+ {
+ ERepositoryRepoNameTest() : TestCase("repo name") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo1");
+ keys->insert("profiles", "e_repository_TEST_dir/repo1/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(
+ &env, keys));
+ TEST_CHECK_STRINGIFY_EQUAL(repo->name(), "test-repo-1");
+ }
+ } test_e_repository_repo_name;
+
+ /**
+ * \test Test ERepository repository with no names.
+ *
+ */
+ struct ERepositoryNoRepoNameTest : TestCase
+ {
+ ERepositoryNoRepoNameTest() : TestCase("no repo name") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo2");
+ keys->insert("profiles", "e_repository_TEST_dir/repo2/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(
+ &env, keys));
+ TEST_CHECK_STRINGIFY_EQUAL(repo->name(), "x-repo2");
+ }
+ } test_e_repository_no_repo_name;
+
+ /**
+ * \test Test ERepository repository empty names.
+ *
+ */
+ struct ERepositoryEmptyRepoNameTest : TestCase
+ {
+ ERepositoryEmptyRepoNameTest() : TestCase("empty repo name") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo3");
+ keys->insert("profiles", "e_repository_TEST_dir/repo3/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(
+ &env, keys));
+ TEST_CHECK_STRINGIFY_EQUAL(repo->name(), "x-repo3");
+ }
+ } test_e_repository_empty_repo_name;
+
+ /**
+ * \test Test ERepository repository has_category_named.
+ *
+ */
+ struct ERepositoryHasCategoryNamedTest : TestCase
+ {
+ ERepositoryHasCategoryNamedTest() : TestCase("has category named") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo1");
+ keys->insert("profiles", "e_repository_TEST_dir/repo1/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ TEST_CHECK(repo->has_category_named(CategoryNamePart("cat-one")));
+ TEST_CHECK(repo->has_category_named(CategoryNamePart("cat-two")));
+ TEST_CHECK(repo->has_category_named(CategoryNamePart("cat-three")));
+ TEST_CHECK(! repo->has_category_named(CategoryNamePart("cat-four")));
+ }
+ }
+ } test_e_repository_has_category_named;
+
+ /**
+ * \test Test ERepository category_names.
+ *
+ */
+ struct ERepositoryCategoryNamesTest : TestCase
+ {
+ ERepositoryCategoryNamesTest() : TestCase("category names") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo1");
+ keys->insert("profiles", "e_repository_TEST_dir/repo1/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ tr1::shared_ptr<const CategoryNamePartSet> c(repo->category_names());
+ TEST_CHECK(c->end() != c->find(CategoryNamePart("cat-one")));
+ TEST_CHECK(c->end() != c->find(CategoryNamePart("cat-two")));
+ TEST_CHECK(c->end() != c->find(CategoryNamePart("cat-three")));
+ TEST_CHECK(c->end() == c->find(CategoryNamePart("cat-four")));
+ TEST_CHECK_EQUAL(3, std::distance(c->begin(), c->end()));
+ }
+ }
+ } test_e_repository_category_names;
+
+ /**
+ * \test Test ERepository has_package_named.
+ *
+ */
+ struct ERepositoryHasPackageNamedTest : TestCase
+ {
+ ERepositoryHasPackageNamedTest() : TestCase("has package named") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo4");
+ keys->insert("profiles", "e_repository_TEST_dir/repo4/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-one/pkg-one")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-two/pkg-two")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-one/pkg-two")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-two/pkg-one")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-one/pkg-both")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-two/pkg-both")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-one/pkg-neither")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-two/pkg-neither")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-one")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-two")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-both")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-neither")));
+ }
+ }
+ } test_e_repository_has_package_named;
+
+ /**
+ * \test Test ERepository has_package_named cached.
+ *
+ */
+ struct ERepositoryHasPackageNamedCachedTest : TestCase
+ {
+ ERepositoryHasPackageNamedCachedTest() : TestCase("has package named cached") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo4");
+ keys->insert("profiles", "e_repository_TEST_dir/repo4/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ repo->package_names(CategoryNamePart("cat-one"));
+ repo->package_names(CategoryNamePart("cat-two"));
+ repo->package_names(CategoryNamePart("cat-three"));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-one/pkg-one")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-two/pkg-two")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-one/pkg-two")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-two/pkg-one")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-one/pkg-both")));
+ TEST_CHECK(repo->has_package_named(QualifiedPackageName("cat-two/pkg-both")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-one/pkg-neither")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-two/pkg-neither")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-one")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-two")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-both")));
+ TEST_CHECK(! repo->has_package_named(QualifiedPackageName("cat-three/pkg-neither")));
+ }
+ }
+ } test_e_repository_has_package_named_cached;
+
+ /**
+ * \test Test ERepository package_names.
+ *
+ */
+ struct ERepositoryPackageNamesTest : TestCase
+ {
+ ERepositoryPackageNamesTest() : TestCase("package names") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo4");
+ keys->insert("profiles", "e_repository_TEST_dir/repo4/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ tr1::shared_ptr<const QualifiedPackageNameSet> names;
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ names = repo->package_names(CategoryNamePart("cat-one"));
+ TEST_CHECK(! names->empty());
+ TEST_CHECK(names->end() != names->find(QualifiedPackageName("cat-one/pkg-one")));
+ TEST_CHECK(names->end() != names->find(QualifiedPackageName("cat-one/pkg-both")));
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-one/pkg-two")));
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-one/pkg-neither")));
+ TEST_CHECK_EQUAL(2, std::distance(names->begin(), names->end()));
+
+ names = repo->package_names(CategoryNamePart("cat-two"));
+ TEST_CHECK(! names->empty());
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-two/pkg-one")));
+ TEST_CHECK(names->end() != names->find(QualifiedPackageName("cat-two/pkg-both")));
+ TEST_CHECK(names->end() != names->find(QualifiedPackageName("cat-two/pkg-two")));
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-two/pkg-neither")));
+ TEST_CHECK_EQUAL(2, std::distance(names->begin(), names->end()));
+
+ names = repo->package_names(CategoryNamePart("cat-three"));
+ TEST_CHECK(names->empty());
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-three/pkg-one")));
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-three/pkg-both")));
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-three/pkg-two")));
+ TEST_CHECK(names->end() == names->find(QualifiedPackageName("cat-three/pkg-neither")));
+ TEST_CHECK_EQUAL(0, std::distance(names->begin(), names->end()));
+ }
+ }
+ } test_e_repository_package_names;
+
+ /**
+ * \test Test ERepository bad package names.
+ *
+ */
+ struct ERepositoryBadPackageNamesTest : TestCase
+ {
+ ERepositoryBadPackageNamesTest() : TestCase("bad package names") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo5");
+ keys->insert("profiles", "e_repository_TEST_dir/repo5/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ tr1::shared_ptr<const QualifiedPackageNameSet> names;
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ names = repo->package_names(CategoryNamePart("cat-one"));
+ TEST_CHECK(! names->empty());
+ TEST_CHECK(names->end() != names->find(QualifiedPackageName("cat-one/pkg-one")));
+ TEST_CHECK_EQUAL(1, std::distance(names->begin(), names->end()));
+ }
+ }
+ } test_e_repository_bad_package_names;
+
+ struct ERepositoryPackageIDTest : TestCase
+ {
+ ERepositoryPackageIDTest() : TestCase("package_ids") { }
+
+ void run()
+ {
+ using namespace tr1::placeholders;
+
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo4");
+ keys->insert("profiles", "e_repository_TEST_dir/repo4/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ tr1::shared_ptr<const PackageIDSequence> versions;
+
+ versions = repo->package_ids(QualifiedPackageName("cat-one/pkg-one"));
+ TEST_CHECK(! versions->empty());
+ TEST_CHECK_EQUAL(2, std::distance(versions->begin(), versions->end()));
+ TEST_CHECK(indirect_iterator(versions->end()) != std::find_if(
+ indirect_iterator(versions->begin()), indirect_iterator(versions->end()),
+ tr1::bind(std::equal_to<VersionSpec>(), tr1::bind(tr1::mem_fn(&PackageID::version), _1), VersionSpec("1"))));
+ TEST_CHECK(indirect_iterator(versions->end()) != std::find_if(
+ indirect_iterator(versions->begin()), indirect_iterator(versions->end()),
+ tr1::bind(std::equal_to<VersionSpec>(), tr1::bind(tr1::mem_fn(&PackageID::version), _1), VersionSpec("1.1-r1"))));
+ TEST_CHECK(indirect_iterator(versions->end()) == std::find_if(
+ indirect_iterator(versions->begin()), indirect_iterator(versions->end()),
+ tr1::bind(std::equal_to<VersionSpec>(), tr1::bind(tr1::mem_fn(&PackageID::version), _1), VersionSpec("2"))));
+
+ versions = repo->package_ids(QualifiedPackageName("cat-one/pkg-neither"));
+ TEST_CHECK(versions->empty());
+ TEST_CHECK_EQUAL(0, std::distance(versions->begin(), versions->end()));
+ }
+ }
+ } test_e_repository_versions;
+
+ /**
+ * \test Test ERepository duff versions.
+ *
+ */
+ struct ERepositoryDuffVersionsTest : TestCase
+ {
+ ERepositoryDuffVersionsTest() : TestCase("duff versions") { }
+
+ void run()
+ {
+ using namespace tr1::placeholders;
+
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo8");
+ keys->insert("profiles", "e_repository_TEST_dir/repo8/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(
+ &env, keys));
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ tr1::shared_ptr<const PackageIDSequence> versions;
+
+ versions = repo->package_ids(QualifiedPackageName("cat-one/pkg-one"));
+ TEST_CHECK(! versions->empty());
+ TEST_CHECK_EQUAL(2, std::distance(versions->begin(), versions->end()));
+ TEST_CHECK(indirect_iterator(versions->end()) != std::find_if(
+ indirect_iterator(versions->begin()), indirect_iterator(versions->end()),
+ tr1::bind(std::equal_to<VersionSpec>(), tr1::bind(tr1::mem_fn(&PackageID::version), _1), VersionSpec("1"))));
+ TEST_CHECK(indirect_iterator(versions->end()) != std::find_if(
+ indirect_iterator(versions->begin()), indirect_iterator(versions->end()),
+ tr1::bind(std::equal_to<VersionSpec>(), tr1::bind(tr1::mem_fn(&PackageID::version), _1), VersionSpec("1.1-r1"))));
+ TEST_CHECK(indirect_iterator(versions->end()) == std::find_if(
+ indirect_iterator(versions->begin()), indirect_iterator(versions->end()),
+ tr1::bind(std::equal_to<VersionSpec>(), tr1::bind(tr1::mem_fn(&PackageID::version), _1), VersionSpec("2"))));
+
+ versions = repo->package_ids(QualifiedPackageName("cat-one/pkg-neither"));
+ TEST_CHECK(versions->empty());
+ TEST_CHECK_EQUAL(0, std::distance(versions->begin(), versions->end()));
+ }
+ }
+ } test_e_repository_duff_versions;
+
+ /**
+ * \test Test ERepository cached metadata.
+ *
+ */
+ struct ERepositoryMetadataCachedTest : TestCase
+ {
+ ERepositoryMetadataCachedTest() : TestCase("metadata cached") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo6");
+ keys->insert("profiles", "e_repository_TEST_dir/repo6/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+ tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("=cat-one/pkg-one-1", pds_pm_unspecific)), qo_require_exactly_one)->begin());
+
+ TEST_CHECK(id->short_description_key());
+ TEST_CHECK_EQUAL(id->short_description_key()->value(), "the-description");
+ }
+ }
+ } test_e_repository_metadata_cached;
+
+ /**
+ * \test Test ERepository uncached metadata.
+ *
+ */
+ struct ERepositoryMetadataUncachedTest : TestCase
+ {
+ ERepositoryMetadataUncachedTest() : TestCase("metadata uncached") { }
+
+ unsigned max_run_time() const
+ {
+ return 300;
+ }
+
+ void run()
+ {
+ for (int opass = 1 ; opass <= 3 ; ++opass)
+ {
+ TestMessageSuffix opass_suffix("opass=" + stringify(opass), true);
+
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("write_cache", "e_repository_TEST_dir/repo7/metadata/cache");
+ keys->insert("location", "e_repository_TEST_dir/repo7");
+ keys->insert("profiles", "e_repository_TEST_dir/repo7/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ for (int pass = 1 ; pass <= 3 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix("pass=" + stringify(pass), true);
+
+ tr1::shared_ptr<const PackageID> id1(*env.package_database()->query(query::Matches(
+ PackageDepSpec("=cat-one/pkg-one-1", pds_pm_unspecific)), qo_require_exactly_one)->begin());
+
+ TEST_CHECK(id1->end_metadata() != id1->find_metadata("EAPI"));
+ TEST_CHECK(id1->short_description_key());
+ TEST_CHECK_EQUAL(id1->short_description_key()->value(), "The Description");
+ StringifyFormatter ff;
+ erepository::DepSpecPrettyPrinter pd(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ TEST_CHECK(id1->build_dependencies_key());
+ id1->build_dependencies_key()->value()->accept(pd);
+ TEST_CHECK_STRINGIFY_EQUAL(pd, "foo/bar");
+ erepository::DepSpecPrettyPrinter pr(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ TEST_CHECK(id1->run_dependencies_key());
+ id1->run_dependencies_key()->value()->accept(pr);
+ TEST_CHECK_STRINGIFY_EQUAL(pr, "foo/bar");
+
+ tr1::shared_ptr<const PackageID> id2(*env.package_database()->query(query::Matches(
+ PackageDepSpec("=cat-one/pkg-one-2", pds_pm_unspecific)), qo_require_exactly_one)->begin());
+
+ TEST_CHECK(id2->end_metadata() != id2->find_metadata("EAPI"));
+ TEST_CHECK(id2->short_description_key());
+ TEST_CHECK_EQUAL(id2->short_description_key()->value(), "dquote \" squote ' backslash \\ dollar $");
+ erepository::DepSpecPrettyPrinter pd2(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ TEST_CHECK(id2->build_dependencies_key());
+ id2->build_dependencies_key()->value()->accept(pd2);
+ TEST_CHECK_STRINGIFY_EQUAL(pd2, "foo/bar bar/baz");
+ erepository::DepSpecPrettyPrinter pr2(0, tr1::shared_ptr<const PackageID>(), ff, 0, false);
+ TEST_CHECK(id2->run_dependencies_key());
+ id2->run_dependencies_key()->value()->accept(pr2);
+ TEST_CHECK_STRINGIFY_EQUAL(pr2, "foo/bar");
+ }
+ }
+ }
+ } test_e_repository_metadata_uncached;
+
+ struct ERepositoryMetadataStaleTest : TestCase
+ {
+ ERepositoryMetadataStaleTest() : TestCase("metadata stale") { }
+
+ unsigned max_run_time() const
+ {
+ return 300;
+ }
+
+ void run()
+ {
+ for (int opass = 1 ; opass <= 3 ; ++opass)
+ {
+ TestMessageSuffix opass_suffix("opass=" + stringify(opass), true);
+
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("write_cache", "e_repository_TEST_dir/repo7/metadata/cache");
+ keys->insert("location", "e_repository_TEST_dir/repo7");
+ keys->insert("profiles", "e_repository_TEST_dir/repo7/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ for (int pass = 1 ; pass <= 3 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix("pass=" + stringify(pass), true);
+
+ tr1::shared_ptr<const PackageID> id1(*env.package_database()->query(query::Matches(
+ PackageDepSpec("=cat-one/stale-pkg-1", pds_pm_unspecific)), qo_require_exactly_one)->begin());
+
+ TEST_CHECK(id1->end_metadata() != id1->find_metadata("EAPI"));
+ TEST_CHECK(id1->short_description_key());
+ TEST_CHECK_EQUAL(id1->short_description_key()->value(), "The Generated Description");
+ }
+
+ for (int pass = 1 ; pass <= 3 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix("pass=" + stringify(pass), true);
+
+ tr1::shared_ptr<const PackageID> id1(*env.package_database()->query(query::Matches(
+ PackageDepSpec("=cat-one/stale-pkg-2", pds_pm_unspecific)), qo_require_exactly_one)->begin());
+
+ TEST_CHECK(id1->end_metadata() != id1->find_metadata("EAPI"));
+ TEST_CHECK(id1->short_description_key());
+ TEST_CHECK_EQUAL(id1->short_description_key()->value(), "The Generated Description");
+ }
+ }
+ }
+ } test_e_repository_metadata_stale;
+
+ /**
+ * \test Test ERepository unparsable metadata.
+ *
+ */
+ struct ERepositoryMetadataUnparsableTest : TestCase
+ {
+ ERepositoryMetadataUnparsableTest() : TestCase("metadata unparsable") { }
+
+ bool skip() const
+ {
+ return ! getenv_with_default("SANDBOX_ON", "").empty();
+ }
+
+ unsigned max_run_time() const
+ {
+ return 300;
+ }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo7");
+ keys->insert("profiles", "e_repository_TEST_dir/repo7/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository( &env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ tr1::shared_ptr<const PackageID> id1(*env.package_database()->query(query::Matches(
+ PackageDepSpec("=cat-one/pkg-two-1", pds_pm_unspecific)), qo_require_exactly_one)->begin());
+
+ TEST_CHECK(id1->end_metadata() != id1->find_metadata("EAPI"));
+ TEST_CHECK_EQUAL(tr1::static_pointer_cast<const erepository::ERepositoryID>(id1)->eapi()->name, "UNKNOWN");
+ TEST_CHECK(! id1->short_description_key());
+ }
+ }
+ } test_e_repository_metadata_unparsable;
+
+ /**
+ * \test Test ERepository query_use and query_use_mask functions.
+ *
+ */
+ struct ERepositoryQueryUseTest : TestCase
+ {
+ ERepositoryQueryUseTest() : TestCase("USE query") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo9");
+ keys->insert("profiles", "e_repository_TEST_dir/repo9/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ tr1::shared_ptr<const PackageID> p1(*env.package_database()->query(query::Matches(PackageDepSpec(
+ "=cat-one/pkg-one-1", pds_pm_unspecific)), qo_require_exactly_one)->begin());
+ tr1::shared_ptr<const PackageID> p2(*env.package_database()->query(query::Matches(PackageDepSpec(
+ "=cat-two/pkg-two-1", pds_pm_unspecific)), qo_require_exactly_one)->begin());
+ tr1::shared_ptr<const PackageID> p4(*env.package_database()->query(query::Matches(PackageDepSpec(
+ "=cat-one/pkg-one-2", pds_pm_unspecific)), qo_require_exactly_one)->begin());
+
+ TEST_CHECK(repo->query_use(UseFlagName("flag1"), *p1) == use_enabled);
+ TEST_CHECK(repo->query_use(UseFlagName("flag2"), *p1) == use_disabled);
+ TEST_CHECK(repo->query_use_mask(UseFlagName("flag2"), *p1));
+ TEST_CHECK(repo->query_use_mask(UseFlagName("flag3"), *p2));
+ TEST_CHECK(! repo->query_use_mask(UseFlagName("flag3"), *p1));
+ TEST_CHECK(repo->query_use_mask(UseFlagName("flag3"), *p4));
+ TEST_CHECK(repo->query_use(UseFlagName("flag3"), *p1) == use_enabled);
+ TEST_CHECK(repo->query_use(UseFlagName("flag5"), *p2) == use_enabled);
+ TEST_CHECK(repo->query_use(UseFlagName("flag5"), *p1) == use_unspecified);
+ }
+ }
+ } test_e_repository_query_use;
+
+ /**
+ * \test Test ERepository query_profile_masks functions.
+ *
+ */
+ struct ERepositoryQueryProfileMasksTest : TestCase
+ {
+ ERepositoryQueryProfileMasksTest() : TestCase("profiles package.mask") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo10");
+ keys->insert("profiles", "e_repository_TEST_dir/repo10/profiles/profile/subprofile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ for (int pass = 1 ; pass <= 2 ; ++pass)
+ {
+ TestMessageSuffix pass_suffix(stringify(pass), true);
+
+ TEST_CHECK((*env.package_database()->query(query::Matches(PackageDepSpec("=cat/masked-0", pds_pm_unspecific)),
+ qo_require_exactly_one)->begin())->masked());
+ TEST_CHECK(! (*env.package_database()->query(query::Matches(PackageDepSpec("=cat/was_masked-0", pds_pm_unspecific)),
+ qo_require_exactly_one)->begin())->masked());
+ TEST_CHECK(! (*env.package_database()->query(query::Matches(PackageDepSpec("=cat/not_masked-0", pds_pm_unspecific)),
+ qo_require_exactly_one)->begin())->masked());
+ }
+ }
+ } test_e_repository_query_profile_masks;
+
+ /**
+ * \test Test ERepository invalidate_masks functions.
+ *
+ */
+ struct ERepositoryInvalidateMasksTest : TestCase
+ {
+ ERepositoryInvalidateMasksTest() : TestCase("invalidate_masks") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo10");
+ keys->insert("profiles", "e_repository_TEST_dir/repo10/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ TEST_CHECK((*env.package_database()->query(query::Matches(PackageDepSpec("=cat/was_masked-0", pds_pm_unspecific)),
+ qo_require_exactly_one)->begin())->masked());
+ repo->set_profile(repo->find_profile(repo->params().location / "profiles/profile/subprofile"));
+ TEST_CHECK(! (*env.package_database()->query(query::Matches(PackageDepSpec("=cat/was_masked-0", pds_pm_unspecific)),
+ qo_require_exactly_one)->begin())->masked());
+ repo->set_profile(repo->find_profile(repo->params().location / "profiles/profile"));
+ TEST_CHECK((*env.package_database()->query(query::Matches(PackageDepSpec("=cat/was_masked-0", pds_pm_unspecific)),
+ qo_require_exactly_one)->begin())->masked());
+ }
+ } test_e_repository_invalidate_masks;
+
+ /**
+ * \test Test ERepository virtuals.
+ *
+ */
+ struct ERepositoryVirtualsTest : TestCase
+ {
+ ERepositoryVirtualsTest() : TestCase("virtuals") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo15");
+ keys->insert("profiles", "e_repository_TEST_dir/repo15/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ bool has_one(false), has_two(false), has_three(false);
+ int count(0);
+
+ tr1::shared_ptr<const RepositoryVirtualsInterface::VirtualsSequence> seq(repo->virtual_packages());
+ for (RepositoryVirtualsInterface::VirtualsSequence::ConstIterator it(seq->begin()),
+ it_end(seq->end()); it_end != it; ++it, ++count)
+ if ("virtual/one" == stringify(it->virtual_name))
+ {
+ has_one = true;
+ TEST_CHECK_STRINGIFY_EQUAL(*it->provided_by_spec, "cat-one/pkg-one");
+ }
+ else
+ {
+ TEST_CHECK_STRINGIFY_EQUAL(it->virtual_name, "virtual/two");
+ has_two = true;
+ TEST_CHECK_STRINGIFY_EQUAL(*it->provided_by_spec, "cat-two/pkg-two");
+ }
+
+ TEST_CHECK(has_one);
+ TEST_CHECK(has_two);
+ TEST_CHECK_EQUAL(count, 2);
+
+ repo->set_profile(repo->find_profile(repo->params().location / "profiles/profile/subprofile"));
+
+ has_one = has_two = false;
+ count = 0;
+
+ seq = repo->virtual_packages();
+ for (RepositoryVirtualsInterface::VirtualsSequence::ConstIterator it(seq->begin()),
+ it_end(seq->end()); it_end != it; ++it, ++count)
+ if ("virtual/one" == stringify(it->virtual_name))
+ {
+ has_one = true;
+ TEST_CHECK_STRINGIFY_EQUAL(*it->provided_by_spec, "cat-two/pkg-two");
+ }
+ else if ("virtual/two" == stringify(it->virtual_name))
+ {
+ has_two = true;
+ TEST_CHECK_STRINGIFY_EQUAL(*it->provided_by_spec, "cat-one/pkg-one");
+ }
+ else
+ {
+ TEST_CHECK_STRINGIFY_EQUAL(it->virtual_name, "virtual/three");
+ has_three = true;
+ TEST_CHECK_STRINGIFY_EQUAL(*it->provided_by_spec, "cat-three/pkg-three");
+ }
+
+ TEST_CHECK(has_one);
+ TEST_CHECK(has_two);
+ TEST_CHECK(has_three);
+ TEST_CHECK_EQUAL(count, 3);
+ }
+ } test_e_repository_virtuals;
+
+ /**
+ * \test Test ERepository Manifest2 generation.
+ *
+ */
+ struct ERepositoryManifestTest : TestCase
+ {
+ ERepositoryManifestTest() : TestCase("manifest2") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo11");
+ keys->insert("profiles", "e_repository_TEST_dir/repo11/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(
+ &env, keys));
+ repo->make_manifest(QualifiedPackageName("category/package"));
+
+ std::multiset<std::string> made_manifest, reference_manifest;
+ std::ifstream made_manifest_stream("e_repository_TEST_dir/repo11/category/package/Manifest"),
+ reference_manifest_stream("e_repository_TEST_dir/repo11/Manifest_correct");
+
+ std::string line;
+
+ while ( getline(made_manifest_stream, line) )
+ made_manifest.insert(line);
+ while ( getline(reference_manifest_stream, line) )
+ reference_manifest.insert(line);
+
+ TEST_CHECK(made_manifest == reference_manifest);
+ }
+ } test_e_repository_manifest;
+
+ struct ERepositoryFetchTest : TestCase
+ {
+ ERepositoryFetchTest() : TestCase("fetch") { }
+
+ unsigned max_run_time() const
+ {
+ return 300;
+ }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(new Map<std::string, std::string>);
+ keys->insert("format", "exheres");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo12");
+ keys->insert("profiles", "e_repository_TEST_dir/repo12/profiles/profile");
+ keys->insert("layout", "exheres");
+ keys->insert("eapi_when_unknown", "exheres-0");
+ keys->insert("eapi_when_unspecified", "exheres-0");
+ keys->insert("profile_eapi", "exheres-0");
+ keys->insert("distdir", stringify(FSEntry::cwd() / "e_repository_TEST_dir" / "distdir"));
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ FetchAction action(FetchActionOptions::create()
+ .fetch_unneeded(false)
+ .safe_resume(true)
+ );
+
+ {
+ TestMessageSuffix suffix("no files", true);
+ const tr1::shared_ptr<const PackageID> no_files_id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/no-files", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(no_files_id);
+ TEST_CHECK(no_files_id->short_description_key());
+ TEST_CHECK_EQUAL(no_files_id->short_description_key()->value(), "The Description");
+ no_files_id->perform_action(action);
+ }
+
+ {
+ TestMessageSuffix suffix("fetched files", true);
+ const tr1::shared_ptr<const PackageID> fetched_files_id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/fetched-files", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(fetched_files_id);
+ TEST_CHECK((FSEntry("e_repository_TEST_dir") / "distdir" / "already-fetched.txt").is_regular_file());
+ fetched_files_id->perform_action(action);
+ TEST_CHECK((FSEntry("e_repository_TEST_dir") / "distdir" / "already-fetched.txt").is_regular_file());
+ }
+
+ {
+ TestMessageSuffix suffix("fetchable files", true);
+ TEST_CHECK(! (FSEntry("e_repository_TEST_dir") / "distdir" / "fetchable-1.txt").is_regular_file());
+ const tr1::shared_ptr<const PackageID> fetchable_files_id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/fetchable-files", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(fetchable_files_id);
+ fetchable_files_id->perform_action(action);
+ TEST_CHECK((FSEntry("e_repository_TEST_dir") / "distdir" / "fetchable-1.txt").is_regular_file());
+ }
+
+ {
+ TestMessageSuffix suffix("arrow files", true);
+ TEST_CHECK(! (FSEntry("e_repository_TEST_dir") / "distdir" / "arrowed.txt").is_regular_file());
+ const tr1::shared_ptr<const PackageID> arrow_files_id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/arrow-files", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(arrow_files_id);
+ arrow_files_id->perform_action(action);
+ TEST_CHECK((FSEntry("e_repository_TEST_dir") / "distdir" / "arrowed.txt").is_regular_file());
+ }
+
+ {
+ TestMessageSuffix suffix("unfetchable files", true);
+ const tr1::shared_ptr<const PackageID> unfetchable_files_id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/unfetchable-files", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(unfetchable_files_id);
+ TEST_CHECK_THROWS(unfetchable_files_id->perform_action(action), FetchActionError);
+ }
+
+ {
+ const tr1::shared_ptr<const PackageID> no_files_restricted_id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/no-files-restricted", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(no_files_restricted_id);
+ no_files_restricted_id->perform_action(action);
+ }
+
+ {
+ const tr1::shared_ptr<const PackageID> fetched_files_restricted_id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/fetched-files-restricted", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(fetched_files_restricted_id);
+ fetched_files_restricted_id->perform_action(action);
+ }
+
+ {
+ const tr1::shared_ptr<const PackageID> fetchable_files_restricted_id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/fetchable-files-restricted", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(fetchable_files_restricted_id);
+ TEST_CHECK_THROWS(fetchable_files_restricted_id->perform_action(action), FetchActionError);
+ }
+ }
+
+ bool repeatable() const
+ {
+ return false;
+ }
+ } test_e_repository_fetch;
+
+ struct ERepositoryManifestCheckTest : TestCase
+ {
+ ERepositoryManifestCheckTest() : TestCase("manifest_check") { }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(
+ new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo11");
+ keys->insert("profiles", "e_repository_TEST_dir/repo11/profiles/profile");
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(
+ &env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ FetchAction action(FetchActionOptions::create()
+ .fetch_unneeded(false)
+ .safe_resume(true)
+ );
+
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("category/package", pds_pm_unspecific)), qo_order_by_version)->last());
+ TEST_CHECK(id);
+ id->perform_action(action);
+ }
+ } test_e_repository_manifest_check;
+
+ struct ERepositoryInstallEAPI0Test : TestCase
+ {
+ ERepositoryInstallEAPI0Test() : TestCase("install_eapi_0") { }
+
+ unsigned max_run_time() const
+ {
+ return 300;
+ }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo13");
+ keys->insert("profiles", "e_repository_TEST_dir/repo13/profiles/profile");
+ keys->insert("layout", "traditional");
+ keys->insert("eapi_when_unknown", "0");
+ keys->insert("eapi_when_unspecified", "0");
+ keys->insert("profile_eapi", "0");
+ keys->insert("distdir", stringify(FSEntry::cwd() / "e_repository_TEST_dir" / "distdir"));
+ keys->insert("builddir", stringify(FSEntry::cwd() / "e_repository_TEST_dir" / "build"));
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ tr1::shared_ptr<FakeInstalledRepository> installed_repo(new FakeInstalledRepository(&env, RepositoryName("installed")));
+ env.package_database()->add_repository(2, installed_repo);
+
+ InstallAction action(InstallActionOptions::create()
+ .debug_build(iado_none)
+ .checks(iaco_default)
+ .no_config_protect(false)
+ .destination(installed_repo)
+ );
+
+ {
+ TestMessageSuffix suffix("in-ebuild die", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/in-ebuild-die", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(id);
+ TEST_CHECK_THROWS(id->perform_action(action), InstallActionError);
+ }
+
+ {
+ TestMessageSuffix suffix("in-subshell die", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/in-subshell-die", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(id);
+ TEST_CHECK_THROWS(id->perform_action(action), InstallActionError);
+ }
+
+ {
+ TestMessageSuffix suffix("success", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/success", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(id);
+ id->perform_action(action);
+ }
+
+ {
+ TestMessageSuffix suffix("unpack die", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/unpack-die", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(id);
+ TEST_CHECK_THROWS(id->perform_action(action), InstallActionError);
+ }
+
+ {
+ TestMessageSuffix suffix("emake fail", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/emake-fail", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(id);
+ id->perform_action(action);
+ }
+
+ {
+ TestMessageSuffix suffix("econf source 0", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("=cat/econf-source-0", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(id);
+ TEST_CHECK_EQUAL(visitor_cast<const MetadataStringKey>(**id->find_metadata("EAPI"))->value(), "0");
+ TEST_CHECK_THROWS(id->perform_action(action), InstallActionError);
+ }
+ }
+ } test_e_repository_install_eapi_0;
+
+ struct ERepositoryInstallEAPI1Test : TestCase
+ {
+ ERepositoryInstallEAPI1Test() : TestCase("install_eapi_1") { }
+
+ unsigned max_run_time() const
+ {
+ return 300;
+ }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo13");
+ keys->insert("profiles", "e_repository_TEST_dir/repo13/profiles/profile");
+ keys->insert("layout", "traditional");
+ keys->insert("eapi_when_unknown", "0");
+ keys->insert("eapi_when_unspecified", "0");
+ keys->insert("profile_eapi", "0");
+ keys->insert("distdir", stringify(FSEntry::cwd() / "e_repository_TEST_dir" / "distdir"));
+ keys->insert("builddir", stringify(FSEntry::cwd() / "e_repository_TEST_dir" / "build"));
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ tr1::shared_ptr<FakeInstalledRepository> installed_repo(new FakeInstalledRepository(&env, RepositoryName("installed")));
+ env.package_database()->add_repository(2, installed_repo);
+
+ InstallAction action(InstallActionOptions::create()
+ .debug_build(iado_none)
+ .checks(iaco_default)
+ .no_config_protect(false)
+ .destination(installed_repo)
+ );
+
+ {
+ TestMessageSuffix suffix("econf source 1", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("=cat/econf-source-1", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(id);
+ TEST_CHECK_EQUAL(visitor_cast<const MetadataStringKey>(**id->find_metadata("EAPI"))->value(), "1");
+ id->perform_action(action);
+ }
+ }
+ } test_e_repository_install_eapi_1;
+
+ struct ERepositoryInstallExheres0Test : TestCase
+ {
+ ERepositoryInstallExheres0Test() : TestCase("install_exheres_0") { }
+
+ unsigned max_run_time() const
+ {
+ return 300;
+ }
+
+ void run()
+ {
+ TestEnvironment env;
+ tr1::shared_ptr<Map<std::string, std::string> > keys(new Map<std::string, std::string>);
+ keys->insert("format", "ebuild");
+ keys->insert("names_cache", "/var/empty");
+ keys->insert("location", "e_repository_TEST_dir/repo14");
+ keys->insert("profiles", "e_repository_TEST_dir/repo14/profiles/profile");
+ keys->insert("layout", "exheres");
+ keys->insert("eapi_when_unknown", "exheres-0");
+ keys->insert("eapi_when_unspecified", "exheres-0");
+ keys->insert("profile_eapi", "exheres-0");
+ keys->insert("distdir", stringify(FSEntry::cwd() / "e_repository_TEST_dir" / "distdir"));
+ keys->insert("builddir", stringify(FSEntry::cwd() / "e_repository_TEST_dir" / "build"));
+ tr1::shared_ptr<ERepository> repo(make_ebuild_repository(&env, keys));
+ env.package_database()->add_repository(1, repo);
+
+ tr1::shared_ptr<FakeInstalledRepository> installed_repo(new FakeInstalledRepository(&env, RepositoryName("installed")));
+ env.package_database()->add_repository(2, installed_repo);
+
+ InstallAction action(InstallActionOptions::create()
+ .debug_build(iado_none)
+ .checks(iaco_default)
+ .no_config_protect(false)
+ .destination(installed_repo)
+ );
+
+ {
+ TestMessageSuffix suffix("in-ebuild die", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/in-ebuild-die", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(id);
+ TEST_CHECK_THROWS(id->perform_action(action), InstallActionError);
+ }
+
+ {
+ TestMessageSuffix suffix("in-subshell die", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/in-subshell-die", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(id);
+ TEST_CHECK_THROWS(id->perform_action(action), InstallActionError);
+ }
+
+ {
+ TestMessageSuffix suffix("success", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/success", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(id);
+ id->perform_action(action);
+ }
+
+ {
+ TestMessageSuffix suffix("unpack die", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/unpack-die", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(id);
+ TEST_CHECK_THROWS(id->perform_action(action), InstallActionError);
+ }
+
+ {
+ TestMessageSuffix suffix("emake fail", true);
+ const tr1::shared_ptr<const PackageID> id(*env.package_database()->query(query::Matches(
+ PackageDepSpec("cat/emake-fail", pds_pm_unspecific)), qo_require_exactly_one)->last());
+ TEST_CHECK(id);
+ TEST_CHECK_THROWS(id->perform_action(action), InstallActionError);
+ }
+ }
+ } test_e_repository_install_exheres_0;
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository_TEST_cleanup.sh b/0.26.0_alpha1/paludis/repositories/e/e_repository_TEST_cleanup.sh
new file mode 100755
index 000000000..3fcc1aac1
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository_TEST_cleanup.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d e_repository_TEST_dir ] ; then
+ rm -fr e_repository_TEST_dir
+else
+ true
+fi
+
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository_TEST_setup.sh b/0.26.0_alpha1/paludis/repositories/e/e_repository_TEST_setup.sh
new file mode 100755
index 000000000..ad8311ddc
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository_TEST_setup.sh
@@ -0,0 +1,689 @@
+#!/bin/bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir e_repository_TEST_dir || exit 1
+cd e_repository_TEST_dir || exit 1
+
+mkdir -p build
+
+mkdir -p distdir
+echo "already fetched" > distdir/already-fetched.txt || exit 1
+
+mkdir -p fetchable
+echo "one" > fetchable/fetchable-1.txt || exit 1
+echo "two" > fetchable/fetchable-2.txt || exit 1
+
+mkdir -p repo1/{eclass,distfiles,profiles/profile} || exit 1
+cd repo1 || exit 1
+echo "test-repo-1" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat-one
+cat-two
+cat-three
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cd ..
+
+mkdir -p repo2/{eclass,distfiles,profiles/profile} || exit 1
+cd repo2 || exit 1
+cat <<END > profiles/categories || exit 1
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cd ..
+
+
+mkdir -p repo3/{eclass,distfiles,profiles/profile} || exit 1
+cd repo3 || exit 1
+echo "# test-repo-3" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cd ..
+
+
+mkdir -p repo4/{eclass,distfiles,profiles/profile} || exit 1
+mkdir -p repo4/{cat-one/{pkg-one,pkg-both},cat-two/{pkg-two,pkg-both}} || exit 1
+cd repo4 || exit 1
+echo "test-repo-4" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat-one
+cat-two
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.1-r1.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-both/pkg-both-3.45.ebuild || exit 1
+END
+cat <<END > cat-two/pkg-two/pkg-two-2.ebuild || exit 1
+END
+cat <<END > cat-two/pkg-both/pkg-both-1.23.ebuild || exit 1
+END
+cd ..
+
+
+mkdir -p repo5/{eclass,distfiles,profiles/profile} || exit 1
+mkdir -p repo5/cat-one/{pkg-one,pkg-1,pkg.one} || exit 1
+cd repo5 || exit 1
+echo "test-repo-5" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat-one
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-1/pkg-1-1.ebuild || exit 1
+END
+cat <<END > cat-one/pkg.one/pkg.one-1.ebuild || exit 1
+END
+cd ..
+
+
+mkdir -p repo6/{eclass,distfiles,profiles/profile} || exit 1
+mkdir -p repo6/cat-one/pkg-one || exit 1
+mkdir -p repo6/metadata/cache/cat-one
+cd repo6 || exit 1
+echo "test-repo-6" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat-one
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.ebuild || exit 1
+END
+cat <<END > metadata/cache/cat-one/pkg-one-1
+the/depend
+the/rdepend
+the-slot
+the-src-uri
+the-restrict
+the-homepage
+the-license
+the-description
+the-keywords
+
+the-iuse
+unused
+the/pdepend
+the/provide
+0
+END
+cd ..
+
+
+mkdir -p repo7/{eclass,distfiles,profiles/profile} || exit 1
+mkdir -p repo7/cat-one/{stale-pkg,pkg-{one,two}} || exit 1
+mkdir -p repo7/metadata/cache/cat-{one,two}
+cd repo7 || exit 1
+echo "test-repo-7" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat-one
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.ebuild || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE=""
+LICENSE="GPL-2"
+KEYWORDS="test"
+DEPEND="foo/bar"
+END
+cat <<"END" > cat-one/pkg-one/pkg-one-2.ebuild || exit 1
+inherit mine
+DESCRIPTION="dquote \" squote ' backslash \\ dollar \$"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE=""
+LICENSE="GPL-2"
+KEYWORDS="test"
+DEPEND="foo/bar"
+END
+cat <<END > eclass/mine.eclass
+DEPEND="bar/baz"
+END
+cat <<END > eclass/stale.eclass
+END
+cat <<END > cat-one/pkg-two/pkg-two-1.ebuild || exit 1
+i am a fish
+END
+
+cat <<END > cat-one/stale-pkg/stale-pkg-1.ebuild || exit 1
+DESCRIPTION="The Generated Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE=""
+LICENSE="GPL-2"
+KEYWORDS="test"
+DEPEND=""
+END
+cat <<END > metadata/cache/cat-one/stale-pkg-1
+the/depend
+the/rdepend
+the-slot
+the-src-uri
+the-restrict
+the-homepage
+the-license
+The Stale Description
+the-keywords
+
+the-iuse
+unused
+the/pdepend
+the/provide
+0
+END
+touch -t 199901010101 metadata/cache/cat-one/stale-pkg-1 || exit 2
+
+cat <<END > cat-one/stale-pkg/stale-pkg-2.ebuild || exit 1
+inherit stale
+
+DESCRIPTION="The Generated Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE=""
+LICENSE="GPL-2"
+KEYWORDS="test"
+DEPEND=""
+END
+cat <<END > metadata/cache/cat-one/stale-pkg-2
+the/depend
+the/rdepend
+the-slot
+the-src-uri
+the-restrict
+the-homepage
+the-license
+The Stale Description
+the-keywords
+stale
+the-iuse
+unused
+the/pdepend
+the/provide
+0
+END
+touch -t 199901010101 metadata/cache/cat-one/stale-pkg-2 || exit 2
+cd ..
+
+mkdir -p repo8/{eclass,distfiles,profiles/profile} || exit 1
+mkdir -p repo8/{cat-one/{pkg-one,pkg-both},cat-two/{pkg-two,pkg-both}} || exit 1
+cd repo8 || exit 1
+echo "test-repo-8" > profiles/repo_name || exit 1
+cat <<END > profiles/categories || exit 1
+cat-one
+cat-two
+END
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-one/pkg-one-1-monkey.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.1-r1.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-both/pkg-both-3.45.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-both/pkg-both-3.45_r1.ebuild || exit 1
+END
+cat <<END > cat-two/pkg-two/pkg-two-2.ebuild || exit 1
+END
+cat <<END > cat-two/pkg-both/pkg-both-1.23.ebuild || exit 1
+END
+cat <<END > cat-two/pkg-both/pkg-both-.ebuild || exit 1
+END
+cd ..
+
+
+mkdir -p repo9/{eclass,distfiles,profiles/profile,cat-one/pkg-one,cat-two/pkg-one} || exit 1
+mkdir -p repo9/{cat-one/pkg-one,cat-two/pkg-two} || exit 1
+cd repo9 || exit 1
+echo "test-repo-9" > profiles/repo_name || exit 1
+cat <<END >profiles/categories || exit 1
+cat-one
+cat-two
+END
+cat <<END >profiles/profile/make.defaults || exit 1
+ARCH=test
+USE="flag1 flag2 flag3 -flag4 -flag5"
+END
+cat <<END >profiles/profile/use.mask || exit 1
+flag2
+END
+cat <<END >profiles/profile/use.force || exit 1
+flag4
+END
+cat <<END >profiles/profile/package.use.mask || exit 1
+cat-two/pkg-two flag3
+>=cat-one/pkg-one-2 flag3
+END
+cat <<END >profiles/profile/package.use.force || exit 1
+cat-two/pkg-two flag5
+END
+cat <<END > cat-one/pkg-one/pkg-one-1.ebuild || exit 1
+END
+cat <<END > cat-one/pkg-one/pkg-one-2.ebuild || exit 1
+END
+cat <<END > cat-two/pkg-two/pkg-two-1.ebuild || exit 1
+END
+cd ..
+
+mkdir -p repo10/{eclass,distfiles,profiles/profile/subprofile,cat/masked,cat/not_masked,cat/was_masked} || exit 1
+cd repo10 || exit 1
+echo "test-repo-10" > profiles/repo_name || exit 1
+cat <<END >profiles/profiles.desc || exit 1
+test profile stable
+test profile/subprofile stable
+END
+cat <<END >profiles/profile/make.defaults || exit 1
+ARCH=test
+USE="flag1 flag2 flag3 -flag4 -flag5"
+END
+cat <<END >profiles/categories || exit 1
+cat
+END
+cat <<END >profiles/profile/package.mask
+cat/masked
+cat/was_masked
+END
+cat <<END >profiles/profile/subprofile/package.mask
+-cat/was_masked
+END
+cat <<END >profiles/profile/subprofile/parent
+..
+END
+cat <<END > cat/masked/masked-0.ebuild
+KEYWORDS="test"
+END
+cat <<END > cat/not_masked/not_masked-0.ebuild
+KEYWORDS="test"
+END
+cat <<END > cat/was_masked/was_masked-0.ebuild
+KEYWORDS="test"
+END
+cd ..
+
+mkdir -p repo11/{eclass,distfiles,profiles/profile} || exit 1
+mkdir -p repo11/category/package/files || exit 1
+cd repo11 || exit 1
+echo "test-repo-11" >> profiles/repo_name || exit 1
+echo "category" >> profiles/categories || exit 1
+cat <<END > profiles/profile/make.defaults
+ARCH=test
+END
+cat <<END > category/package/package-1.ebuild || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI="foo"
+SLOT="0"
+IUSE=""
+LICENSE="GPL-2"
+KEYWORDS="test"
+DEPEND=""
+END
+cat <<END > category/package/package-2.ebuild || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI="bar"
+SLOT="0"
+IUSE=""
+LICENSE="GPL-2"
+KEYWORDS="test"
+DEPEND=""
+END
+cat <<END > category/package/ChangeLog || exit 1
+The times, they are-a changin'...
+END
+cat <<END > category/package/metadata.xml || exit
+This isn't valid xml & I don't care!
+END
+cat <<END > category/package/files/some.patch || exit 1
++ Manifest2
+END
+echo "something" > distfiles/foo || exit 1
+echo "for nothing" > distfiles/bar || exit 1
+cat <<END > Manifest_correct || exit 1
+AUX some.patch 12 RMD160 e7f53a2bea1265ef55ae5494ef6050ff7fd1a900 SHA256 26955b4e2d4f60561b8002b72c34ce266f534a4f32f13a29aa33875d39d31cc4
+DIST bar 12 RMD160 90bd2a71cf9d8cf744b0afc0e9a00b999bb59f72 SHA256 27cd06afc317a809116e7730736663b9f09dd863fcc37b69d32d4f5eb58708b2
+DIST foo 10 RMD160 9e19cc1527a061585aa02dae8b7f4047dcd16275 SHA256 4bc453b53cb3d914b45f4b250294236adba2c0e09ff6f03793949e7e39fd4cc1
+EBUILD package-1.ebuild 134 RMD160 0a59df8f246cd5d9f83b89b36026701f1bfe235b SHA256 4d58e5622889397ff6a257d87652a8220585c4d97efbf0a42bf59b3f75d19e03
+EBUILD package-2.ebuild 134 RMD160 d8149a3828ea05849c7033c431d3df5c6eaab67d SHA256 3fb00f77d96c3e6576c2d424d31023958b507bdf20eb6555e89a135b37a54c07
+MISC ChangeLog 34 RMD160 64ae4731e1de8dc8d81f0504c22e586358a5b6f0 SHA256 a8dfbbc187c93c0731fa9722aff87c437a4b9f59b1786d62651fb104b0c3ed97
+MISC metadata.xml 37 RMD160 52a6de8e54eeea3b5e3e8357a400fbc6d3f4062b SHA256 ba3b181b832c002612fba7768c95e526e188658d8fc85b92c153940ad43169de
+END
+cd ..
+
+mkdir -p repo12/{profiles/profile,metadata} || exit 1
+cd repo12 || exit 1
+echo "test-repo-12" >> profiles/repo_name || exit 1
+echo "cat" >> metadata/categories.conf || exit 1
+cat <<END > profiles/profile/make.defaults
+END
+mkdir -p packages/cat/no-files
+cat <<END > packages/cat/no-files/no-files-1.exheres-0 || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+MYOPTIONS=""
+LICENSE="GPL-2"
+PLATFORMS="test"
+DEPENDENCIES=""
+END
+mkdir -p packages/cat/fetched-files
+cat <<END > packages/cat/fetched-files/fetched-files-1.exheres-0 || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI="file:///var/empty/already-fetched.txt"
+SLOT="0"
+MYOPTIONS=""
+LICENSE="GPL-2"
+PLATFORMS="test"
+DEPENDENCIES=""
+END
+mkdir -p packages/cat/fetchable-files
+cat <<END > packages/cat/fetchable-files/fetchable-files-1.exheres-0 || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI="file:///$(dirname $(pwd ) )/fetchable/fetchable-1.txt"
+SLOT="0"
+MYOPTIONS=""
+LICENSE="GPL-2"
+PLATFORMS="test"
+DEPENDENCIES=""
+END
+mkdir -p packages/cat/arrow-files
+cat <<END > packages/cat/arrow-files/arrow-files-1.exheres-0 || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI="file:///$(dirname $(pwd ) )/fetchable/fetchable-1.txt -> arrowed.txt"
+SLOT="0"
+MYOPTIONS=""
+LICENSE="GPL-2"
+PLATFORMS="test"
+DEPENDENCIES=""
+END
+mkdir -p packages/cat/unfetchable-files
+cat <<END > packages/cat/unfetchable-files/unfetchable-files-1.exheres-0 || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI="file:///var/empty/unfetchable-file.txt"
+SLOT="0"
+MYOPTIONS=""
+LICENSE="GPL-2"
+PLATFORMS="test"
+DEPENDENCIES=""
+END
+mkdir -p packages/cat/no-files-restricted
+cat <<END > packages/cat/no-files-restricted/no-files-restricted-1.exheres-0 || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+MYOPTIONS=""
+LICENSE="GPL-2"
+PLATFORMS="test"
+DEPENDENCIES=""
+END
+mkdir -p packages/cat/fetched-files-restricted
+cat <<END > packages/cat/fetched-files-restricted/fetched-files-restricted-1.exheres-0 || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI="manual: file:///var/empty/already-fetched.txt"
+SLOT="0"
+MYOPTIONS=""
+LICENSE="GPL-2"
+PLATFORMS="test"
+DEPENDENCIES=""
+END
+mkdir -p packages/cat/fetchable-files-restricted
+cat <<END > packages/cat/fetchable-files-restricted/fetchable-files-restricted-1.exheres-0 || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI="manual: file:///$(dirname $(pwd ) )/fetchable/fetchable-2.txt"
+SLOT="0"
+MYOPTIONS=""
+LICENSE="GPL-2"
+PLATFORMS="test"
+DEPENDENCIES=""
+END
+cd ..
+
+mkdir -p repo13/{profiles/profile,metadata,eclass} || exit 1
+cd repo13 || exit 1
+echo "test-repo-13" >> profiles/repo_name || exit 1
+echo "cat" >> profiles/categories || exit 1
+cat <<END > profiles/profile/make.defaults
+ARCH="test"
+USERLAND="GNU"
+KERNEL="linux"
+LIBC="glibc"
+CHOST="i286-badger-linux-gnu"
+PALUDIS_COMMAND="/bin/false"
+END
+mkdir -p "cat/in-ebuild-die"
+cat <<END > cat/in-ebuild-die/in-ebuild-die-1.ebuild || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE=""
+LICENSE="GPL-2"
+KEYWORDS="test"
+
+pkg_setup() {
+ die "boom"
+}
+END
+mkdir -p "cat/in-subshell-die"
+cat <<END > cat/in-subshell-die/in-subshell-die-1.ebuild || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE=""
+LICENSE="GPL-2"
+KEYWORDS="test"
+
+pkg_setup() {
+ ( hasq test \$KEYWORDS && die "boom" )
+}
+END
+mkdir -p "cat/success"
+cat <<END > cat/success/success-1.ebuild || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE="spork"
+LICENSE="GPL-2"
+KEYWORDS="test"
+
+pkg_setup() {
+ useq spork && die "boom"
+}
+END
+mkdir -p "cat/unpack-die"
+cat <<END > cat/unpack-die/unpack-die-1.ebuild || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE="spork"
+LICENSE="GPL-2"
+KEYWORDS="test"
+
+src_unpack() {
+ echo "123" > f.bz2
+ unpack ./f.bz2
+}
+END
+mkdir -p "cat/emake-fail"
+cat <<END > cat/emake-fail/emake-fail-1.ebuild || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE="spork"
+LICENSE="GPL-2"
+KEYWORDS="test"
+
+src_compile() {
+ emake monkey
+}
+END
+mkdir -p "cat/econf-source"
+cat <<END > cat/econf-source/econf-source-0.ebuild || exit 1
+EAPI="\${PV}"
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+IUSE="spork"
+LICENSE="GPL-2"
+KEYWORDS="test"
+
+src_unpack() {
+ ECONF_SOURCE=subdir
+ mkdir \${S}
+ cd \${S}
+ mkdir subdir
+ echo 'touch monkey' > subdir/configure
+ chmod +x subdir/configure
+}
+
+src_install() {
+ insinto /usr/bin
+ doins monkey || die "no monkey"
+}
+END
+cp cat/econf-source/econf-source-{0,1}.ebuild || exit 1
+cd ..
+
+mkdir -p repo14/{profiles/profile,metadata,eclass} || exit 1
+cd repo14 || exit 1
+echo "test-repo-14" >> profiles/repo_name || exit 1
+echo "cat" >> metadata/categories.conf || exit 1
+cat <<END > profiles/profile/make.defaults
+CHOST="i286-badger-linux-gnu"
+PALUDIS_COMMAND="/bin/false"
+END
+mkdir -p "packages/cat/in-ebuild-die"
+cat <<END > packages/cat/in-ebuild-die/in-ebuild-die-1.ebuild || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+MYOPTIONS=""
+LICENSE="GPL-2"
+PLATFORMS="test"
+
+pkg_setup() {
+ die "boom"
+}
+END
+mkdir -p "packages/cat/in-subshell-die"
+cat <<END > packages/cat/in-subshell-die/in-subshell-die-1.ebuild || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+MYOPTIONS=""
+LICENSE="GPL-2"
+PLATFORMS="test"
+
+pkg_setup() {
+ ( hasq test \$PLATFORMS && die "boom" )
+}
+END
+mkdir -p "packages/cat/success"
+cat <<END > packages/cat/success/success-1.ebuild || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+MYOPTIONS="spork"
+LICENSE="GPL-2"
+PLATFORMS="test"
+
+pkg_setup() {
+ optionq spork && die "boom"
+}
+END
+mkdir -p "packages/cat/unpack-die"
+cat <<END > packages/cat/unpack-die/unpack-die-1.ebuild || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+MYOPTIONS="spork"
+LICENSE="GPL-2"
+PLATFORMS="test"
+
+src_unpack() {
+ echo "123" > f.bz2
+ unpack ./f.bz2
+}
+END
+mkdir -p "packages/cat/emake-fail"
+cat <<END > packages/cat/emake-fail/emake-fail-1.ebuild || exit 1
+DESCRIPTION="The Description"
+HOMEPAGE="http://example.com/"
+SRC_URI=""
+SLOT="0"
+MYOPTIONS="spork"
+LICENSE="GPL-2"
+PLATFORMS="test"
+
+src_compile() {
+ emake monkey
+}
+END
+cd ..
+
+mkdir -p repo15/{eclass,distfiles,profiles/profile/subprofile} || exit 1
+cd repo15 || exit 1
+echo "test-repo-15" >> profiles/repo_name || exit 1
+cat <<END >profiles/profiles.desc || exit 1
+test profile stable
+test profile/subprofile stable
+END
+cat <<END > profiles/profile/make.defaults || exit 1
+ARCH=test
+END
+cat <<END > profiles/profile/virtuals || exit 1
+virtual/one cat-one/pkg-one
+virtual/two cat-two/pkg-two
+END
+cat <<END >profiles/profile/subprofile/parent || exit 1
+..
+END
+cat <<END > profiles/profile/subprofile/virtuals || exit 1
+virtual/one cat-two/pkg-two
+virtual/two cat-one/pkg-one
+virtual/three cat-three/pkg-three
+END
+cd ..
+
+cd ..
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository_entries.cc b/0.26.0_alpha1/paludis/repositories/e/e_repository_entries.cc
new file mode 100644
index 000000000..ed2c1452f
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository_entries.cc
@@ -0,0 +1,52 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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 "e_repository_entries.hh"
+#include "ebuild_entries.hh"
+#include "ebin_entries.hh"
+#include <paludis/util/virtual_constructor-impl.hh>
+#include <paludis/util/instantiation_policy-impl.hh>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+template class VirtualConstructor<std::string,
+ tr1::shared_ptr<ERepositoryEntries> (*) (const Environment * const, ERepository * const,
+ const ERepositoryParams &),
+ virtual_constructor_not_found::ThrowException<NoSuchERepositoryEntriesType> >;
+
+template class InstantiationPolicy<ERepositoryEntriesMaker, instantiation_method::SingletonTag>;
+
+ERepositoryEntries::~ERepositoryEntries()
+{
+}
+
+NoSuchERepositoryEntriesType::NoSuchERepositoryEntriesType(const std::string & format) throw ():
+ ConfigurationError("No available maker for E Repository entries type '" + format + "'")
+{
+}
+
+ERepositoryEntriesMaker::ERepositoryEntriesMaker()
+{
+ register_maker("ebuild", &EbuildEntries::make_ebuild_entries);
+#if 0
+ register_maker("ebin", &EbinEntries::make_ebin_entries);
+#endif
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository_entries.hh b/0.26.0_alpha1/paludis/repositories/e/e_repository_entries.hh
new file mode 100644
index 000000000..0e600d819
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository_entries.hh
@@ -0,0 +1,156 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_E_E_REPOSITORY_METADATA_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_E_REPOSITORY_METADATA_HH 1
+
+#include <paludis/name-fwd.hh>
+#include <paludis/action-fwd.hh>
+#include <paludis/repository-fwd.hh>
+#include <paludis/version_spec-fwd.hh>
+#include <paludis/package_id-fwd.hh>
+#include <paludis/environment-fwd.hh>
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/virtual_constructor.hh>
+#include <paludis/util/tr1_memory.hh>
+#include <paludis/repositories/e/e_repository_profile.hh>
+#include <paludis/repositories/e/e_repository_params.hh>
+#include <paludis/repositories/e/e_repository_id.hh>
+#include <string>
+
+/** \file
+ * Declaration for the ERepositoryEntries class.
+ *
+ * \ingroup grperepository
+ */
+
+namespace paludis
+{
+ class ERepository;
+
+ namespace erepository
+ {
+ /**
+ * Handle entries (for example, ebuilds) in a ERepository.
+ *
+ * \ingroup grperepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE ERepositoryEntries
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ virtual ~ERepositoryEntries() = 0;
+
+ ///\}
+
+ virtual bool is_package_file(const QualifiedPackageName &, const FSEntry &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual VersionSpec extract_package_file_version(const QualifiedPackageName &, const FSEntry &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ /**
+ * Create an ERepositoryID.
+ */
+ virtual const tr1::shared_ptr<const ERepositoryID> make_id(const QualifiedPackageName &, const VersionSpec &,
+ const FSEntry &, const std::string &) const
+ PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ /**
+ * Fetch an environment variable.
+ */
+ virtual std::string get_environment_variable(const tr1::shared_ptr<const ERepositoryID> &, const std::string & var,
+ tr1::shared_ptr<const ERepositoryProfile>) const = 0;
+
+ /**
+ * Handle an install.
+ */
+ virtual void install(const tr1::shared_ptr<const ERepositoryID> &, const InstallActionOptions &,
+ tr1::shared_ptr<const ERepositoryProfile>) const = 0;
+
+ /**
+ * Handle a fetch.
+ */
+ virtual void fetch(const tr1::shared_ptr<const ERepositoryID> &, const FetchActionOptions &,
+ tr1::shared_ptr<const ERepositoryProfile>) const = 0;
+
+ /**
+ * Handle a pretend.
+ */
+ virtual bool pretend(const tr1::shared_ptr<const ERepositoryID> &,
+ tr1::shared_ptr<const ERepositoryProfile>) const = 0;
+
+ /**
+ * Handle an info.
+ */
+ virtual void info(const tr1::shared_ptr<const ERepositoryID> &,
+ tr1::shared_ptr<const ERepositoryProfile>) const = 0;
+
+ /**
+ * Handle a merge.
+ */
+ virtual void merge(const MergeOptions &) = 0;
+
+ /**
+ * Gives the Manifest key for a given package file (for
+ * example, "EBUILD").
+ */
+ virtual std::string get_package_file_manifest_key(const FSEntry &, const QualifiedPackageName &) const = 0;
+ };
+
+ /**
+ * Thrown if a repository of the specified type does not exist.
+ *
+ * \ingroup grpexceptions
+ * \ingroup grprepository
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE NoSuchERepositoryEntriesType : public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ NoSuchERepositoryEntriesType(const std::string & format) throw ();
+ };
+
+ /**
+ * Virtual constructor for ERepositoryEntries.
+ *
+ * \ingroup grprepository
+ */
+ class PALUDIS_VISIBLE ERepositoryEntriesMaker :
+ public VirtualConstructor<std::string,
+ tr1::shared_ptr<ERepositoryEntries> (*) (const Environment * const, ERepository * const,
+ const ERepositoryParams &),
+ virtual_constructor_not_found::ThrowException<NoSuchERepositoryEntriesType> >,
+ public InstantiationPolicy<ERepositoryEntriesMaker, instantiation_method::SingletonTag>
+ {
+ friend class InstantiationPolicy<ERepositoryEntriesMaker, instantiation_method::SingletonTag>;
+
+ private:
+ ERepositoryEntriesMaker();
+ };
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository_exceptions.cc b/0.26.0_alpha1/paludis/repositories/e/e_repository_exceptions.cc
new file mode 100644
index 000000000..c9f6d386a
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository_exceptions.cc
@@ -0,0 +1,29 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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 "e_repository_exceptions.hh"
+
+using namespace paludis;
+
+ERepositoryConfigurationError::ERepositoryConfigurationError(
+ const std::string & msg) throw () :
+ ConfigurationError("E Repository configuration error: " + msg)
+{
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository_exceptions.hh b/0.26.0_alpha1/paludis/repositories/e/e_repository_exceptions.hh
new file mode 100644
index 000000000..65cde585f
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository_exceptions.hh
@@ -0,0 +1,53 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_E_E_REPOSITORY_EXCEPTIONS_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_E_REPOSITORY_EXCEPTIONS_HH 1
+
+#include <paludis/util/exception.hh>
+
+/** \file
+ * Declaration for the ERepository exception classes.
+ *
+ * \ingroup grperepository
+ */
+
+namespace paludis
+{
+ /**
+ * Thrown if invalid parameters are provided for
+ * ERepository::make_e_repository.
+ *
+ * \ingroup grpexceptions
+ * \ingroup grperepository
+ */
+ class PALUDIS_VISIBLE ERepositoryConfigurationError :
+ public ConfigurationError
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ ERepositoryConfigurationError(const std::string & msg) throw ();
+ };
+
+
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository_id.cc b/0.26.0_alpha1/paludis/repositories/e/e_repository_id.cc
new file mode 100644
index 000000000..317e66b3a
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository_id.cc
@@ -0,0 +1,33 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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/version_spec.hh>
+#include <paludis/repositories/e/eapi.hh>
+#include <paludis/repositories/e/e_repository_id.hh>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+bool
+ERepositoryID::breaks_portage() const
+{
+ return (version().has_try_part() || version().has_scm_part()
+ || (! eapi()->supported) || (eapi()->supported->breaks_portage));
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository_id.hh b/0.26.0_alpha1/paludis/repositories/e/e_repository_id.hh
new file mode 100644
index 000000000..f8c486cf4
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository_id.hh
@@ -0,0 +1,42 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_E_E_REPOSITORY_ID_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_E_REPOSITORY_ID_HH 1
+
+#include <paludis/package_id.hh>
+#include <paludis/repositories/e/eapi-fwd.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ class ERepositoryID :
+ public PackageID
+ {
+ public:
+ virtual const tr1::shared_ptr<const EAPI> eapi() const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+ virtual const tr1::shared_ptr<const MetadataSpecTreeKey<RestrictSpecTree> > restrict_key() const = 0;
+
+ virtual bool breaks_portage() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+}
+
+#endif
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository_mask_file.cc b/0.26.0_alpha1/paludis/repositories/e/e_repository_mask_file.cc
new file mode 100644
index 000000000..4f3dc63e4
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository_mask_file.cc
@@ -0,0 +1,97 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 David Leverton <levertond@googlemail.com>
+ *
+ * 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 "e_repository_mask_file.hh"
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/options.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/config_file.hh>
+#include <paludis/mask.hh>
+
+#include <libwrapiter/libwrapiter_forward_iterator-impl.hh>
+#include <libwrapiter/libwrapiter_output_iterator-impl.hh>
+
+#include <list>
+
+using namespace paludis;
+using namespace paludis::erepository;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<MaskFile>
+ {
+ std::list<std::pair<const std::string, tr1::shared_ptr<const RepositoryMaskInfo> > > lines;
+ };
+}
+
+MaskFile::MaskFile(const FSEntry & f, const LineConfigFileOptions & opts) :
+ PrivateImplementationPattern<MaskFile>(new Implementation<MaskFile>)
+{
+ LineConfigFileOptions myopts(opts);
+ myopts += lcfo_disallow_comments;
+ myopts += lcfo_no_skip_blank_lines;
+
+ LineConfigFile file(f, myopts);
+ tr1::shared_ptr<Sequence<std::string> > comment(new Sequence<std::string>);
+ bool comment_used(false);
+ for (LineConfigFile::ConstIterator it(file.begin()), it_end(file.end()); it_end != it; ++it)
+ {
+ if (it->empty())
+ {
+ comment.reset(new Sequence<std::string>);
+ comment_used = false;
+ continue;
+ }
+
+ if ('#' == it->at(0))
+ {
+ if (comment_used)
+ {
+ tr1::shared_ptr<Sequence<std::string> > cpy(new Sequence<std::string>);
+ std::copy(comment->begin(), comment->end(), cpy->back_inserter());
+ comment = cpy;
+ comment_used = false;
+ }
+ comment->push_back(strip_leading(it->substr(1), " \t\r\n"));
+ continue;
+ }
+
+ _imp->lines.push_back(std::make_pair(*it, tr1::shared_ptr<RepositoryMaskInfo>(new RepositoryMaskInfo(f, comment))));
+ comment_used = true;
+ }
+}
+
+MaskFile::ConstIterator
+MaskFile::begin() const
+{
+ return ConstIterator(_imp->lines.begin());
+}
+
+MaskFile::ConstIterator
+MaskFile::end() const
+{
+ return ConstIterator(_imp->lines.end());
+}
+
+MaskFile::~MaskFile()
+{
+}
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository_mask_file.hh b/0.26.0_alpha1/paludis/repositories/e/e_repository_mask_file.hh
new file mode 100644
index 000000000..1587a32e5
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository_mask_file.hh
@@ -0,0 +1,68 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2007 David Leverton <levertond@googlemail.com>
+ *
+ * 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_E_E_REPOSITORY_MASK_FILE_HH
+#define PALUDIS_GUARD_PALUDIS_REPOSITORIES_E_E_REPOSITORY_MASK_FILE_HH 1
+
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/config_file.hh>
+#include <paludis/mask-fwd.hh>
+
+#include <libwrapiter/libwrapiter_forward_iterator-fwd.hh>
+
+namespace paludis
+{
+ namespace erepository
+ {
+ /**
+ * A file listing masks in an ERepository.
+ *
+ * Handles parsing mask reasons from the comments.
+ *
+ * \ingroup grperepository
+ */
+ class PALUDIS_VISIBLE MaskFile :
+ private PrivateImplementationPattern<MaskFile>
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ MaskFile(const FSEntry &, const LineConfigFileOptions &);
+ ~MaskFile();
+
+ ///\}
+
+ ///\name Iterate over our mask lines.
+ ///\{
+
+ typedef libwrapiter::ForwardIterator<MaskFile,
+ const std::pair<const std::string, tr1::shared_ptr<const RepositoryMaskInfo> > > ConstIterator;
+ ConstIterator begin() const;
+ ConstIterator end() const;
+
+ ///\}
+ };
+ }
+}
+
+#endif
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository_news.cc b/0.26.0_alpha1/paludis/repositories/e/e_repository_news.cc
new file mode 100644
index 000000000..6e0b84e79
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository_news.cc
@@ -0,0 +1,294 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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_repository.hh>
+#include <paludis/repositories/e/e_repository_news.hh>
+
+#include <paludis/util/config_file.hh>
+#include <paludis/environment.hh>
+#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/strip.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/options.hh>
+#include <paludis/query.hh>
+#include <libwrapiter/libwrapiter_forward_iterator.hh>
+
+#include <set>
+#include <ostream>
+#include <fstream>
+#include <list>
+
+using namespace paludis;
+
+namespace paludis
+{
+ /**
+ * Implementation data for ERepositoryNews.
+ *
+ * \ingroup grperepository
+ */
+ template<>
+ struct Implementation<ERepositoryNews>
+ {
+ const Environment * const environment;
+ const ERepository * const e_repository;
+ const ERepositoryParams params;
+
+ const FSEntry skip_file;
+ const FSEntry unread_file;
+
+ Implementation(const Environment * const e, const ERepository * const p,
+ const ERepositoryParams & k) :
+ environment(e),
+ e_repository(p),
+ params(k),
+ skip_file(e->root() / "var" / "lib" / "paludis" / "news" /
+ ("news-" + stringify(e_repository->name()) + ".skip")),
+ unread_file(e->root() / "var" / "lib" / "paludis" / "news" /
+ ("news-" + stringify(e_repository->name()) + ".unread"))
+ {
+ }
+ };
+}
+
+ERepositoryNews::ERepositoryNews(const Environment * const e, const ERepository * const p,
+ const ERepositoryParams & k) :
+ PrivateImplementationPattern<ERepositoryNews>(new Implementation<ERepositoryNews>(e, p, k))
+{
+}
+
+ERepositoryNews::~ERepositoryNews()
+{
+}
+
+void
+ERepositoryNews::update_news() const
+{
+ Context context("When updating news at location '" +
+ stringify(_imp->params.newsdir) + "' for repository '" +
+ stringify(_imp->e_repository->name()) + "':");
+
+ if (! _imp->params.newsdir.is_directory_or_symlink_to_directory())
+ return;
+
+ std::set<std::string> skip;
+
+ if (_imp->skip_file.is_regular_file_or_symlink_to_regular_file())
+ {
+ Context local_context("When handling news skip file '" + stringify(
+ _imp->skip_file) + "':");
+ LineConfigFile s(_imp->skip_file, LineConfigFileOptions());
+ std::copy(s.begin(), s.end(), std::inserter(skip, skip.end()));
+ }
+
+ for (DirIterator d(_imp->params.newsdir), d_end ; d != d_end ; ++d)
+ {
+ Context local_context("When handling news entry '" + stringify(*d) + "':");
+
+ if (0 == stringify(_imp->e_repository->name()).compare(0, 2, "x-"))
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Cannot enable GLEP 42 news items for repository '"
+ + stringify(_imp->e_repository->name()) + "' because it is using a generated repository name");
+ return;
+ }
+
+ if (! d->is_directory_or_symlink_to_directory())
+ continue;
+ if (! (*d / (d->basename() + ".en.txt")).is_regular_file_or_symlink_to_regular_file())
+ continue;
+
+ if (skip.end() != skip.find(d->basename()))
+ continue;
+
+ try
+ {
+ NewsFile news(*d / (d->basename() + ".en.txt"));
+ bool show(true);
+
+ if (news.begin_display_if_installed() != news.end_display_if_installed())
+ {
+ bool local_show(false);
+ for (NewsFile::DisplayIfInstalledConstIterator i(news.begin_display_if_installed()),
+ i_end(news.end_display_if_installed()) ; i != i_end ; ++i)
+ if (! _imp->environment->package_database()->query(
+ query::Matches(PackageDepSpec(*i, pds_pm_permissive)) &
+ query::SupportsAction<InstalledAction>(),
+ qo_whatever)->empty())
+ local_show = true;
+ show &= local_show;
+ }
+
+ if (news.begin_display_if_keyword() != news.end_display_if_keyword())
+ {
+ bool local_show(false);
+ for (NewsFile::DisplayIfKeywordConstIterator i(news.begin_display_if_keyword()),
+ i_end(news.end_display_if_keyword()) ; i != i_end && ! local_show ; ++i)
+ if (*i == _imp->e_repository->profile_variable("ARCH"))
+ local_show = true;
+ show &= local_show;
+ }
+
+ if (news.begin_display_if_profile() != news.end_display_if_profile())
+ {
+ bool local_show(false);
+ tr1::shared_ptr<const FSEntrySequence> c(_imp->params.profiles);
+ for (FSEntrySequence::ConstIterator p(c->begin()), p_end(c->end()) ; p != p_end ; ++p)
+ {
+ std::string profile(strip_leading_string(strip_trailing_string(
+ strip_leading_string(stringify(p->realpath()),
+ stringify(p->realpath())), "/"), "/"));
+ Log::get_instance()->message(ll_debug, lc_no_context,
+ "Profile path is '" + profile + "'");
+ for (NewsFile::DisplayIfProfileConstIterator i(news.begin_display_if_profile()),
+ i_end(news.end_display_if_profile()) ; i != i_end ; ++i)
+ if (profile == *i)
+ local_show = true;
+ }
+ show &= local_show;
+ }
+
+ if (show)
+ {
+ std::ofstream s(stringify(_imp->skip_file).c_str(),
+ std::ios::out | std::ios::app);
+ if (! s)
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Cannot append to news skip file '"
+ + stringify(_imp->skip_file) +
+ "', skipping news item '" + stringify(*d) + "'");
+
+ std::ofstream t(stringify(_imp->unread_file).c_str(),
+ std::ios::out | std::ios::app);
+ if (! t)
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Cannot append to unread file '"
+ + stringify(_imp->unread_file) +
+ "', skipping news item '" + stringify(*d) + "'");
+
+ if (s && t)
+ {
+ s << d->basename() << std::endl;
+ t << d->basename() << std::endl;
+ }
+ }
+ }
+ catch (const Exception & e)
+ {
+ Log::get_instance()->message(ll_warning, lc_no_context,
+ "Skipping news item '"
+ + stringify(*d) + "' because of exception '" + e.message() + "' ("
+ + e.what() + ")");
+ }
+ }
+
+}
+
+namespace paludis
+{
+ /**
+ * Implementation data for NewsFile.
+ *
+ * \ingroup grpnewsconfigfile
+ */
+ template<>
+ struct Implementation<NewsFile>
+ {
+ std::list<std::string> display_if_installed;
+ std::list<std::string> display_if_keyword;
+ std::list<std::string> display_if_profile;
+ };
+}
+
+NewsFile::NewsFile(const FSEntry & our_filename) :
+ PrivateImplementationPattern<NewsFile>(new Implementation<NewsFile>)
+{
+ Context context("When parsing GLEP 42 news file '" + stringify(our_filename) + "':");
+
+ LineConfigFile line_file(our_filename, LineConfigFileOptions() + lcfo_disallow_continuations + lcfo_no_skip_blank_lines
+ + lcfo_disallow_comments);
+ for (LineConfigFile::ConstIterator line(line_file.begin()), line_end(line_file.end()) ;
+ line != line_end ; ++line)
+ {
+ if (line->empty())
+ break;
+
+ std::string::size_type p(line->find(':'));
+ if (std::string::npos == p)
+ {
+ Log::get_instance()->message(ll_warning, lc_context, "Bad header line '" + *line + "'");
+ break;
+ }
+ else
+ {
+ std::string k(strip_leading(strip_trailing(line->substr(0, p), " \t\n"), " \t\n"));
+ std::string v(strip_leading(strip_trailing(line->substr(p + 1), " \t\n"), " \t\n"));
+ if (k == "Display-If-Installed")
+ _imp->display_if_installed.push_back(v);
+ else if (k == "Display-If-Keyword")
+ _imp->display_if_keyword.push_back(v);
+ if (k == "Display-If-Profile")
+ _imp->display_if_profile.push_back(v);
+ }
+ }
+}
+
+NewsFile::~NewsFile()
+{
+}
+
+NewsFile::DisplayIfInstalledConstIterator
+NewsFile::begin_display_if_installed() const
+{
+ return DisplayIfInstalledConstIterator(_imp->display_if_installed.begin());
+}
+
+NewsFile::DisplayIfInstalledConstIterator
+NewsFile::end_display_if_installed() const
+{
+ return DisplayIfInstalledConstIterator(_imp->display_if_installed.end());
+}
+
+NewsFile::DisplayIfKeywordConstIterator
+NewsFile::begin_display_if_keyword() const
+{
+ return DisplayIfKeywordConstIterator(_imp->display_if_keyword.begin());
+}
+
+NewsFile::DisplayIfKeywordConstIterator
+NewsFile::end_display_if_keyword() const
+{
+ return DisplayIfKeywordConstIterator(_imp->display_if_keyword.end());
+}
+
+NewsFile::DisplayIfProfileConstIterator
+NewsFile::begin_display_if_profile() const
+{
+ return DisplayIfProfileConstIterator(_imp->display_if_profile.begin());
+}
+
+NewsFile::DisplayIfProfileConstIterator
+NewsFile::end_display_if_profile() const
+{
+ return DisplayIfProfileConstIterator(_imp->display_if_profile.end());
+}
+
+
diff --git a/0.26.0_alpha1/paludis/repositories/e/e_repository_news.hh b/0.26.0_alpha1/paludis/repositories/e/e_repository_news.hh
new file mode 100644
index 000000000..7ec8d4139
--- /dev/null
+++ b/0.26.0_alpha1/paludis/repositories/e/e_repository_news.hh
@@ -0,0 +1,131 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaran.mccreesh@blueyonder.co.uk>
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License 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
+ * deta