aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMu Qiao <qiaomuf@gentoo.org>2011-05-05 14:53:14 +0800
committerMu Qiao <qiaomuf@gentoo.org>2011-05-08 20:55:51 +0800
commit7f6c20a9ef87ec5377f0d7758f7cdce20da11831 (patch)
tree852ca2a7fc9378608d25ed7a6ebe1c0b1fdd9630
parentCore: return 0 if boost::lexical_cast<int> fails (diff)
downloadlibbash-7f6c20a9ef87ec5377f0d7758f7cdce20da11831.tar.gz
libbash-7f6c20a9ef87ec5377f0d7758f7cdce20da11831.tar.bz2
libbash-7f6c20a9ef87ec5377f0d7758f7cdce20da11831.zip
Utils: reimplement instruo with libbash
With the help of instruo from Paludis, we can setup variables to bash env needed for metadata generation. In the meanwhile, we can compare the original instruo utility with our implementation.
-rw-r--r--.gitignore2
-rw-r--r--Makefile.am15
-rw-r--r--configure.ac2
-rw-r--r--src/libbash.cpp5
-rw-r--r--src/libbash.h3
-rw-r--r--utils/command_line.cpp88
-rw-r--r--utils/command_line.h62
-rw-r--r--utils/instruo.cpp251
-rw-r--r--utils/metadata.cpp113
-rw-r--r--utils/metadata.h31
-rw-r--r--utils/metadata_generator.cpp84
11 files changed, 571 insertions, 85 deletions
diff --git a/.gitignore b/.gitignore
index 10b4131..79e3a80 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
*.swo
*.o
*.la
+*.a
*.lo
*.log
*.class
@@ -21,6 +22,7 @@ cppunittests
variable_printer
metadata_generator
ast_printer
+instruo
long.sh
massif.out
libbash.g
diff --git a/Makefile.am b/Makefile.am
index a3890bb..95beba6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -113,13 +113,24 @@ cppunittests_LDFLAGS = -static
endif
-noinst_PROGRAMS = variable_printer metadata_generator ast_printer
+noinst_LIBRARIES = libmetadata.a
+
+libmetadata_a_SOURCES = utils/metadata.h utils/metadata.cpp
+libmetadata_a_CPPFLAGS = $(AM_CPPFLAGS) -Iutils
+
+noinst_PROGRAMS = variable_printer metadata_generator ast_printer instruo
variable_printer_SOURCES = utils/variable_printer.cpp
variable_printer_LDADD = libcppbash.la
metadata_generator_SOURCES = utils/metadata_generator.cpp
-metadata_generator_LDADD = libcppbash.la
+metadata_generator_LDADD = libcppbash.la libmetadata.a
+metadata_generator_CPPFLAGS = $(AM_CPPFLAGS) -Iutils
+
+instruo_SOURCES = utils/instruo.cpp utils/command_line.cpp utils/command_line.h
+instruo_LDADD = libcppbash.la @PALUDIS_LIBS@ libmetadata.a
+instruo_CPPFLAGS = $(AM_CPPFLAGS) @PALUDIS_CFLAGS@ -Iutils
+instruo_CXXFLAGS = $(AM_CXXFLAGS) -Wno-extra
ast_printer_SOURCES = utils/ast_printer.cpp
ast_printer_LDADD = libcppbash.la $(BOOST_PROGRAM_OPTIONS_LIB)
diff --git a/configure.ac b/configure.ac
index b710a97..3563013 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,6 +29,8 @@ AC_ARG_ENABLE([developer],
[AS_HELP_STRING([--enable-developer],[enables various QA checks])])
AM_CONDITIONAL([DEVELOPER_MODE],[test "x$enable_developer" = xyes])
+PKG_CHECK_MODULES([PALUDIS], [paludis])
+
AS_IF([test "x$enable_developer" = xyes],[boost_version="1.46.1"],[boost_version="1.43.0"])
AX_BOOST_BASE([$boost_version],[:],
[AC_MSG_ERROR([Needed boost not found])])
diff --git a/src/libbash.cpp b/src/libbash.cpp
index 4fb4102..f04064d 100644
--- a/src/libbash.cpp
+++ b/src/libbash.cpp
@@ -39,6 +39,11 @@ namespace libbash
if(!input)
throw interpreter_exception("Unable to create fstream for script: " + path);
interpreter walker;
+
+ // Initialize bash environment
+ for(auto iter = variables.begin(); iter != variables.end(); ++iter)
+ walker.set_value(iter->first, (iter->second)[0]);
+
bash_ast ast(input);
ast.interpret_with(walker);
diff --git a/src/libbash.h b/src/libbash.h
index ca8cdaa..3f903e9 100644
--- a/src/libbash.h
+++ b/src/libbash.h
@@ -39,7 +39,8 @@ namespace libbash
/// \brief interpret a script specifid by path, return a map filled with
/// variables defined in the script
/// \param the path of target script
- /// \param the map to store variables
+ /// \param[in, out] we use the map to initialize bash environment and store the result
+ /// \param[out] store the names of the functions defined in the script
void LIBBASH_API interpret(const std::string& path,
std::unordered_map<std::string, std::vector<std::string>>& variables,
std::vector<std::string>& functions);
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;
}