Gentoo Archives: gentoo-commits

From: "Petteri Räty" <betelgeuse@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/libbash:master commit in: src/, /, utils/
Date: Sun, 08 May 2011 13:08:13
Message-Id: 7f6c20a9ef87ec5377f0d7758f7cdce20da11831.betelgeuse@gentoo
1 commit: 7f6c20a9ef87ec5377f0d7758f7cdce20da11831
2 Author: Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
3 AuthorDate: Thu May 5 06:53:14 2011 +0000
4 Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
5 CommitDate: Sun May 8 12:55:51 2011 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=7f6c20a9
7
8 Utils: reimplement instruo with libbash
9
10 With the help of instruo from Paludis, we can setup variables to
11 bash env needed for metadata generation. In the meanwhile, we can
12 compare the original instruo utility with our implementation.
13
14 ---
15 .gitignore | 2 +
16 Makefile.am | 15 ++-
17 configure.ac | 2 +
18 src/libbash.cpp | 5 +
19 src/libbash.h | 3 +-
20 utils/command_line.cpp | 88 +++++++++
21 utils/command_line.h | 62 ++++++
22 utils/instruo.cpp | 251 ++++++++++++++++++++++++
23 utils/{metadata_generator.cpp => metadata.cpp} | 35 +---
24 src/libbash.h => utils/metadata.h | 31 +---
25 utils/metadata_generator.cpp | 84 +--------
26 11 files changed, 445 insertions(+), 133 deletions(-)
27
28 diff --git a/.gitignore b/.gitignore
29 index 10b4131..79e3a80 100644
30 --- a/.gitignore
31 +++ b/.gitignore
32 @@ -2,6 +2,7 @@
33 *.swo
34 *.o
35 *.la
36 +*.a
37 *.lo
38 *.log
39 *.class
40 @@ -21,6 +22,7 @@ cppunittests
41 variable_printer
42 metadata_generator
43 ast_printer
44 +instruo
45 long.sh
46 massif.out
47 libbash.g
48
49 diff --git a/Makefile.am b/Makefile.am
50 index a3890bb..95beba6 100644
51 --- a/Makefile.am
52 +++ b/Makefile.am
53 @@ -113,13 +113,24 @@ cppunittests_LDFLAGS = -static
54
55 endif
56
57 -noinst_PROGRAMS = variable_printer metadata_generator ast_printer
58 +noinst_LIBRARIES = libmetadata.a
59 +
60 +libmetadata_a_SOURCES = utils/metadata.h utils/metadata.cpp
61 +libmetadata_a_CPPFLAGS = $(AM_CPPFLAGS) -Iutils
62 +
63 +noinst_PROGRAMS = variable_printer metadata_generator ast_printer instruo
64
65 variable_printer_SOURCES = utils/variable_printer.cpp
66 variable_printer_LDADD = libcppbash.la
67
68 metadata_generator_SOURCES = utils/metadata_generator.cpp
69 -metadata_generator_LDADD = libcppbash.la
70 +metadata_generator_LDADD = libcppbash.la libmetadata.a
71 +metadata_generator_CPPFLAGS = $(AM_CPPFLAGS) -Iutils
72 +
73 +instruo_SOURCES = utils/instruo.cpp utils/command_line.cpp utils/command_line.h
74 +instruo_LDADD = libcppbash.la @PALUDIS_LIBS@ libmetadata.a
75 +instruo_CPPFLAGS = $(AM_CPPFLAGS) @PALUDIS_CFLAGS@ -Iutils
76 +instruo_CXXFLAGS = $(AM_CXXFLAGS) -Wno-extra
77
78 ast_printer_SOURCES = utils/ast_printer.cpp
79 ast_printer_LDADD = libcppbash.la $(BOOST_PROGRAM_OPTIONS_LIB)
80
81 diff --git a/configure.ac b/configure.ac
82 index b710a97..3563013 100644
83 --- a/configure.ac
84 +++ b/configure.ac
85 @@ -29,6 +29,8 @@ AC_ARG_ENABLE([developer],
86 [AS_HELP_STRING([--enable-developer],[enables various QA checks])])
87 AM_CONDITIONAL([DEVELOPER_MODE],[test "x$enable_developer" = xyes])
88
89 +PKG_CHECK_MODULES([PALUDIS], [paludis])
90 +
91 AS_IF([test "x$enable_developer" = xyes],[boost_version="1.46.1"],[boost_version="1.43.0"])
92 AX_BOOST_BASE([$boost_version],[:],
93 [AC_MSG_ERROR([Needed boost not found])])
94
95 diff --git a/src/libbash.cpp b/src/libbash.cpp
96 index 4fb4102..f04064d 100644
97 --- a/src/libbash.cpp
98 +++ b/src/libbash.cpp
99 @@ -39,6 +39,11 @@ namespace libbash
100 if(!input)
101 throw interpreter_exception("Unable to create fstream for script: " + path);
102 interpreter walker;
103 +
104 + // Initialize bash environment
105 + for(auto iter = variables.begin(); iter != variables.end(); ++iter)
106 + walker.set_value(iter->first, (iter->second)[0]);
107 +
108 bash_ast ast(input);
109 ast.interpret_with(walker);
110
111
112 diff --git a/src/libbash.h b/src/libbash.h
113 index ca8cdaa..3f903e9 100644
114 --- a/src/libbash.h
115 +++ b/src/libbash.h
116 @@ -39,7 +39,8 @@ namespace libbash
117 /// \brief interpret a script specifid by path, return a map filled with
118 /// variables defined in the script
119 /// \param the path of target script
120 - /// \param the map to store variables
121 + /// \param[in, out] we use the map to initialize bash environment and store the result
122 + /// \param[out] store the names of the functions defined in the script
123 void LIBBASH_API interpret(const std::string& path,
124 std::unordered_map<std::string, std::vector<std::string>>& variables,
125 std::vector<std::string>& functions);
126
127 diff --git a/utils/command_line.cpp b/utils/command_line.cpp
128 new file mode 100644
129 index 0000000..8d238b4
130 --- /dev/null
131 +++ b/utils/command_line.cpp
132 @@ -0,0 +1,88 @@
133 +/* This file was copied from Paludis src/clients/instruo/command_line.cc that is licensed as follows: */
134 +
135 +/*
136 + * Copyright (c) 2007, 2008, 2009, 2010 Ciaran McCreesh
137 + *
138 + * This file is part of the Paludis package manager. Paludis is free software;
139 + * you can redistribute it and/or modify it under the terms of the GNU General
140 + * Public License version 2, as published by the Free Software Foundation.
141 + *
142 + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
143 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
144 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
145 + * details.
146 + *
147 + * You should have received a copy of the GNU General Public License along with
148 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
149 + * Place, Suite 330, Boston, MA 02111-1307 USA
150 + */
151 +
152 +#include "command_line.h"
153 +#include <paludis/util/singleton-impl.hh>
154 +
155 +using namespace paludis;
156 +
157 +template class paludis::Singleton<CommandLine>;
158 +
159 +CommandLine::CommandLine() :
160 + ArgsHandler(),
161 +
162 + action_args(main_options_section(), "Actions",
163 + "Selects which basic action to perform. Exactly one action should "
164 + "be specified."),
165 + a_generate_cache(&action_args, "generate-cache", 'g', "Generate cache", false),
166 + a_version(&action_args, "version", 'V', "Display program version", false),
167 + a_help(&action_args, "help", 'h', "Display program help", false),
168 +
169 + general_args(main_options_section(), "General options",
170 + "Options which are relevant for most or all actions."),
171 + a_log_level(&general_args, "log-level", '\0'),
172 + a_no_colour(&general_args, "no-colour", '\0', "Do not use colour", false),
173 + a_no_color(&a_no_colour, "no-color"),
174 + a_force_colour(&general_args, "force-colour", '\0', "Force the use of colour", false),
175 + a_force_color(&a_force_colour, "force-color"),
176 + a_repository_directory(&general_args, "repository-dir", 'D',
177 + "Where to find the repository (default: current directory)"),
178 + a_output_directory(&general_args, "output-dir", 'o',
179 + "Where to place generated metadata (default: current directory)"),
180 + a_master_repository_name(&general_args, "master-repository-name", '\0',
181 + "Use the specified name for the master repository. Specify the location using --extra-repository-dir. "
182 + "Only for repositories with no metadata/layout.conf."),
183 + a_extra_repository_dir(&general_args, "extra-repository-dir", '\0',
184 + "Also include the repository at this location. May be specified multiple times, in creation order."),
185 + a_report_file(&general_args, "report-file", 'r',
186 + "Write report to the specified file, rather than stdout")
187 +{
188 + add_usage_line("--generate-cache [ at least one of --repository-dir /dir or --output-dir /dir ]");
189 +
190 + add_description_line("instruo is configured purely from the command line. It does not use any user "
191 + "configuration files.");
192 +
193 + add_environment_variable("INSTRUO_OPTIONS", "Default command-line options.");
194 + add_environment_variable("INSTRUO_THREADS", "Number of threads to use. Default: 5");
195 +}
196 +
197 +std::string
198 +CommandLine::app_name() const
199 +{
200 + return "instruo";
201 +}
202 +
203 +std::string
204 +CommandLine::app_synopsis() const
205 +{
206 + return "Metadata generation client for Paludis";
207 +}
208 +
209 +std::string
210 +CommandLine::app_description() const
211 +{
212 + return
213 + "instruo is a metadata generation client for Paludis. It generates metadata cache for every ID in a "
214 + "given repository and produces a report of any failures.";
215 +}
216 +
217 +CommandLine::~CommandLine()
218 +{
219 +}
220 +
221
222 diff --git a/utils/command_line.h b/utils/command_line.h
223 new file mode 100644
224 index 0000000..2fdb10b
225 --- /dev/null
226 +++ b/utils/command_line.h
227 @@ -0,0 +1,62 @@
228 +/* This file was copied from Paludis src/clients/instruo/command_line.hh that is licensed as follows: */
229 +
230 +/*
231 + * Copyright (c) 2007, 2008, 2010 Ciaran McCreesh
232 + *
233 + * This file is part of the Paludis package manager. Paludis is free software;
234 + * you can redistribute it and/or modify it under the terms of the GNU General
235 + * Public License version 2, as published by the Free Software Foundation.
236 + *
237 + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
238 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
239 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
240 + * details.
241 + *
242 + * You should have received a copy of the GNU General Public License along with
243 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
244 + * Place, Suite 330, Boston, MA 02111-1307 USA
245 + */
246 +
247 +#ifndef PALUDIS_GUARD_SRC_CLIENTS_INSTRUO_COMMAND_LINE_HH
248 +#define PALUDIS_GUARD_SRC_CLIENTS_INSTRUO_COMMAND_LINE_HH 1
249 +
250 +#include <paludis/args/args.hh>
251 +#include <paludis/util/singleton.hh>
252 +#include <paludis/args/log_level_arg.hh>
253 +
254 +class CommandLine :
255 + public paludis::args::ArgsHandler,
256 + public paludis::Singleton<CommandLine>
257 +{
258 + friend class paludis::Singleton<CommandLine>;
259 +
260 + private:
261 + CommandLine();
262 + ~CommandLine();
263 +
264 + public:
265 + virtual std::string app_name() const;
266 + virtual std::string app_synopsis() const;
267 + virtual std::string app_description() const;
268 +
269 + paludis::args::ArgsGroup action_args;
270 +
271 + paludis::args::SwitchArg a_generate_cache;
272 + paludis::args::SwitchArg a_version;
273 + paludis::args::SwitchArg a_help;
274 +
275 + paludis::args::ArgsGroup general_args;
276 +
277 + paludis::args::LogLevelArg a_log_level;
278 + paludis::args::SwitchArg a_no_colour;
279 + paludis::args::AliasArg a_no_color;
280 + paludis::args::SwitchArg a_force_colour;
281 + paludis::args::AliasArg a_force_color;
282 + paludis::args::StringArg a_repository_directory;
283 + paludis::args::StringArg a_output_directory;
284 + paludis::args::StringArg a_master_repository_name;
285 + paludis::args::StringSequenceArg a_extra_repository_dir;
286 + paludis::args::StringArg a_report_file;
287 +};
288 +
289 +#endif
290
291 diff --git a/utils/instruo.cpp b/utils/instruo.cpp
292 new file mode 100644
293 index 0000000..bd1c981
294 --- /dev/null
295 +++ b/utils/instruo.cpp
296 @@ -0,0 +1,251 @@
297 +/* This file was partly copied from Paludis src/clients/instruo/instruo.cc.
298 + * The metadata generation logic is reimplemented with libbash. This file is
299 + * licensed as follows: */
300 +
301 +/*
302 + * Copyright (c) 2007, 2008, 2009, 2010 Ciaran McCreesh
303 + *
304 + * This file is part of the Paludis package manager. Paludis is free software;
305 + * you can redistribute it and/or modify it under the terms of the GNU General
306 + * Public License version 2, as published by the Free Software Foundation.
307 + *
308 + * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
309 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
310 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
311 + * details.
312 + *
313 + * You should have received a copy of the GNU General Public License along with
314 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
315 + * Place, Suite 330, Boston, MA 02111-1307 USA
316 + */
317 +
318 +#include <algorithm>
319 +#include <fstream>
320 +#include <functional>
321 +#include <iostream>
322 +#include <map>
323 +
324 +#include <paludis/args/do_help.hh>
325 +#include <paludis/about.hh>
326 +#include <paludis/action.hh>
327 +#include <paludis/package_id.hh>
328 +#include <paludis/generator.hh>
329 +#include <paludis/filter.hh>
330 +#include <paludis/filtered_generator.hh>
331 +#include <paludis/selection.hh>
332 +#include <paludis/util/system.hh>
333 +#include <paludis/util/join.hh>
334 +#include <paludis/util/log.hh>
335 +#include <paludis/util/sequence.hh>
336 +#include <paludis/util/map.hh>
337 +#include <paludis/util/visitor_cast.hh>
338 +#include <paludis/util/set.hh>
339 +#include <paludis/util/make_named_values.hh>
340 +#include <paludis/util/mutex.hh>
341 +#include <paludis/util/thread_pool.hh>
342 +#include <paludis/util/destringify.hh>
343 +#include <paludis/util/safe_ofstream.hh>
344 +#include <paludis/util/pretty_print.hh>
345 +#include <paludis/util/indirect_iterator-impl.hh>
346 +#include <paludis/util/timestamp.hh>
347 +#include <paludis/util/accept_visitor.hh>
348 +#include <paludis/environments/no_config/no_config_environment.hh>
349 +#include <paludis/package_database.hh>
350 +#include <paludis/metadata_key.hh>
351 +
352 +#include "command_line.h"
353 +#include "libbash.h"
354 +#include "utils/metadata.h"
355 +
356 +using namespace paludis;
357 +using std::cout;
358 +using std::cerr;
359 +using std::endl;
360 +
361 +void worker(const std::shared_ptr<PackageIDSequence> &ids)
362 +{
363 + std::unordered_map<std::string, std::vector<std::string>> variables;
364 +
365 + std::shared_ptr<const PackageID> id;
366 + unsigned total(0);
367 + CategoryNamePart old_cat("OLDCAT");
368 + while(!ids->empty())
369 + {
370 + id = *ids->begin();
371 + ids->pop_front();
372 + if (id->name().category() != old_cat)
373 + {
374 + std::cout << "Processing " << stringify(id->name().category()) << "..." << std::endl;
375 + old_cat = id->name().category();
376 + FSPath(CommandLine::get_instance()->a_output_directory.argument() + "/" +
377 + stringify(id->name().category())).mkdir(0755, {fspmkdo_ok_if_exists});
378 + ++total;
379 + }
380 +
381 + Context i_context("When generating metadata for ID '" + stringify(*id) + "':");
382 +
383 + variables.clear();
384 + variables["PN"].push_back(stringify(id->name().package()));
385 + variables["PV"].push_back(stringify(id->version().remove_revision()));
386 + variables["P"].push_back(stringify(id->name().package()) + "-" +
387 + stringify(id->version().remove_revision()));
388 + variables["PR"].push_back(id->version().revision_only());
389 + variables["PVR"].push_back(stringify(id->version()));
390 + variables["PF"].push_back(stringify(id->name().package()) + "-" + stringify(id->version()));
391 + variables["CATEGORY"].push_back(stringify(id->name().category()));
392 + std::vector<std::string> functions;
393 +
394 + std::string ebuild_path(CommandLine::get_instance()->a_repository_directory.argument() +
395 + variables["CATEGORY"][0] + "/" +
396 + variables["PN"][0] + "/" +
397 + variables["PN"][0] + "-" +
398 + variables["PVR"][0] + ".ebuild");
399 + try
400 + {
401 + libbash::interpret(ebuild_path, variables, functions);
402 + }
403 + catch(const interpreter_exception& e)
404 + {
405 + cerr << "Exception occurred while interpreting " << ebuild_path << ". The error message is:\n"
406 + << e.what() << endl;
407 + continue;
408 + }
409 +
410 + std::string output_path(CommandLine::get_instance()->a_output_directory.argument() + "/" +
411 + variables["CATEGORY"][0] + "/" +
412 + variables["PN"][0] + "-" +
413 + variables["PVR"][0]);
414 + FSPath(output_path).dirname().mkdir(0755, {fspmkdo_ok_if_exists});
415 + std::ofstream output(output_path, std::ofstream::out | std::ofstream::trunc);
416 + write_metadata(output, variables, functions);
417 + }
418 +}
419 +
420 +int main(int argc, char** argv)
421 +{
422 + try
423 + {
424 + std::string options(paludis::getenv_with_default("INSTRUO_OPTIONS", ""));
425 + if (! options.empty())
426 + options = "(" + options + ") ";
427 + options += join(argv + 1, argv + argc, " ");
428 +
429 + Context context(std::string("In program ") + argv[0] + " " + options + ":");
430 +
431 + CommandLine::get_instance()->run(argc, argv, "instruo", "INSTRUO_OPTIONS", "INSTRUO_CMDLINE");
432 +
433 + if (CommandLine::get_instance()->a_help.specified())
434 + throw args::DoHelp();
435 +
436 + if (CommandLine::get_instance()->a_log_level.specified())
437 + Log::get_instance()->set_log_level(CommandLine::get_instance()->a_log_level.option());
438 + else
439 + Log::get_instance()->set_log_level(ll_qa);
440 +
441 + if (1 < (
442 + CommandLine::get_instance()->a_generate_cache.specified() +
443 + CommandLine::get_instance()->a_version.specified()
444 + ))
445 + throw args::DoHelp("you should specify exactly one action");
446 +
447 + if (! CommandLine::get_instance()->a_repository_directory.specified())
448 + CommandLine::get_instance()->a_repository_directory.set_argument(stringify(FSPath::cwd()));
449 +
450 + if (CommandLine::get_instance()->a_version.specified())
451 + {
452 + cout << "instruo, part of " << PALUDIS_PACKAGE << " " << PALUDIS_VERSION_MAJOR << "."
453 + << PALUDIS_VERSION_MINOR << "." << PALUDIS_VERSION_MICRO << PALUDIS_VERSION_SUFFIX;
454 + if (! std::string(PALUDIS_GIT_HEAD).empty())
455 + cout << " git " << PALUDIS_GIT_HEAD;
456 + cout << endl << endl;
457 + cout << "Paludis comes with ABSOLUTELY NO WARRANTY. Paludis is free software, and you" << endl;
458 + cout << "are welcome to redistribute it under the terms of the GNU General Public" << endl;
459 + cout << "License, version 2." << endl;
460 +
461 + return EXIT_SUCCESS;
462 + }
463 +
464 + if ((
465 + CommandLine::get_instance()->a_repository_directory.specified() +
466 + CommandLine::get_instance()->a_output_directory.specified()
467 + ) < 1)
468 + throw args::DoHelp("at least one of '--" + CommandLine::get_instance()->a_repository_directory.long_name() + "' or '--"
469 + + CommandLine::get_instance()->a_output_directory.long_name() + "' must be specified");
470 +
471 + if (! CommandLine::get_instance()->a_output_directory.specified())
472 + CommandLine::get_instance()->a_output_directory.set_argument(stringify(FSPath::cwd()));
473 +
474 + std::shared_ptr<FSPathSequence> extra_repository_dirs(std::make_shared<FSPathSequence>());
475 + for (args::StringSequenceArg::ConstIterator d(CommandLine::get_instance()->a_extra_repository_dir.begin_args()),
476 + d_end(CommandLine::get_instance()->a_extra_repository_dir.end_args()) ;
477 + d != d_end ; ++d)
478 + extra_repository_dirs->push_back(FSPath(*d));
479 +
480 + std::shared_ptr<Map<std::string, std::string> > keys(std::make_shared<Map<std::string, std::string>>());
481 + keys->insert("append_repository_name_to_write_cache", "false");
482 + NoConfigEnvironment env(make_named_values<no_config_environment::Params>(
483 + n::accept_unstable() = true,
484 + n::disable_metadata_cache() = true,
485 + n::extra_accept_keywords() = "",
486 + n::extra_params() = keys,
487 + n::extra_repository_dirs() = extra_repository_dirs,
488 + n::master_repository_name() = CommandLine::get_instance()->a_master_repository_name.argument(),
489 + n::profiles_if_not_auto() = "",
490 + n::repository_dir() = CommandLine::get_instance()->a_repository_directory.argument(),
491 + n::repository_type() = no_config_environment::ncer_ebuild,
492 + n::write_cache() = CommandLine::get_instance()->a_output_directory.argument()
493 + ));
494 +
495 + FSPath(CommandLine::get_instance()->a_output_directory.argument()).mkdir(0755, {fspmkdo_ok_if_exists});
496 +
497 + std::shared_ptr<PackageIDSequence> ids(env[selection::AllVersionsSorted(
498 + generator::InRepository(env.main_repository()->name()))]);
499 + worker(ids);
500 + }
501 + catch (const paludis::args::ArgsError & e)
502 + {
503 + cerr << "Usage error: " << e.message() << endl;
504 + cerr << "Try " << argv[0] << " --help" << endl;
505 + return EXIT_FAILURE;
506 + }
507 + catch (const args::DoHelp & h)
508 + {
509 + if (h.message.empty())
510 + {
511 + cout << "Usage: " << argv[0] << " [options]" << endl;
512 + cout << endl;
513 + cout << *CommandLine::get_instance();
514 + return EXIT_SUCCESS;
515 + }
516 + else
517 + {
518 + cerr << "Usage error: " << h.message << endl;
519 + cerr << "Try " << argv[0] << " --help" << endl;
520 + return EXIT_FAILURE;
521 + }
522 + }
523 + catch (const Exception & e)
524 + {
525 + cout << endl;
526 + cerr << "Unhandled exception:" << endl
527 + << " * " << e.backtrace("\n * ")
528 + << e.message() << " (" << e.what() << ")" << endl;
529 + return EXIT_FAILURE;
530 + }
531 + catch (const std::exception & e)
532 + {
533 + cout << endl;
534 + cerr << "Unhandled exception:" << endl
535 + << " * " << e.what() << endl;
536 + return EXIT_FAILURE;
537 + }
538 + catch (...)
539 + {
540 + cout << endl;
541 + cerr << "Unhandled exception:" << endl
542 + << " * Unknown exception type. Ouch..." << endl;
543 + return EXIT_FAILURE;
544 + }
545 +
546 + return EXIT_SUCCESS;
547 +}
548
549 diff --git a/utils/metadata_generator.cpp b/utils/metadata.cpp
550 similarity index 83%
551 copy from utils/metadata_generator.cpp
552 copy to utils/metadata.cpp
553 index 52b4590..600f9e4 100644
554 --- a/utils/metadata_generator.cpp
555 +++ b/utils/metadata.cpp
556 @@ -17,21 +17,18 @@
557 along with libbash. If not, see <http://www.gnu.org/licenses/>.
558 */
559 ///
560 -/// \file metadata_generator.cpp
561 +/// \file metadata.cpp
562 /// \author Mu Qiao
563 -/// \brief a simple utility for generating metadata
564 +/// \brief a helper for printing metadata content
565 ///
566 -#include <iostream>
567 #include <set>
568 -#include <string>
569 -#include <vector>
570
571 #include <boost/spirit/include/karma.hpp>
572 #include <boost/algorithm/string/classification.hpp>
573 #include <boost/algorithm/string/split.hpp>
574 #include <boost/algorithm/string/trim.hpp>
575
576 -#include "libbash.h"
577 +#include "utils/metadata.h"
578
579 static const std::vector<std::string> metadata_names = {"DEPEND", "RDEPEND", "SLOT", "SRC_URI",
580 "RESTRICT", "HOMEPAGE", "LICENSE", "DESCRIPTION",
581 @@ -56,20 +53,10 @@ static const std::unordered_map<std::string, std::string> phases = {
582 {"pkg_nofetch", "nofetch"}
583 };
584
585 -int main(int argc, char** argv)
586 +void write_metadata(std::ostream& output,
587 + std::unordered_map<std::string, std::vector<std::string>>& variables,
588 + std::vector<std::string>& functions)
589 {
590 - using namespace boost::spirit::karma;
591 -
592 - if(argc != 2)
593 - {
594 - std::cerr<<"Please provide your script as an argument"<<std::endl;
595 - exit(EXIT_FAILURE);
596 - }
597 -
598 - std::unordered_map<std::string, std::vector<std::string>> variables;
599 - std::vector<std::string> functions;
600 - libbash::interpret(argv[1], variables, functions);
601 -
602 for(auto iter_name = metadata_names.begin(); iter_name != metadata_names.end(); ++iter_name)
603 {
604 auto iter_value = variables.find(*iter_name);
605 @@ -106,7 +93,8 @@ int main(int argc, char** argv)
606 value,
607 boost::is_any_of(" \t\n"),
608 boost::token_compress_on);
609 - std::cout << format(string % ' ', splitted_value) << std::endl;
610 + using namespace boost::spirit::karma;
611 + output << format(string % ' ', splitted_value) << std::endl;
612 }
613
614 // Print defined phases
615 @@ -117,10 +105,9 @@ int main(int argc, char** argv)
616 if(iter_phase != phases.end())
617 sorted_phases.insert(iter_phase->second);
618 }
619 - std::cout << format(string % ' ', sorted_phases) << std::endl;
620 + using namespace boost::spirit::karma;
621 + output << format(string % ' ', sorted_phases) << std::endl;
622
623 // Print empty lines
624 - std::cout << std::endl << std::endl << std::endl << std::endl << std::endl;
625 -
626 - return EXIT_SUCCESS;
627 + output << std::endl << std::endl << std::endl << std::endl << std::endl;
628 }
629
630 diff --git a/src/libbash.h b/utils/metadata.h
631 similarity index 55%
632 copy from src/libbash.h
633 copy to utils/metadata.h
634 index ca8cdaa..cb7f559 100644
635 --- a/src/libbash.h
636 +++ b/utils/metadata.h
637 @@ -15,34 +15,17 @@
638
639 You should have received a copy of the GNU General Public License
640 along with libbash. If not, see <http://www.gnu.org/licenses/>.
641 -*/
642 + */
643 ///
644 -/// \file libbash.h
645 +/// \file metadata.h
646 /// \author Mu Qiao
647 -/// \brief public interface for libbash
648 +/// \brief a helper for printing metadata content
649 ///
650 -
651 -#ifndef LIBBASH_LIBBASH_H_
652 -#define LIBBASH_LIBBASH_H_
653 -
654 -#include <memory>
655 +#include <iostream>
656 #include <string>
657 #include <unordered_map>
658 #include <vector>
659
660 -#include "common.h"
661 -#include "core/interpreter_exception.h"
662 -
663 -namespace libbash
664 -{
665 - ///
666 - /// \brief interpret a script specifid by path, return a map filled with
667 - /// variables defined in the script
668 - /// \param the path of target script
669 - /// \param the map to store variables
670 - void LIBBASH_API interpret(const std::string& path,
671 - std::unordered_map<std::string, std::vector<std::string>>& variables,
672 - std::vector<std::string>& functions);
673 -}
674 -
675 -#endif
676 +void write_metadata(std::ostream& output,
677 + std::unordered_map<std::string, std::vector<std::string>>& variables,
678 + std::vector<std::string>& functions);
679
680 diff --git a/utils/metadata_generator.cpp b/utils/metadata_generator.cpp
681 index 52b4590..14602f2 100644
682 --- a/utils/metadata_generator.cpp
683 +++ b/utils/metadata_generator.cpp
684 @@ -22,44 +22,14 @@
685 /// \brief a simple utility for generating metadata
686 ///
687 #include <iostream>
688 -#include <set>
689 #include <string>
690 #include <vector>
691
692 -#include <boost/spirit/include/karma.hpp>
693 -#include <boost/algorithm/string/classification.hpp>
694 -#include <boost/algorithm/string/split.hpp>
695 -#include <boost/algorithm/string/trim.hpp>
696 -
697 #include "libbash.h"
698 -
699 -static const std::vector<std::string> metadata_names = {"DEPEND", "RDEPEND", "SLOT", "SRC_URI",
700 - "RESTRICT", "HOMEPAGE", "LICENSE", "DESCRIPTION",
701 - "KEYWORDS", "INHERITED", "IUSE", "REQUIRED_USE",
702 - "PDEPEND", "PROVIDE", "EAPI", "PROPERTIES"};
703 -
704 -static const std::unordered_map<std::string, std::string> phases = {
705 - {"pkg_pretend", "ppretend"},
706 - {"pkg_setup", "setup"},
707 - {"src_unpack", "unpack"},
708 - {"src_prepare", "prepare"},
709 - {"src_configure", "configure"},
710 - {"src_compile", "compile"},
711 - {"src_test", "test"},
712 - {"src_install", "install"},
713 - {"pkg_preinst", "preinst"},
714 - {"pkg_postinst", "postinst"},
715 - {"pkg_prerm", "prerm"},
716 - {"pkg_postrm", "postrm"},
717 - {"pkg_config", "config"},
718 - {"pkg_info", "info"},
719 - {"pkg_nofetch", "nofetch"}
720 -};
721 +#include "utils/metadata.h"
722
723 int main(int argc, char** argv)
724 {
725 - using namespace boost::spirit::karma;
726 -
727 if(argc != 2)
728 {
729 std::cerr<<"Please provide your script as an argument"<<std::endl;
730 @@ -70,57 +40,7 @@ int main(int argc, char** argv)
731 std::vector<std::string> functions;
732 libbash::interpret(argv[1], variables, functions);
733
734 - for(auto iter_name = metadata_names.begin(); iter_name != metadata_names.end(); ++iter_name)
735 - {
736 - auto iter_value = variables.find(*iter_name);
737 - std::string value;
738 -
739 - if(iter_value != variables.end())
740 - value = iter_value->second[0];
741 -
742 - // Check if global is defined
743 - auto iter_global = variables.find("E_" + *iter_name);
744 - if(iter_global != variables.end())
745 - {
746 - boost::trim_if(iter_global->second[0], boost::is_any_of(" \t\n"));
747 - std::vector<std::string> splitted_global;
748 - boost::split(splitted_global,
749 - iter_global->second[0],
750 - boost::is_any_of(" \t\n"),
751 - boost::token_compress_on);
752 -
753 - // Append the global value to 'value' if it doesn't cause duplication
754 - for(auto iter_splitted_global = splitted_global.begin();
755 - iter_splitted_global != splitted_global.end();
756 - ++iter_splitted_global)
757 - {
758 - if(value.find(*iter_splitted_global) == std::string::npos)
759 - value += " " + *iter_splitted_global;
760 - }
761 - }
762 -
763 - boost::trim_if(value, boost::is_any_of(" \t\n"));
764 -
765 - std::vector<std::string> splitted_value;
766 - boost::split(splitted_value,
767 - value,
768 - boost::is_any_of(" \t\n"),
769 - boost::token_compress_on);
770 - std::cout << format(string % ' ', splitted_value) << std::endl;
771 - }
772 -
773 - // Print defined phases
774 - std::set<std::string> sorted_phases;
775 - for(auto iter = functions.begin(); iter != functions.end(); ++iter)
776 - {
777 - auto iter_phase = phases.find(*iter);
778 - if(iter_phase != phases.end())
779 - sorted_phases.insert(iter_phase->second);
780 - }
781 - std::cout << format(string % ' ', sorted_phases) << std::endl;
782 -
783 - // Print empty lines
784 - std::cout << std::endl << std::endl << std::endl << std::endl << std::endl;
785 + write_metadata(std::cout, variables, functions);
786
787 return EXIT_SUCCESS;
788 }