/* 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"install.hh"#include<src/output/colour.hh>#include<src/output/console_install_task.hh>#include<src/output/licence.hh>#include<iostream>#include<limits>#include<set>#include<signal.h>#include<sys/types.h>#include<sys/wait.h>#include<paludis/tasks/install_task.hh>#include<paludis/util/fd_output_stream.hh>#include<paludis/util/log.hh>#include<paludis/util/tokeniser.hh>#include<paludis/environment.hh>#include<paludis/dep_list/exceptions.hh>#include<paludis/query.hh>/** \file * Handle the --install action for the contrarius program. */usingnamespacepaludis;usingstd::cerr;usingstd::cout;usingstd::endl;namespace{classOurInstallTask:publicConsoleInstallTask{public:OurInstallTask(std::tr1::shared_ptr<Environment>env,constDepListOptions&options):ConsoleInstallTask(env.get(),options,env->default_destinations()){}virtualboolwant_full_install_reasons()const{return"full"==CommandLine::get_instance()->a_show_reasons.argument();}virtualboolwant_tags_summary()const{returnCommandLine::get_instance()->a_pretend.specified();}virtualboolwant_install_reasons()const{return"full"==CommandLine::get_instance()->a_show_reasons.argument()||"summary"==CommandLine::get_instance()->a_show_reasons.argument();}virtualboolwant_unchanged_use_flags()const{returnfalse;}virtualboolwant_changed_use_flags()const{returnfalse;}virtualboolwant_new_use_flags()const{returnfalse;}virtualboolwant_use_summary()const{returnfalse;}};voidshow_resume_command(std::tr1::shared_ptr<Environment>env,constInstallTask&task){if(CommandLine::get_instance()->a_fetch.specified()||CommandLine::get_instance()->a_pretend.specified())return;if(task.current_dep_list_entry()!=task.dep_list().end()){std::stringresume_command=env->paludis_command()+" ""--dl-installed-deps-pre discard ""--dl-installed-deps-runtime discard ""--dl-installed-deps-post discard ""--dl-uninstalled-deps-pre discard ""--dl-uninstalled-deps-runtime discard ""--dl-uninstalled-deps-post discard ""--install --preserve-world";for(DepList::Iteratori(task.current_dep_list_entry()),i_end(task.dep_list().end());i!=i_end;++i)if(dlk_package==i->kind)resume_command=resume_command+" ="+stringify(i->package.name)+"-"+stringify(i->package.version)+"::"+stringify(i->package.repository);if(CommandLine::get_instance()->a_resume_command_template.specified()){std::stringfile_name(CommandLine::get_instance()->a_resume_command_template.argument());char*resume_template=strdup(file_name.c_str());FDOutputStreamresume_command_file(mkstemp(resume_template));cerr<<endl;cerr<<"Resume command saved to file: "<<resume_template;cerr<<endl;resume_command_file<<resume_command<<endl;std::free(resume_template);}elsecerr<<"Resume command: "<<resume_command<<endl;}}classInstallKilledCatcher{private:staticconstInstallTask*_task;staticstd::tr1::shared_ptr<Environment>_env;staticvoid_signal_handler(intsig)PALUDIS_ATTRIBUTE((noreturn));sig_t_old;public:InstallKilledCatcher(std::tr1::shared_ptr<Environment>env,constInstallTask&task):_old(signal(SIGINT,&InstallKilledCatcher::_signal_handler)){_task=&task;_env=env;}~InstallKilledCatcher(){signal(SIGINT,_old);_task=0;}};constInstallTask*InstallKilledCatcher::_task(0);std::tr1::shared_ptr<Environment>InstallKilledCatcher::_env;voidInstallKilledCatcher::_signal_handler(intsig){// ignore further signals to avoid a race if// a sigal arrives while this handler hasn't finishedsignal(sig,SIG_IGN);staticboolrecursing(false);if(recursing){cout<<endl;cerr<<"Caught signal "<<sig<<" inside signal"<<endl;cerr<<"NOT waiting for children any more..."<<endl;cerr<<endl;cerr<<"Exiting with failure"<<endl;exit(EXIT_FAILURE);}else{recursing=true;cout<<endl;cerr<<"Caught signal "<<sig<<endl;cerr<<"Waiting for children..."<<endl;while(-1!=wait(0));cerr<<endl;if(_task)show_resume_command(_env,*_task);cerr<<endl;cerr<<"Exiting with failure"<<endl;exit(EXIT_FAILURE);}}}intdo_install(std::tr1::shared_ptr<Environment>env,std::tr1::shared_ptr<constPackageDepSpec>spec){intreturn_code(0);Contextcontext("When performing install action from command line:");DepListOptionsoptions;options.circular=dl_circular_discard;options.circular=dl_circular_error;options.installed_deps_pre=dl_deps_discard;options.installed_deps_runtime=dl_deps_discard;options.installed_deps_post=dl_deps_discard;options.uninstalled_deps_pre=dl_deps_discard;options.uninstalled_deps_runtime=dl_deps_discard;options.uninstalled_deps_post=dl_deps_discard;options.reinstall=dl_reinstall_never;options.target_type=dl_target_set;OurInstallTasktask(env,options);task.set_fetch_only(CommandLine::get_instance()->a_fetch.specified());task.set_pretend(CommandLine::get_instance()->a_pretend.specified());if(CommandLine::get_instance()->a_debug_build.specified()){if(CommandLine::get_instance()->a_debug_build.argument()=="none")task.set_debug_mode(ido_none);elseif(CommandLine::get_instance()->a_debug_build.argument()=="split")task.set_debug_mode(ido_split);elseif(CommandLine::get_instance()->a_debug_build.argument()=="internal")task.set_debug_mode(ido_internal);elsethrowDoHelp("bad value for --debug-build");}try{task.add_target(stringify(*spec));task.execute();cout<<endl;if(task.dep_list().has_errors())return_code|=1;}catch(constAmbiguousPackageNameError&e){cout<<endl;cerr<<"Query error:"<<endl;cerr<<" * "<<e.backtrace("\n * ");cerr<<"Ambiguous package name '"<<e.name()<<"'. Did you mean:"<<endl;for(AmbiguousPackageNameError::OptionsIteratoro(e.begin_options()),o_end(e.end_options());o!=o_end;++o)cerr<<" * "<<colour(cl_package_name,*o)<<endl;cerr<<endl;return1;}catch(constPackageInstallActionError&e){cout<<endl;cerr<<"Install error:"<<endl;cerr<<" * "<<e.backtrace("\n * ");cerr<<e.message()<<endl;cerr<<endl;return_code|=1;}catch(constPackageFetchActionError&e){cout<<endl;cerr<<"Fetch error:"<<endl;cerr<<" * "<<e.backtrace("\n * ");cerr<<e.message()<<endl;cerr<<endl;return_code|=1;}catch(constNoSuchPackageError&e){cout<<endl;cerr<<"Query error:"<<endl;cerr<<" * "<<e.backtrace("\n * ");cerr<<"No such package '"<<e.name()<<"'"<<endl;return1;}catch(constAllMaskedError&e){try{std::tr1::shared_ptr<constPackageDatabaseEntryCollection>p(env->package_database()->query(query::Matches(PackageDepSpec(e.query()))&query::RepositoryHasUninstallableInterface(),qo_order_by_version));if(p->empty()){cout<<endl;cerr<<"Query error:"<<endl;cerr<<" * "<<e.backtrace("\n * ");cerr<<"All versions of '"<<e.query()<<"' are masked"<<endl;}else{cout<<endl;cerr<<"Query error:"<<endl;cerr<<" * "<<e.backtrace("\n * ");cerr<<"All versions of '"<<e.query()<<"' are masked. Candidates are:"<<endl;for(PackageDatabaseEntryCollection::Iteratorpp(p->begin()),pp_end(p->end());pp!=pp_end;++pp){cerr<<" * "<<colour(cl_package_name,*pp)<<": Masked by ";boolneed_comma(false);MaskReasonsm(env->mask_reasons(*pp));for(unsignedmm=0;mm<m.size();++mm)if(m[mm]){if(need_comma)cerr<<", ";cerr<<MaskReason(mm);if(mr_eapi==mm){std::stringeapi_str(env->package_database()->fetch_repository(pp->repository)->version_metadata(pp->name,pp->version)->eapi);cerr<<" ( "<<colour(cl_masked,eapi_str)<<" )";}elseif(mr_license==mm){std::tr1::shared_ptr<constVersionMetadata>meta(env->package_database()->fetch_repository(pp->repository)->version_metadata(pp->name,pp->version));if(meta->license_interface){cerr<<" ";LicenceDisplayerld(cerr,env.get(),&*pp);meta->license_interface->license()->accept(&ld);}}elseif(mr_keyword==mm){std::tr1::shared_ptr<constVersionMetadata>meta(env->package_database()->fetch_repository(pp->repository)->version_metadata(pp->name,pp->version));if(meta->ebuild_interface){std::set<KeywordName>keywords;WhitespaceTokeniser::get_instance()->tokenise(meta->ebuild_interface->keywords,create_inserter<KeywordName>(std::inserter(keywords,keywords.end())));cerr<<" ( "<<colour(cl_masked,join(keywords.begin(),keywords.end()," "))<<" )";}}need_comma=true;}cerr<<endl;}}}catch(...){throwe;}return1;}catch(constUseRequirementsNotMetError&e){cout<<endl;cerr<<"DepList USE requirements not met error:"<<endl;cerr<<" * "<<e.backtrace("\n * ")<<e.message()<<endl;cerr<<endl;cerr<<"This error usually indicates that one of the packages you are trying to"<<endl;cerr<<"install requires that another package be built with particular USE flags"<<endl;cerr<<"enabled or disabled. You may be able to work around this restriction by"<<endl;cerr<<"adjusting your use.conf."<<endl;cerr<<endl;return_code|=1;}catch(constDepListError&e){cout<<endl;cerr<<"Dependency error:"<<endl;cerr<<" * "<<e.backtrace("\n * ")<<e.message()<<" ("<<e.what()<<")"<<endl;cerr<<endl;return_code|=1;}returnreturn_code;}