Skip to content

Commit c30e0fc

Browse files
timsong-cppjwakely
authored andcommitted
Centralize metadata reading to handle non-default paths
1 parent e6555b3 commit c30e0fc

File tree

7 files changed

+96
-77
lines changed

7 files changed

+96
-77
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ all: pgms
3232

3333
pgms: $(PGMS)
3434

35-
bin/lists: src/date.o src/issues.o src/status.o src/sections.o src/mailing_info.o src/report_generator.o src/lists.o
35+
bin/lists: src/date.o src/issues.o src/status.o src/sections.o src/mailing_info.o src/report_generator.o src/lists.o src/metadata.o
3636

3737
bin/section_data: src/section_data.o
3838

3939
bin/toc_diff: src/toc_diff.o
4040

41-
bin/list_issues: src/date.o src/issues.o src/status.o src/sections.o src/list_issues.o
41+
bin/list_issues: src/date.o src/issues.o src/status.o src/sections.o src/list_issues.o src/metadata.o
4242

4343
bin/set_status: src/set_status.o src/status.o
4444

src/issues.cpp

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#endif
44

55
#include "issues.h"
6-
#include "sections.h"
6+
#include "metadata.h"
77
#include "status.h"
88

99
#include <algorithm>
@@ -64,26 +64,10 @@ auto make_date(std::tm const & mod) -> gregorian::date {
6464
return gregorian::year((unsigned short)(mod.tm_year+1900)) / (mod.tm_mon+1) / mod.tm_mday;
6565
}
6666

67-
struct issue_mod_time {
68-
int id;
69-
std::time_t t;
70-
operator std::pair<const int, std::time_t>() const { return { id, t }; }
71-
friend std::istream& operator>>(std::istream& in, issue_mod_time& v) { return in >> v.id >> v.t; }
72-
};
73-
74-
auto git_commit_times() -> std::map<int, std::time_t>
75-
{
76-
using Iter = std::istream_iterator<issue_mod_time>;
77-
std::ifstream f{"meta-data/dates"};
78-
std::map<int, std::time_t> times{ Iter{f}, Iter{} };
79-
return times;
80-
}
81-
82-
auto report_date_file_last_modified(std::filesystem::path const & filename) -> gregorian::date {
67+
auto report_date_file_last_modified(std::filesystem::path const & filename, lwg::metadata const& meta) -> gregorian::date {
8368
std::time_t mtime;
8469
int id = std::stoi(filename.filename().stem().native().substr(5));
85-
static auto git_times = git_commit_times();
86-
if (auto it = git_times.find(id); it != git_times.end())
70+
if (auto it = meta.git_commit_times.find(id); it != meta.git_commit_times.end())
8771
mtime = it->second;
8872
else
8973
{
@@ -112,7 +96,8 @@ std::string escape_special_chars(std::string s) {
11296
} // close unnamed namespace
11397

11498
auto lwg::parse_issue_from_file(std::string tx, std::string const & filename,
115-
lwg::section_map & section_db) -> issue {
99+
lwg::metadata & meta) -> issue {
100+
auto& section_db = meta.section_db;
116101
struct bad_issue_file : std::runtime_error {
117102
bad_issue_file(std::string const & filename, std::string error_message)
118103
: runtime_error{"Error parsing issue file " + filename + ": " + error_message}
@@ -263,7 +248,7 @@ auto lwg::parse_issue_from_file(std::string tx, std::string const & filename,
263248
is.date = parse_date(temp);
264249

265250
// Get modification date
266-
is.mod_date = report_date_file_last_modified(filename);
251+
is.mod_date = report_date_file_last_modified(filename, meta);
267252
}
268253
catch(std::exception const & ex) {
269254
throw bad_issue_file{filename, ex.what()};

src/issues.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
// solution specific headers
1111
#include "date.h"
12-
#include "sections.h"
12+
#include "metadata.h"
1313
#include "status.h"
1414

1515
namespace lwg
@@ -38,7 +38,7 @@ struct order_by_issue_number {
3838
bool operator()(int x, issue const & y) const noexcept { return x < y.num; }
3939
};
4040

41-
auto parse_issue_from_file(std::string file_contents, std::string const & filename, lwg::section_map & section_db) -> issue;
41+
auto parse_issue_from_file(std::string file_contents, std::string const & filename, lwg::metadata & meta) -> issue;
4242
// Seems appropriate constructor behavior.
4343
//
4444
// Note that 'section_db' is modifiable as new (unknown) sections may be inserted,

src/list_issues.cpp

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ namespace fs = std::filesystem;
3939

4040
// solution specific headers
4141
#include "issues.h"
42-
#include "sections.h"
42+
#include "metadata.h"
4343

4444

4545
auto read_file_into_string(fs::path const & filename) -> std::string {
@@ -66,7 +66,7 @@ auto is_issue_xml_file(fs::directory_entry const & e) {
6666
return false;
6767
}
6868

69-
void filter_issues(fs::path const & issues_path, lwg::section_map & section_db, std::function<bool(lwg::issue const &)> predicate) {
69+
void filter_issues(fs::path const & issues_path, lwg::metadata & meta, std::function<bool(lwg::issue const &)> predicate) {
7070
// Open the specified directory, 'issues_path', and iterate all the '.xml' files
7171
// it contains, parsing each such file as an LWG issue document. Collect
7272
// the number of every issue that satisfies the 'predicate'.
@@ -75,7 +75,7 @@ void filter_issues(fs::path const & issues_path, lwg::section_map & section_db,
7575
for (auto ent : fs::directory_iterator(issues_path)) {
7676
if (is_issue_xml_file(ent)) {
7777
fs::path const issue_file = ent.path();
78-
auto const iss = parse_issue_from_file(read_file_into_string(issue_file), issue_file.string(), section_db);
78+
auto const iss = parse_issue_from_file(read_file_into_string(issue_file), issue_file.string(), meta);
7979
if (predicate(iss)) {
8080
nums.push_back(iss.num);
8181
}
@@ -97,8 +97,6 @@ void check_is_directory(fs::path const & directory) {
9797

9898
int main(int argc, char const* argv[]) {
9999
try {
100-
bool trace_on{false}; // Will pick this up from the command line later
101-
102100
if (argc != 2) {
103101
std::cerr << "Must specify exactly one status\n";
104102
return 2;
@@ -109,22 +107,9 @@ int main(int argc, char const* argv[]) {
109107

110108
check_is_directory(path);
111109

112-
lwg::section_map section_db = [&] {
113-
// This lambda expression scopes the lifetime of an open 'fstream'
114-
auto filename = path / "meta-data/section.data";
115-
std::ifstream infile{filename};
116-
if (!infile.is_open()) {
117-
throw std::runtime_error{"Can't open section.data at " + path.string() + "meta-data"};
118-
}
119-
120-
if (trace_on) {
121-
std::cout << "Reading section-tag index from: " << filename << std::endl;
122-
}
123-
124-
return lwg::read_section_db(infile);
125-
}();
110+
auto metadata = lwg::metadata::read_from_path(path);
126111

127-
filter_issues(path / "xml/", section_db, [status](lwg::issue const & iss) { return status == iss.stat; });
112+
filter_issues(path / "xml/", metadata, [status](lwg::issue const & iss) { return status == iss.stat; });
128113
}
129114
catch(std::exception const & ex) {
130115
std::cout << ex.what() << std::endl;

src/lists.cpp

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ auto is_issue_xml_file(fs::directory_entry const & e) {
7878
return false;
7979
}
8080

81-
auto read_issues(fs::path const & issues_path, lwg::section_map & section_db) -> std::vector<lwg::issue> {
81+
auto read_issues(fs::path const & issues_path, lwg::metadata & meta) -> std::vector<lwg::issue> {
8282
// Open the specified directory, 'issues_path', and iterate all the '.xml' files
8383
// it contains, parsing each such file as an LWG issue document. Return the set
8484
// of issues as a vector.
@@ -87,7 +87,7 @@ auto read_issues(fs::path const & issues_path, lwg::section_map & section_db) ->
8787
for (auto ent : fs::directory_iterator(issues_path)) {
8888
if (is_issue_xml_file(ent)) {
8989
fs::path const issue_file = ent.path();
90-
issues.emplace_back(parse_issue_from_file(read_file_into_string(issue_file), issue_file.string(), section_db));
90+
issues.emplace_back(parse_issue_from_file(read_file_into_string(issue_file), issue_file.string(), meta));
9191
}
9292
}
9393

@@ -218,18 +218,9 @@ namespace
218218
};
219219
}
220220

221-
std::unordered_map<std::string, std::string> paper_titles = [] {
222-
std::unordered_map<std::string, std::string> titles;
223-
std::ifstream in{"meta-data/paper_titles.txt"};
224-
std::string paper_number, title;
225-
while (in >> paper_number && std::getline(in, title))
226-
titles[paper_number] = title;
227-
return titles;
228-
}();
229-
230221
// The title of the specified paper, formatted as an HTML title="..." attribute.
231-
std::string paper_title_attr(std::string paper_number) {
232-
auto title = paper_titles[paper_number];
222+
std::string paper_title_attr(std::string paper_number, lwg::metadata& meta) {
223+
auto title = meta.paper_titles[paper_number];
233224
if (!title.empty())
234225
{
235226
title = lwg::replace_reserved_char(std::move(title), '&', "&amp;");
@@ -242,8 +233,9 @@ std::string paper_title_attr(std::string paper_number) {
242233
void format_issue_as_html(lwg::issue & is,
243234
std::vector<lwg::issue>::iterator first_issue,
244235
std::vector<lwg::issue>::iterator last_issue,
245-
lwg::section_map & section_db) {
236+
lwg::metadata & meta) {
246237

238+
auto& section_db = meta.section_db;
247239
std::vector<std::string> tag_stack; // stack of open XML tags as we parse
248240

249241
// Used by fix_tags to report errors.
@@ -453,7 +445,7 @@ void format_issue_as_html(lwg::issue & is,
453445
std::transform(paper_number.begin(), paper_number.end(), paper_number.begin(),
454446
[] (unsigned char c) { return std::toupper(c); });
455447

456-
auto title = paper_title_attr(paper_number);
448+
auto title = paper_title_attr(paper_number, meta);
457449

458450
j -= i - 1;
459451
std::string r = "<a href=\"https://wg21.link/" + paper_number + "\"" + title + ">" + paper_number + "</a>";
@@ -497,7 +489,7 @@ void format_issue_as_html(lwg::issue & is,
497489
}
498490

499491

500-
void prepare_issues(std::vector<lwg::issue> & issues, lwg::section_map & section_db) {
492+
void prepare_issues(std::vector<lwg::issue> & issues, lwg::metadata & meta) {
501493
// Initially sort the issues by issue number, so each issue can be correctly 'format'ted
502494
sort(issues.begin(), issues.end(), lwg::order_by_issue_number{});
503495

@@ -507,7 +499,7 @@ void prepare_issues(std::vector<lwg::issue> & issues, lwg::section_map & section
507499
// Currently, the 'format' function takes a reference-to-non-const-vector-of-issues purely to
508500
// mark up information related to duplicates, so processing duplicates in a separate pass may
509501
// clarify the code.
510-
for (auto & i : issues) { format_issue_as_html(i, issues.begin(), issues.end(), section_db); }
502+
for (auto & i : issues) { format_issue_as_html(i, issues.begin(), issues.end(), meta); }
511503

512504
// Issues will be routinely re-sorted in later code, but contents should be fixed after formatting.
513505
// This suggests we may want to be storing some kind of issue handle in the functions that keep
@@ -754,20 +746,10 @@ int main(int argc, char* argv[]) {
754746
const fs::path target_path{path / "mailing"};
755747
check_is_directory(target_path);
756748

757-
758-
lwg::section_map section_db =[&path]() {
759-
auto filename = path / "meta-data" / "section.data";
760-
std::ifstream infile{filename};
761-
if (!infile.is_open()) {
762-
throw std::runtime_error{"Can't open section.data at " + path.string() + "meta-data"};
763-
}
764-
std::cout << "Reading section-tag index from: " << filename << std::endl;
765-
766-
return lwg::read_section_db(infile);
767-
}();
749+
auto metadata = lwg::metadata::read_from_path(path);
768750
#if defined (DEBUG_LOGGING)
769751
// dump the contents of the section index
770-
for (auto const & elem : section_db ) {
752+
for (auto const & elem : metadata.section_db ) {
771753
std::string temp = elem.first;
772754
temp.erase(temp.end()-1);
773755
temp.erase(temp.begin());
@@ -793,11 +775,11 @@ int main(int argc, char* argv[]) {
793775

794776

795777
std::cout << "Reading issues from: " << issues_path << std::endl;
796-
auto issues = read_issues(issues_path, section_db);
797-
prepare_issues(issues, section_db);
778+
auto issues = read_issues(issues_path, metadata);
779+
prepare_issues(issues, metadata);
798780

799781

800-
lwg::report_generator generator{lwg_issues_xml, section_db};
782+
lwg::report_generator generator{lwg_issues_xml, metadata.section_db};
801783

802784

803785
// issues must be sorted by number before making the mailing list documents

src/metadata.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include "metadata.h"
2+
3+
#include <fstream>
4+
#include <iterator>
5+
#include <iostream>
6+
7+
namespace {
8+
struct issue_mod_time {
9+
int id;
10+
std::time_t t;
11+
operator std::pair<const int, std::time_t>() const { return { id, t }; }
12+
friend std::istream& operator>>(std::istream& in, issue_mod_time& v) { return in >> v.id >> v.t; }
13+
};
14+
15+
auto read_git_commit_times(std::filesystem::path const& path) -> std::map<int, std::time_t>
16+
{
17+
using Iter = std::istream_iterator<issue_mod_time>;
18+
std::ifstream f{path};
19+
std::map<int, std::time_t> times{ Iter{f}, Iter{} };
20+
return times;
21+
}
22+
23+
auto read_paper_titles(std::filesystem::path const& path) -> std::unordered_map<std::string, std::string> {
24+
std::unordered_map<std::string, std::string> titles;
25+
std::ifstream in{path};
26+
std::string paper_number, title;
27+
while (in >> paper_number && std::getline(in, title))
28+
titles[paper_number] = title;
29+
return titles;
30+
}
31+
32+
}
33+
34+
auto lwg::metadata::read_from_path(std::filesystem::path const& path) -> metadata {
35+
auto filename = path / "meta-data" / "section.data";
36+
std::ifstream infile{filename};
37+
if (!infile.is_open()) {
38+
throw std::runtime_error{"Can't open section.data at " + path.string() + "meta-data"};
39+
}
40+
std::cout << "Reading section-tag index from: " << filename << std::endl;
41+
return {
42+
read_section_db(infile),
43+
read_git_commit_times(path / "meta-data" / "dates"),
44+
read_paper_titles(path / "meta-data" / "paper_titles.txt"),
45+
};
46+
}

src/metadata.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef INCLUDE_LWG_METADATA_H
2+
#define INCLUDE_LWG_METADATA_H
3+
#include "sections.h"
4+
#include <map>
5+
#include <unordered_map>
6+
#include <ctime>
7+
#include <filesystem>
8+
9+
namespace lwg {
10+
11+
// Various things read from meta-data/
12+
struct metadata {
13+
section_map section_db;
14+
std::map<int, std::time_t> git_commit_times;
15+
std::unordered_map<std::string, std::string> paper_titles;
16+
17+
static metadata read_from_path(std::filesystem::path const& path);
18+
};
19+
20+
}
21+
#endif

0 commit comments

Comments
 (0)