-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
556 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") | ||
|
||
cc_library( | ||
name = "add_module", | ||
hdrs = ["add_module.hh"], | ||
srcs = ["add_module.cc"], | ||
deps = [ | ||
":get_registries", | ||
":find_workspace_dir", | ||
":download_module_metadata", | ||
"@boost.process", | ||
], | ||
) | ||
cc_library( | ||
name = "init_module", | ||
hdrs = ["init_module.hh"], | ||
srcs = ["init_module.cc"], | ||
deps = [ | ||
"@abseil-cpp//absl/strings", | ||
], | ||
) | ||
cc_library( | ||
name = "download_module_metadata", | ||
hdrs = ["download_module_metadata.hh"], | ||
srcs = ["download_module_metadata.cc"], | ||
deps = [ | ||
"//bzlreg:download", | ||
"//bzlreg:config_types", | ||
], | ||
) | ||
|
||
cc_library( | ||
name = "get_registries", | ||
hdrs = ["get_registries.hh"], | ||
srcs = ["get_registries.cc"], | ||
deps = [ | ||
"@abseil-cpp//absl/strings", | ||
], | ||
) | ||
cc_library( | ||
name = "find_workspace_dir", | ||
hdrs = ["find_workspace_dir.hh"], | ||
srcs = ["find_workspace_dir.cc"], | ||
deps = [ | ||
], | ||
) | ||
|
||
cc_binary( | ||
name = "bzlmod", | ||
srcs = ["bzlmod.cc"], | ||
deps = [ | ||
"@docopt.cpp//:docopt", | ||
":add_module", | ||
":init_module", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
#include "bzlmod/add_module.hh" | ||
|
||
#include <filesystem> | ||
#include <iostream> | ||
#include <algorithm> | ||
#include <execution> | ||
#include <format> | ||
#include <boost/process.hpp> | ||
#include "bzlmod/get_registries.hh" | ||
#include "bzlmod/find_workspace_dir.hh" | ||
#include "bzlmod/download_module_metadata.hh" | ||
|
||
namespace bp = boost::process; | ||
namespace fs = std::filesystem; | ||
|
||
struct registry_resolve_entry { | ||
std::string_view registry; | ||
std::string module_version; | ||
}; | ||
|
||
auto bzlmod::add_module( // | ||
std::string_view dep_name | ||
) -> int { | ||
auto buildozer = bp::search_path("buildozer"); | ||
if(buildozer.empty()) { | ||
std::cerr << std::format( | ||
"[ERROR] `buildozer` is required to use `bzlmod add`. Please make sure " | ||
"it's in your PATH. Buildozer may be downloaded here:\n" | ||
" https://github.com/bazelbuild/buildtools/releases\n\n" | ||
); | ||
return 1; | ||
} | ||
|
||
auto workspace_dir = find_workspace_dir(fs::current_path()); | ||
|
||
if(!workspace_dir) { | ||
std::cerr << std::format( | ||
"[ERROR] Cannot find bazel workspace from {}." | ||
" Did you mean `bzlmod init`?\n", | ||
fs::current_path().generic_string() | ||
); | ||
return 1; | ||
} | ||
|
||
auto registries = get_registries(*workspace_dir); | ||
|
||
if(!registries) { | ||
std::cerr << "[ERROR] Unable to read .bazelrc file(s)\n"; | ||
return 1; | ||
} | ||
|
||
auto registry_resolve_entries = std::vector<registry_resolve_entry>{}; | ||
registry_resolve_entries.reserve(registries->size()); | ||
for(auto& registry : *registries) { | ||
registry_resolve_entries.emplace_back(registry, ""); | ||
} | ||
|
||
std::for_each( | ||
std::execution::par, | ||
registry_resolve_entries.begin(), | ||
registry_resolve_entries.end(), | ||
[&](registry_resolve_entry& entry) { | ||
auto metadata_url = std::format( // | ||
"{}/modules/{}/metadata.json", | ||
entry.registry, | ||
dep_name | ||
); | ||
auto metadata = bzlmod::download_module_metadata(metadata_url); | ||
|
||
if(metadata && !metadata->versions.empty()) { | ||
entry.module_version = metadata->versions.back(); | ||
} | ||
} | ||
); | ||
|
||
auto dep_version = std::optional<std::string>{}; | ||
|
||
for(auto& entry : registry_resolve_entries) { | ||
if(!entry.module_version.empty()) { | ||
dep_version = entry.module_version; | ||
break; | ||
} | ||
} | ||
|
||
if(!dep_version) { | ||
std::cerr << "Failed to find " << dep_name << " in:\n"; | ||
for(auto& entry : registry_resolve_entries) { | ||
std::cerr << "\t" << entry.registry << "\n"; | ||
} | ||
return 1; | ||
} | ||
|
||
std::cout << "Found version for " << dep_name << ": " << *dep_version << "\n"; | ||
|
||
bp::child{ | ||
bp::exe(buildozer), | ||
bp::args({ | ||
std::format("new bazel_dep {}", dep_name), | ||
"//MODULE.bazel:all", | ||
}), | ||
}.wait(); | ||
|
||
|
||
bp::child{ | ||
bp::exe(buildozer), | ||
bp::args({ | ||
std::format("set version {}", *dep_version), | ||
std::format("//MODULE.bazel:{}", dep_name), | ||
}), | ||
}.wait(); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#pragma once | ||
|
||
#include <string_view> | ||
|
||
namespace bzlmod { | ||
auto add_module( // | ||
std::string_view dep_name | ||
) -> int; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#include <filesystem> | ||
#include <iostream> | ||
#include "docopt.h" | ||
#include "bzlmod/init_module.hh" | ||
#include "bzlmod/add_module.hh" | ||
|
||
namespace fs = std::filesystem; | ||
|
||
constexpr auto USAGE = R"docopt( | ||
Bzlmod - manage your bazel module with _ease_ | ||
Usage: | ||
bzlmod init [<module-dir>] | ||
bzlmod add <dep-name> | ||
)docopt"; | ||
|
||
auto main(int argc, char* argv[]) -> int { | ||
auto bazel_working_dir = std::getenv("BUILD_WORKING_DIRECTORY"); | ||
if(bazel_working_dir != nullptr) { | ||
fs::current_path(bazel_working_dir); | ||
} | ||
|
||
auto args = docopt::docopt(USAGE, {argv + 1, argv + argc}); | ||
auto exit_code = int{0}; | ||
|
||
if(args["init"].asBool()) { | ||
auto module_dir = args["<module-dir>"] // | ||
? fs::path{args.at("<module-dir>").asString()} | ||
: fs::current_path(); | ||
|
||
exit_code = bzlmod::init_module(module_dir); | ||
} else if(args["add"].asBool()) { | ||
auto dep_name = args["<dep-name>"].asString(); | ||
exit_code = bzlmod::add_module(dep_name); | ||
} | ||
|
||
return exit_code; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#include "bzlmod/download_module_metadata.hh" | ||
|
||
#include "nlohmann/json.hpp" | ||
#include "bzlreg/download.hh" | ||
|
||
using nlohmann::json; | ||
|
||
auto bzlmod::download_module_metadata( // | ||
std::string_view url | ||
) -> std::optional<bzlreg::metadata_config> { | ||
auto data = bzlreg::download_file(url); | ||
if(!data) { | ||
return std::nullopt; | ||
} | ||
|
||
bzlreg::metadata_config metadata = json::parse(*data); | ||
return metadata; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#pragma once | ||
|
||
#include <string_view> | ||
#include <optional> | ||
#include "bzlreg/config_types.hh" | ||
|
||
namespace bzlmod { | ||
auto download_module_metadata( // | ||
std::string_view url | ||
) -> std::optional<bzlreg::metadata_config>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#include "bzlmod/find_workspace_dir.hh" | ||
|
||
#include <filesystem> | ||
|
||
namespace fs = std::filesystem; | ||
|
||
auto bzlmod::find_workspace_dir( // | ||
std::filesystem::path start_dir | ||
) -> std::optional<std::filesystem::path> { | ||
if(fs::exists(start_dir / "MODULE.bazel")) { | ||
return start_dir; | ||
} | ||
|
||
if(start_dir.has_parent_path()) { | ||
return find_workspace_dir(start_dir.parent_path()); | ||
} | ||
|
||
return std::nullopt; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#pragma once | ||
|
||
#include <filesystem> | ||
#include <optional> | ||
|
||
namespace bzlmod { | ||
auto find_workspace_dir( | ||
std::filesystem::path start_dir | ||
) -> std::optional<std::filesystem::path>; | ||
} |
Oops, something went wrong.