Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 79 additions & 6 deletions ffs/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
#include "starlark/token.h"
#include "starlark/tokenizer.h"

#include <cassert>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <iterator>
#include <optional>
#include <sstream>
#include <string>
#include <string_view>
Expand All @@ -27,15 +30,49 @@ std::string to_string(std::vector<starlark::Token> const &tokens) {
return std::move(ss).str();
}

} // namespace
// Find the first directory w/ a MODULE.bazel above a given path.
std::optional<std::filesystem::path> project_root(std::filesystem::path from) {
assert(std::filesystem::is_directory(from));

int main(int argc, char **argv) {
if (argc != 2) {
std::string_view name = argv[0] != nullptr ? argv[0] : "<bin>";
std::cerr << "Usage: " << name << " <input_file>\n";
return 1;
do {
if (std::filesystem::exists(from / "MODULE.bazel")) {
return from;
}

from = from.parent_path();
std::cerr << from << std::endl;
} while (from != from.parent_path());

return std::nullopt;
}

std::optional<std::vector<std::filesystem::path>>
build_files_from_pattern(std::filesystem::path const &from, std::string_view pattern) {
if (pattern != "...") {
// TODO(robinlinden): Support patterns.
std::cerr << "Unsupported pattern '" << pattern << "'.\n";
return std::nullopt;
}

auto root_path = project_root(from);
if (!root_path) {
std::cerr << "Unable to find ffs project root for folder '" << from << "'.\n";
return std::nullopt;
}

std::vector<std::filesystem::path> found;
for (auto const &dir : std::filesystem::recursive_directory_iterator{from}) {
if (std::filesystem::exists(dir.path() / "BUILD.bazel")) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you take BUILD.bazel as an arg, it'll be easier to introduce ffs tagged files without cross contamination, ffs.build in one dir, but BUILD.bazel from another. (Worth supporting, just not implicitly)

found.push_back(dir.path() / "BUILD.bazel");
}
}

return found;
}

int run_debug(int argc, char **argv) {
assert(argc == 2);

auto input = std::ifstream{argv[1]};
if (!input) {
std::cerr << "Error: Could not open file " << argv[1] << "\n";
Expand All @@ -59,4 +96,40 @@ int main(int argc, char **argv) {
std::cerr << "Error: Failed to parse input.\n";
return 1;
}

return 0;
}

int run_query(int argc, char **argv) {
assert(argc == 3);

auto cwd = std::filesystem::current_path();
auto build_files = build_files_from_pattern(cwd, argv[2]);
if (!build_files) {
std::cerr << "Failed to find build files.\n";
return 1;
}

// TODO(robinlinden): Get targets from build files.
for (auto const &build_file : *build_files) {
std::cout << build_file << '\n';
}

return 0;
}

} // namespace

int main(int argc, char **argv) {
if (argc == 3 && argv[1] == std::string_view{"query"}) {
return run_query(argc, argv);
}

if (argc != 2) {
std::string_view name = argv[0] != nullptr ? argv[0] : "<bin>";
std::cerr << "Usage: " << name << " <input_file>\n";
return 1;
}

return run_debug(argc, argv);
}