Skip to content

Commit 2dceee4

Browse files
authored
Merge Output into src/build (#713)
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent e54ca13 commit 2dceee4

File tree

8 files changed

+579
-514
lines changed

8 files changed

+579
-514
lines changed

src/build/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
sourcemeta_library(NAMESPACE sourcemeta PROJECT one NAME build
22
SOURCES build.cc)
3+
target_link_libraries(sourcemeta_one_build
4+
PUBLIC sourcemeta::core::json
5+
PRIVATE sourcemeta::core::jsonschema)

src/build/build.cc

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include <sourcemeta/one/build.h>
22

3+
#include <sourcemeta/core/jsonschema.h>
4+
35
#include <cassert> // assert
46
#include <chrono> // std::chrono::nanoseconds, std::chrono::duration_cast
57
#include <cstdint> // std::int64_t
@@ -18,7 +20,13 @@ auto Build::dependency(std::filesystem::path node)
1820
}
1921

2022
Build::Build(const std::filesystem::path &output_root)
21-
: root{std::filesystem::canonical(output_root)} {
23+
: root{(static_cast<void>(std::filesystem::create_directories(output_root)),
24+
std::filesystem::canonical(output_root))} {
25+
for (const auto &entry :
26+
std::filesystem::recursive_directory_iterator(this->root)) {
27+
this->tracker.emplace(entry.path(), false);
28+
}
29+
2230
const auto deps_path{this->root / DEPENDENCIES_FILE};
2331
if (!std::filesystem::exists(deps_path)) {
2432
return;
@@ -114,15 +122,14 @@ auto Build::has_dependencies(const std::filesystem::path &path) const -> bool {
114122
return match != this->dependencies_map.end() && !match->second.empty();
115123
}
116124

117-
auto Build::write_dependencies(
118-
const std::function<bool(const std::filesystem::path &)> &filter) -> void {
125+
auto Build::finish() -> void {
119126
const auto deps_path{this->root / DEPENDENCIES_FILE};
120127
std::ofstream stream{deps_path};
121128
assert(!stream.fail());
122129

123130
std::shared_lock dependencies_lock{this->dependencies_mutex};
124131
for (const auto &entry : this->dependencies_map) {
125-
if (!filter(this->root / entry.first)) {
132+
if (this->is_untracked_file(this->root / entry.first)) {
126133
continue;
127134
}
128135

@@ -156,6 +163,13 @@ auto Build::write_dependencies(
156163

157164
stream.flush();
158165
stream.close();
166+
this->track(deps_path);
167+
168+
for (const auto &entry : this->tracker) {
169+
if (!entry.second) {
170+
std::filesystem::remove_all(entry.first);
171+
}
172+
}
159173
}
160174

161175
auto Build::refresh(const std::filesystem::path &path) -> void {
@@ -198,4 +212,53 @@ auto Build::mark(const std::filesystem::path &path)
198212
}
199213
}
200214

215+
auto Build::track(const std::filesystem::path &path)
216+
-> const std::filesystem::path & {
217+
assert(path.is_absolute());
218+
assert(std::filesystem::exists(path));
219+
std::unique_lock lock{this->tracker_mutex};
220+
assert(!this->tracker.contains(path) || !this->tracker.at(path));
221+
const auto &result{this->tracker.insert_or_assign(path, true).first->first};
222+
for (auto current = path; !current.empty() && current != this->root;
223+
current = current.parent_path()) {
224+
this->tracker.insert_or_assign(current, true);
225+
}
226+
227+
return result;
228+
}
229+
230+
auto Build::is_untracked_file(const std::filesystem::path &path) const -> bool {
231+
std::shared_lock lock{this->tracker_mutex};
232+
const auto match{this->tracker.find(path)};
233+
return match == this->tracker.cend() || !match->second;
234+
}
235+
236+
auto Build::output_write_json(const std::filesystem::path &path,
237+
const sourcemeta::core::JSON &document)
238+
-> const std::filesystem::path & {
239+
assert(path.is_absolute());
240+
std::filesystem::create_directories(path.parent_path());
241+
std::ofstream stream{path};
242+
assert(!stream.fail());
243+
sourcemeta::core::stringify(document, stream);
244+
return this->track(path);
245+
}
246+
247+
auto Build::write_json_if_different(const std::filesystem::path &path,
248+
const sourcemeta::core::JSON &document)
249+
-> void {
250+
if (std::filesystem::exists(path)) {
251+
const auto current{sourcemeta::core::read_json(path)};
252+
if (current != document) {
253+
this->output_write_json(path, document);
254+
this->refresh(path);
255+
} else {
256+
this->track(path);
257+
}
258+
} else {
259+
this->output_write_json(path, document);
260+
this->refresh(path);
261+
}
262+
}
263+
201264
} // namespace sourcemeta::one

src/build/include/sourcemeta/one/build.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include <sourcemeta/one/build_export.h>
66
#endif
77

8+
#include <sourcemeta/core/json.h>
9+
810
#include <algorithm> // std::ranges::none_of
911
#include <cassert> // assert
1012
#include <cstdint> // std::uint8_t
@@ -38,13 +40,14 @@ class SOURCEMETA_ONE_BUILD_EXPORT Build {
3840

3941
Build(const std::filesystem::path &output_root);
4042

43+
auto path() const -> const std::filesystem::path & { return this->root; }
44+
4145
static auto dependency(std::filesystem::path node)
4246
-> std::pair<DependencyKind, std::filesystem::path>;
4347

4448
[[nodiscard]] auto has_dependencies(const std::filesystem::path &path) const
4549
-> bool;
46-
auto write_dependencies(
47-
const std::function<bool(const std::filesystem::path &)> &filter) -> void;
50+
auto finish() -> void;
4851
auto refresh(const std::filesystem::path &path) -> void;
4952
[[nodiscard]] auto mark(const std::filesystem::path &path)
5053
-> std::optional<mark_type>;
@@ -88,6 +91,7 @@ class SOURCEMETA_ONE_BUILD_EXPORT Build {
8891
return !dependency_mark.has_value() ||
8992
dependency_mark.value() > destination_mark.value();
9093
})) {
94+
this->track(destination);
9195
return false;
9296
}
9397
}
@@ -113,6 +117,7 @@ class SOURCEMETA_ONE_BUILD_EXPORT Build {
113117
assert(destination.is_absolute());
114118
assert(std::filesystem::exists(destination));
115119
this->refresh(destination);
120+
this->track(destination);
116121
const auto key{destination.lexically_relative(this->root).string()};
117122
{
118123
std::unique_lock lock{this->dependencies_mutex};
@@ -123,13 +128,27 @@ class SOURCEMETA_ONE_BUILD_EXPORT Build {
123128
return true;
124129
}
125130

131+
auto track(const std::filesystem::path &path)
132+
-> const std::filesystem::path &;
133+
[[nodiscard]] auto is_untracked_file(const std::filesystem::path &path) const
134+
-> bool;
135+
136+
auto write_json_if_different(const std::filesystem::path &path,
137+
const sourcemeta::core::JSON &document) -> void;
138+
126139
private:
140+
auto output_write_json(const std::filesystem::path &path,
141+
const sourcemeta::core::JSON &document)
142+
-> const std::filesystem::path &;
143+
127144
std::filesystem::path root;
128145
std::unordered_map<std::filesystem::path, mark_type> marks;
129146
std::shared_mutex mutex;
130147
std::unordered_map<std::string, Dependencies> dependencies_map;
131148
mutable std::shared_mutex dependencies_mutex;
132149
bool has_previous_run{false};
150+
std::unordered_map<std::filesystem::path, bool> tracker;
151+
mutable std::shared_mutex tracker_mutex;
133152
};
134153

135154
} // namespace sourcemeta::one

src/index/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
sourcemeta_executable(NAMESPACE sourcemeta PROJECT one NAME index
22
FOLDER "One/Index"
3-
SOURCES index.cc output.h generators.h explorer.h)
3+
SOURCES index.cc generators.h explorer.h)
44

55
set_target_properties(sourcemeta_one_index PROPERTIES OUTPUT_NAME sourcemeta-one-index)
66

src/index/explorer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#include <sourcemeta/core/json.h>
99
#include <sourcemeta/core/jsonschema.h>
1010

11-
#include "output.h"
11+
#include <sourcemeta/one/build.h>
1212

1313
#include <algorithm> // std::sort
1414
#include <cassert> // assert
@@ -283,7 +283,7 @@ struct GENERATE_EXPLORER_DIRECTORY_LIST {
283283
struct Context {
284284
const std::filesystem::path &directory;
285285
const sourcemeta::one::Configuration &configuration;
286-
const sourcemeta::one::Output &output;
286+
const sourcemeta::one::Build &output;
287287
const std::filesystem::path &explorer_path;
288288
const std::filesystem::path &schemas_path;
289289
};

0 commit comments

Comments
 (0)