diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/command_line.cpp | 88 | ||||
-rw-r--r-- | utils/command_line.h | 62 | ||||
-rw-r--r-- | utils/instruo.cpp | 251 | ||||
-rw-r--r-- | utils/metadata.cpp | 113 | ||||
-rw-r--r-- | utils/metadata.h | 31 | ||||
-rw-r--r-- | utils/metadata_generator.cpp | 84 |
6 files changed, 547 insertions, 82 deletions
diff --git a/utils/command_line.cpp b/utils/command_line.cpp new file mode 100644 index 0000000..8d238b4 --- /dev/null +++ b/utils/command_line.cpp @@ -0,0 +1,88 @@ +/* This file was copied from Paludis src/clients/instruo/command_line.cc that is licensed as follows: */ + +/* + * Copyright (c) 2007, 2008, 2009, 2010 Ciaran McCreesh + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "command_line.h" +#include <paludis/util/singleton-impl.hh> + +using namespace paludis; + +template class paludis::Singleton<CommandLine>; + +CommandLine::CommandLine() : + ArgsHandler(), + + action_args(main_options_section(), "Actions", + "Selects which basic action to perform. Exactly one action should " + "be specified."), + a_generate_cache(&action_args, "generate-cache", 'g', "Generate cache", false), + a_version(&action_args, "version", 'V', "Display program version", false), + a_help(&action_args, "help", 'h', "Display program help", false), + + general_args(main_options_section(), "General options", + "Options which are relevant for most or all actions."), + a_log_level(&general_args, "log-level", '\0'), + a_no_colour(&general_args, "no-colour", '\0', "Do not use colour", false), + a_no_color(&a_no_colour, "no-color"), + a_force_colour(&general_args, "force-colour", '\0', "Force the use of colour", false), + a_force_color(&a_force_colour, "force-color"), + a_repository_directory(&general_args, "repository-dir", 'D', + "Where to find the repository (default: current directory)"), + a_output_directory(&general_args, "output-dir", 'o', + "Where to place generated metadata (default: current directory)"), + a_master_repository_name(&general_args, "master-repository-name", '\0', + "Use the specified name for the master repository. Specify the location using --extra-repository-dir. " + "Only for repositories with no metadata/layout.conf."), + a_extra_repository_dir(&general_args, "extra-repository-dir", '\0', + "Also include the repository at this location. May be specified multiple times, in creation order."), + a_report_file(&general_args, "report-file", 'r', + "Write report to the specified file, rather than stdout") +{ + add_usage_line("--generate-cache [ at least one of --repository-dir /dir or --output-dir /dir ]"); + + add_description_line("instruo is configured purely from the command line. It does not use any user " + "configuration files."); + + add_environment_variable("INSTRUO_OPTIONS", "Default command-line options."); + add_environment_variable("INSTRUO_THREADS", "Number of threads to use. Default: 5"); +} + +std::string +CommandLine::app_name() const +{ + return "instruo"; +} + +std::string +CommandLine::app_synopsis() const +{ + return "Metadata generation client for Paludis"; +} + +std::string +CommandLine::app_description() const +{ + return + "instruo is a metadata generation client for Paludis. It generates metadata cache for every ID in a " + "given repository and produces a report of any failures."; +} + +CommandLine::~CommandLine() +{ +} + diff --git a/utils/command_line.h b/utils/command_line.h new file mode 100644 index 0000000..2fdb10b --- /dev/null +++ b/utils/command_line.h @@ -0,0 +1,62 @@ +/* This file was copied from Paludis src/clients/instruo/command_line.hh that is licensed as follows: */ + +/* + * Copyright (c) 2007, 2008, 2010 Ciaran McCreesh + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PALUDIS_GUARD_SRC_CLIENTS_INSTRUO_COMMAND_LINE_HH +#define PALUDIS_GUARD_SRC_CLIENTS_INSTRUO_COMMAND_LINE_HH 1 + +#include <paludis/args/args.hh> +#include <paludis/util/singleton.hh> +#include <paludis/args/log_level_arg.hh> + +class CommandLine : + public paludis::args::ArgsHandler, + public paludis::Singleton<CommandLine> +{ + friend class paludis::Singleton<CommandLine>; + + private: + CommandLine(); + ~CommandLine(); + + public: + virtual std::string app_name() const; + virtual std::string app_synopsis() const; + virtual std::string app_description() const; + + paludis::args::ArgsGroup action_args; + + paludis::args::SwitchArg a_generate_cache; + paludis::args::SwitchArg a_version; + paludis::args::SwitchArg a_help; + + paludis::args::ArgsGroup general_args; + + paludis::args::LogLevelArg a_log_level; + paludis::args::SwitchArg a_no_colour; + paludis::args::AliasArg a_no_color; + paludis::args::SwitchArg a_force_colour; + paludis::args::AliasArg a_force_color; + paludis::args::StringArg a_repository_directory; + paludis::args::StringArg a_output_directory; + paludis::args::StringArg a_master_repository_name; + paludis::args::StringSequenceArg a_extra_repository_dir; + paludis::args::StringArg a_report_file; +}; + +#endif diff --git a/utils/instruo.cpp b/utils/instruo.cpp new file mode 100644 index 0000000..bd1c981 --- /dev/null +++ b/utils/instruo.cpp @@ -0,0 +1,251 @@ +/* This file was partly copied from Paludis src/clients/instruo/instruo.cc. + * The metadata generation logic is reimplemented with libbash. This file is + * licensed as follows: */ + +/* + * Copyright (c) 2007, 2008, 2009, 2010 Ciaran McCreesh + * + * This file is part of the Paludis package manager. Paludis is free software; + * you can redistribute it and/or modify it under the terms of the GNU General + * Public License version 2, as published by the Free Software Foundation. + * + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <algorithm> +#include <fstream> +#include <functional> +#include <iostream> +#include <map> + +#include <paludis/args/do_help.hh> +#include <paludis/about.hh> +#include <paludis/action.hh> +#include <paludis/package_id.hh> +#include <paludis/generator.hh> +#include <paludis/filter.hh> +#include <paludis/filtered_generator.hh> +#include <paludis/selection.hh> +#include <paludis/util/system.hh> +#include <paludis/util/join.hh> +#include <paludis/util/log.hh> +#include <paludis/util/sequence.hh> +#include <paludis/util/map.hh> +#include <paludis/util/visitor_cast.hh> +#include <paludis/util/set.hh> +#include <paludis/util/make_named_values.hh> +#include <paludis/util/mutex.hh> +#include <paludis/util/thread_pool.hh> +#include <paludis/util/destringify.hh> +#include <paludis/util/safe_ofstream.hh> +#include <paludis/util/pretty_print.hh> +#include <paludis/util/indirect_iterator-impl.hh> +#include <paludis/util/timestamp.hh> +#include <paludis/util/accept_visitor.hh> +#include <paludis/environments/no_config/no_config_environment.hh> +#include <paludis/package_database.hh> +#include <paludis/metadata_key.hh> + +#include "command_line.h" +#include "libbash.h" +#include "utils/metadata.h" + +using namespace paludis; +using std::cout; +using std::cerr; +using std::endl; + +void worker(const std::shared_ptr<PackageIDSequence> &ids) +{ + std::unordered_map<std::string, std::vector<std::string>> variables; + + std::shared_ptr<const PackageID> id; + unsigned total(0); + CategoryNamePart old_cat("OLDCAT"); + while(!ids->empty()) + { + id = *ids->begin(); + ids->pop_front(); + if (id->name().category() != old_cat) + { + std::cout << "Processing " << stringify(id->name().category()) << "..." << std::endl; + old_cat = id->name().category(); + FSPath(CommandLine::get_instance()->a_output_directory.argument() + "/" + + stringify(id->name().category())).mkdir(0755, {fspmkdo_ok_if_exists}); + ++total; + } + + Context i_context("When generating metadata for ID '" + stringify(*id) + "':"); + + variables.clear(); + variables["PN"].push_back(stringify(id->name().package())); + variables["PV"].push_back(stringify(id->version().remove_revision())); + variables["P"].push_back(stringify(id->name().package()) + "-" + + stringify(id->version().remove_revision())); + variables["PR"].push_back(id->version().revision_only()); + variables["PVR"].push_back(stringify(id->version())); + variables["PF"].push_back(stringify(id->name().package()) + "-" + stringify(id->version())); + variables["CATEGORY"].push_back(stringify(id->name().category())); + std::vector<std::string> functions; + + std::string ebuild_path(CommandLine::get_instance()->a_repository_directory.argument() + + variables["CATEGORY"][0] + "/" + + variables["PN"][0] + "/" + + variables["PN"][0] + "-" + + variables["PVR"][0] + ".ebuild"); + try + { + libbash::interpret(ebuild_path, variables, functions); + } + catch(const interpreter_exception& e) + { + cerr << "Exception occurred while interpreting " << ebuild_path << ". The error message is:\n" + << e.what() << endl; + continue; + } + + std::string output_path(CommandLine::get_instance()->a_output_directory.argument() + "/" + + variables["CATEGORY"][0] + "/" + + variables["PN"][0] + "-" + + variables["PVR"][0]); + FSPath(output_path).dirname().mkdir(0755, {fspmkdo_ok_if_exists}); + std::ofstream output(output_path, std::ofstream::out | std::ofstream::trunc); + write_metadata(output, variables, functions); + } +} + +int main(int argc, char** argv) +{ + try + { + std::string options(paludis::getenv_with_default("INSTRUO_OPTIONS", "")); + if (! options.empty()) + options = "(" + options + ") "; + options += join(argv + 1, argv + argc, " "); + + Context context(std::string("In program ") + argv[0] + " " + options + ":"); + + CommandLine::get_instance()->run(argc, argv, "instruo", "INSTRUO_OPTIONS", "INSTRUO_CMDLINE"); + + if (CommandLine::get_instance()->a_help.specified()) + throw args::DoHelp(); + + if (CommandLine::get_instance()->a_log_level.specified()) + Log::get_instance()->set_log_level(CommandLine::get_instance()->a_log_level.option()); + else + Log::get_instance()->set_log_level(ll_qa); + + if (1 < ( + CommandLine::get_instance()->a_generate_cache.specified() + + CommandLine::get_instance()->a_version.specified() + )) + throw args::DoHelp("you should specify exactly one action"); + + if (! CommandLine::get_instance()->a_repository_directory.specified()) + CommandLine::get_instance()->a_repository_directory.set_argument(stringify(FSPath::cwd())); + + if (CommandLine::get_instance()->a_version.specified()) + { + cout << "instruo, part of " << PALUDIS_PACKAGE << " " << PALUDIS_VERSION_MAJOR << "." + << PALUDIS_VERSION_MINOR << "." << PALUDIS_VERSION_MICRO << PALUDIS_VERSION_SUFFIX; + if (! std::string(PALUDIS_GIT_HEAD).empty()) + cout << " git " << PALUDIS_GIT_HEAD; + cout << endl << endl; + cout << "Paludis comes with ABSOLUTELY NO WARRANTY. Paludis is free software, and you" << endl; + cout << "are welcome to redistribute it under the terms of the GNU General Public" << endl; + cout << "License, version 2." << endl; + + return EXIT_SUCCESS; + } + + if (( + CommandLine::get_instance()->a_repository_directory.specified() + + CommandLine::get_instance()->a_output_directory.specified() + ) < 1) + throw args::DoHelp("at least one of '--" + CommandLine::get_instance()->a_repository_directory.long_name() + "' or '--" + + CommandLine::get_instance()->a_output_directory.long_name() + "' must be specified"); + + if (! CommandLine::get_instance()->a_output_directory.specified()) + CommandLine::get_instance()->a_output_directory.set_argument(stringify(FSPath::cwd())); + + std::shared_ptr<FSPathSequence> extra_repository_dirs(std::make_shared<FSPathSequence>()); + for (args::StringSequenceArg::ConstIterator d(CommandLine::get_instance()->a_extra_repository_dir.begin_args()), + d_end(CommandLine::get_instance()->a_extra_repository_dir.end_args()) ; + d != d_end ; ++d) + extra_repository_dirs->push_back(FSPath(*d)); + + std::shared_ptr<Map<std::string, std::string> > keys(std::make_shared<Map<std::string, std::string>>()); + keys->insert("append_repository_name_to_write_cache", "false"); + NoConfigEnvironment env(make_named_values<no_config_environment::Params>( + n::accept_unstable() = true, + n::disable_metadata_cache() = true, + n::extra_accept_keywords() = "", + n::extra_params() = keys, + n::extra_repository_dirs() = extra_repository_dirs, + n::master_repository_name() = CommandLine::get_instance()->a_master_repository_name.argument(), + n::profiles_if_not_auto() = "", + n::repository_dir() = CommandLine::get_instance()->a_repository_directory.argument(), + n::repository_type() = no_config_environment::ncer_ebuild, + n::write_cache() = CommandLine::get_instance()->a_output_directory.argument() + )); + + FSPath(CommandLine::get_instance()->a_output_directory.argument()).mkdir(0755, {fspmkdo_ok_if_exists}); + + std::shared_ptr<PackageIDSequence> ids(env[selection::AllVersionsSorted( + generator::InRepository(env.main_repository()->name()))]); + worker(ids); + } + catch (const paludis::args::ArgsError & e) + { + cerr << "Usage error: " << e.message() << endl; + cerr << "Try " << argv[0] << " --help" << endl; + return EXIT_FAILURE; + } + catch (const args::DoHelp & h) + { + if (h.message.empty()) + { + cout << "Usage: " << argv[0] << " [options]" << endl; + cout << endl; + cout << *CommandLine::get_instance(); + return EXIT_SUCCESS; + } + else + { + cerr << "Usage error: " << h.message << endl; + cerr << "Try " << argv[0] << " --help" << endl; + return EXIT_FAILURE; + } + } + catch (const Exception & e) + { + cout << endl; + cerr << "Unhandled exception:" << endl + << " * " << e.backtrace("\n * ") + << e.message() << " (" << e.what() << ")" << endl; + return EXIT_FAILURE; + } + catch (const std::exception & e) + { + cout << endl; + cerr << "Unhandled exception:" << endl + << " * " << e.what() << endl; + return EXIT_FAILURE; + } + catch (...) + { + cout << endl; + cerr << "Unhandled exception:" << endl + << " * Unknown exception type. Ouch..." << endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/utils/metadata.cpp b/utils/metadata.cpp new file mode 100644 index 0000000..600f9e4 --- /dev/null +++ b/utils/metadata.cpp @@ -0,0 +1,113 @@ +/* + Please use git log for copyright holder and year information + + This file is part of libbash. + + libbash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + libbash 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 libbash. If not, see <http://www.gnu.org/licenses/>. + */ +/// +/// \file metadata.cpp +/// \author Mu Qiao +/// \brief a helper for printing metadata content +/// +#include <set> + +#include <boost/spirit/include/karma.hpp> +#include <boost/algorithm/string/classification.hpp> +#include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/trim.hpp> + +#include "utils/metadata.h" + +static const std::vector<std::string> metadata_names = {"DEPEND", "RDEPEND", "SLOT", "SRC_URI", + "RESTRICT", "HOMEPAGE", "LICENSE", "DESCRIPTION", + "KEYWORDS", "INHERITED", "IUSE", "REQUIRED_USE", + "PDEPEND", "PROVIDE", "EAPI", "PROPERTIES"}; + +static const std::unordered_map<std::string, std::string> phases = { + {"pkg_pretend", "ppretend"}, + {"pkg_setup", "setup"}, + {"src_unpack", "unpack"}, + {"src_prepare", "prepare"}, + {"src_configure", "configure"}, + {"src_compile", "compile"}, + {"src_test", "test"}, + {"src_install", "install"}, + {"pkg_preinst", "preinst"}, + {"pkg_postinst", "postinst"}, + {"pkg_prerm", "prerm"}, + {"pkg_postrm", "postrm"}, + {"pkg_config", "config"}, + {"pkg_info", "info"}, + {"pkg_nofetch", "nofetch"} +}; + +void write_metadata(std::ostream& output, + std::unordered_map<std::string, std::vector<std::string>>& variables, + std::vector<std::string>& functions) +{ + for(auto iter_name = metadata_names.begin(); iter_name != metadata_names.end(); ++iter_name) + { + auto iter_value = variables.find(*iter_name); + std::string value; + + if(iter_value != variables.end()) + value = iter_value->second[0]; + + // Check if global is defined + auto iter_global = variables.find("E_" + *iter_name); + if(iter_global != variables.end()) + { + boost::trim_if(iter_global->second[0], boost::is_any_of(" \t\n")); + std::vector<std::string> splitted_global; + boost::split(splitted_global, + iter_global->second[0], + boost::is_any_of(" \t\n"), + boost::token_compress_on); + + // Append the global value to 'value' if it doesn't cause duplication + for(auto iter_splitted_global = splitted_global.begin(); + iter_splitted_global != splitted_global.end(); + ++iter_splitted_global) + { + if(value.find(*iter_splitted_global) == std::string::npos) + value += " " + *iter_splitted_global; + } + } + + boost::trim_if(value, boost::is_any_of(" \t\n")); + + std::vector<std::string> splitted_value; + boost::split(splitted_value, + value, + boost::is_any_of(" \t\n"), + boost::token_compress_on); + using namespace boost::spirit::karma; + output << format(string % ' ', splitted_value) << std::endl; + } + + // Print defined phases + std::set<std::string> sorted_phases; + for(auto iter = functions.begin(); iter != functions.end(); ++iter) + { + auto iter_phase = phases.find(*iter); + if(iter_phase != phases.end()) + sorted_phases.insert(iter_phase->second); + } + using namespace boost::spirit::karma; + output << format(string % ' ', sorted_phases) << std::endl; + + // Print empty lines + output << std::endl << std::endl << std::endl << std::endl << std::endl; +} diff --git a/utils/metadata.h b/utils/metadata.h new file mode 100644 index 0000000..cb7f559 --- /dev/null +++ b/utils/metadata.h @@ -0,0 +1,31 @@ +/* + Please use git log for copyright holder and year information + + This file is part of libbash. + + libbash is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + libbash 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 libbash. If not, see <http://www.gnu.org/licenses/>. + */ +/// +/// \file metadata.h +/// \author Mu Qiao +/// \brief a helper for printing metadata content +/// +#include <iostream> +#include <string> +#include <unordered_map> +#include <vector> + +void write_metadata(std::ostream& output, + std::unordered_map<std::string, std::vector<std::string>>& variables, + std::vector<std::string>& functions); diff --git a/utils/metadata_generator.cpp b/utils/metadata_generator.cpp index 52b4590..14602f2 100644 --- a/utils/metadata_generator.cpp +++ b/utils/metadata_generator.cpp @@ -22,44 +22,14 @@ /// \brief a simple utility for generating metadata /// #include <iostream> -#include <set> #include <string> #include <vector> -#include <boost/spirit/include/karma.hpp> -#include <boost/algorithm/string/classification.hpp> -#include <boost/algorithm/string/split.hpp> -#include <boost/algorithm/string/trim.hpp> - #include "libbash.h" - -static const std::vector<std::string> metadata_names = {"DEPEND", "RDEPEND", "SLOT", "SRC_URI", - "RESTRICT", "HOMEPAGE", "LICENSE", "DESCRIPTION", - "KEYWORDS", "INHERITED", "IUSE", "REQUIRED_USE", - "PDEPEND", "PROVIDE", "EAPI", "PROPERTIES"}; - -static const std::unordered_map<std::string, std::string> phases = { - {"pkg_pretend", "ppretend"}, - {"pkg_setup", "setup"}, - {"src_unpack", "unpack"}, - {"src_prepare", "prepare"}, - {"src_configure", "configure"}, - {"src_compile", "compile"}, - {"src_test", "test"}, - {"src_install", "install"}, - {"pkg_preinst", "preinst"}, - {"pkg_postinst", "postinst"}, - {"pkg_prerm", "prerm"}, - {"pkg_postrm", "postrm"}, - {"pkg_config", "config"}, - {"pkg_info", "info"}, - {"pkg_nofetch", "nofetch"} -}; +#include "utils/metadata.h" int main(int argc, char** argv) { - using namespace boost::spirit::karma; - if(argc != 2) { std::cerr<<"Please provide your script as an argument"<<std::endl; @@ -70,57 +40,7 @@ int main(int argc, char** argv) std::vector<std::string> functions; libbash::interpret(argv[1], variables, functions); - for(auto iter_name = metadata_names.begin(); iter_name != metadata_names.end(); ++iter_name) - { - auto iter_value = variables.find(*iter_name); - std::string value; - - if(iter_value != variables.end()) - value = iter_value->second[0]; - - // Check if global is defined - auto iter_global = variables.find("E_" + *iter_name); - if(iter_global != variables.end()) - { - boost::trim_if(iter_global->second[0], boost::is_any_of(" \t\n")); - std::vector<std::string> splitted_global; - boost::split(splitted_global, - iter_global->second[0], - boost::is_any_of(" \t\n"), - boost::token_compress_on); - - // Append the global value to 'value' if it doesn't cause duplication - for(auto iter_splitted_global = splitted_global.begin(); - iter_splitted_global != splitted_global.end(); - ++iter_splitted_global) - { - if(value.find(*iter_splitted_global) == std::string::npos) - value += " " + *iter_splitted_global; - } - } - - boost::trim_if(value, boost::is_any_of(" \t\n")); - - std::vector<std::string> splitted_value; - boost::split(splitted_value, - value, - boost::is_any_of(" \t\n"), - boost::token_compress_on); - std::cout << format(string % ' ', splitted_value) << std::endl; - } - - // Print defined phases - std::set<std::string> sorted_phases; - for(auto iter = functions.begin(); iter != functions.end(); ++iter) - { - auto iter_phase = phases.find(*iter); - if(iter_phase != phases.end()) - sorted_phases.insert(iter_phase->second); - } - std::cout << format(string % ' ', sorted_phases) << std::endl; - - // Print empty lines - std::cout << std::endl << std::endl << std::endl << std::endl << std::endl; + write_metadata(std::cout, variables, functions); return EXIT_SUCCESS; } |