From b97825efb699849b4f6f5d7c15dacca047d68f5b Mon Sep 17 00:00:00 2001 From: Trevor Hickey Date: Fri, 9 Aug 2024 11:43:31 -0400 Subject: [PATCH] updates --- .../program_options/program_options.cpp | 2 +- .../header_remover/task_executer.hcp | 2 + .../repo_tools/visibility_adjuster/BUILD | 35 ++++ .../visibility_adjuster/program_options/BUILD | 14 ++ .../program_options/program_options.cpp | 173 ++++++++++++++++++ .../program_options/program_options.hpp | 45 +++++ .../visibility_adjuster/task_executer.hcp | 158 ++++++++++++++++ .../visibility_adjuster.cpp | 11 ++ .../types/strings/observers/regex/lib.cpp | 12 ++ .../types/strings/observers/regex/lib.hpp | 2 + 10 files changed, 453 insertions(+), 1 deletion(-) create mode 100644 source/code/programs/repo_tools/visibility_adjuster/BUILD create mode 100644 source/code/programs/repo_tools/visibility_adjuster/program_options/BUILD create mode 100644 source/code/programs/repo_tools/visibility_adjuster/program_options/program_options.cpp create mode 100644 source/code/programs/repo_tools/visibility_adjuster/program_options/program_options.hpp create mode 100644 source/code/programs/repo_tools/visibility_adjuster/task_executer.hcp create mode 100644 source/code/programs/repo_tools/visibility_adjuster/visibility_adjuster.cpp diff --git a/source/code/programs/repo_tools/header_remover/program_options/program_options.cpp b/source/code/programs/repo_tools/header_remover/program_options/program_options.cpp index 85253a8f7..1badbb4c3 100644 --- a/source/code/programs/repo_tools/header_remover/program_options/program_options.cpp +++ b/source/code/programs/repo_tools/header_remover/program_options/program_options.cpp @@ -140,7 +140,7 @@ std::string Program_Options::Dir() const{ int Program_Options::Start_At() const{ int data = 0; if (vm.count("start-at")){ - data = vm["start-at"].as(); + data = vm["start-at"].as(); } return data; diff --git a/source/code/programs/repo_tools/header_remover/task_executer.hcp b/source/code/programs/repo_tools/header_remover/task_executer.hcp index 65de3768b..4b767be55 100644 --- a/source/code/programs/repo_tools/header_remover/task_executer.hcp +++ b/source/code/programs/repo_tools/header_remover/task_executer.hcp @@ -2,6 +2,7 @@ class ❪iostream❫ ❪string❫ ❪utility❫ +❪regex❫ ❪"code/programs/repo_tools/header_remover/program_options/program_options"❫ ❪"code/utilities/filesystem/paths/lib"❫ ❪"code/utilities/streams/filestreams/read_all/lib"❫ @@ -15,6 +16,7 @@ class ❪"code/utilities/types/strings/transformers/other/lib"❫ ❪"code/utilities/linguistics/computer/header_detection/cpp_header_detector"❫ ⚯ +❪regex❫ ⚞⚟ diff --git a/source/code/programs/repo_tools/visibility_adjuster/BUILD b/source/code/programs/repo_tools/visibility_adjuster/BUILD new file mode 100644 index 000000000..1fbc867af --- /dev/null +++ b/source/code/programs/repo_tools/visibility_adjuster/BUILD @@ -0,0 +1,35 @@ +package(default_visibility = ["//visibility:public"]) + +load("//bazel/rules/hcp:hcp.bzl", "hcp") +load("//bazel/rules/hcp:hcp_hdrs_derive.bzl", "hcp_hdrs_derive") +load("//bazel/rules/cpp:object.bzl", "cpp_object") +load("//bazel/rules/cpp:distributable_main.bzl", "distributable_cpp_main") + +hcp( + name = "task_executer", + deps = [ + "//code/programs/repo_tools/visibility_adjuster/program_options:lib", + "//code/utilities/build/profiler:profile_compilation_timer", + "//code/utilities/filesystem/paths:lib", + "//code/utilities/linguistics/computer/header_detection:cpp_header_detector", + "//code/utilities/program/call/process_spawn:process_spawner", + "//code/utilities/streams/filestreams/read_all:lib", + "//code/utilities/streams/filestreams/write_all:lib", + "//code/utilities/types/strings/observers/other:lib", + "//code/utilities/types/strings/transformers/other:lib", + "//code/utilities/types/strings/transformers/trimming:lib", + "//code/utilities/filesystem/files/getting:lib", + "//code/utilities/types/strings/observers/regex:lib", + ], +) + +distributable_cpp_main( + name = "visibility_adjuster", + depends = [ + ], + description = "adjusts visibility on bazel BUILD files", + deps = [ + "//code/programs/repo_tools/visibility_adjuster:task_executer", + "//code/programs/repo_tools/visibility_adjuster/program_options:lib", + ], +) diff --git a/source/code/programs/repo_tools/visibility_adjuster/program_options/BUILD b/source/code/programs/repo_tools/visibility_adjuster/program_options/BUILD new file mode 100644 index 000000000..17f1e4ac8 --- /dev/null +++ b/source/code/programs/repo_tools/visibility_adjuster/program_options/BUILD @@ -0,0 +1,14 @@ +package(default_visibility = ["//visibility:public"]) + +load("//bazel/rules/hcp:hcp.bzl", "hcp") +load("//bazel/rules/hcp:hcp_hdrs_derive.bzl", "hcp_hdrs_derive") +load("//bazel/rules/cpp:object.bzl", "cpp_object") + +cc_library( + name = "lib", + srcs = glob(["*.cpp"]), + hdrs = glob(["*.hpp"]), + deps = [ + "@boost//:program_options", + ], +) diff --git a/source/code/programs/repo_tools/visibility_adjuster/program_options/program_options.cpp b/source/code/programs/repo_tools/visibility_adjuster/program_options/program_options.cpp new file mode 100644 index 000000000..50453b796 --- /dev/null +++ b/source/code/programs/repo_tools/visibility_adjuster/program_options/program_options.cpp @@ -0,0 +1,173 @@ + +#include "program_options.hpp" +#include +#include +#include +#include + +//constructor +Program_Options::Program_Options(int const& argc, char** const& argv){ + using namespace boost::program_options; + + //build all the possible flags and add description. + options_description desc (Get_Options_Description()); + + //set positional arguments + positional_options_description pod; + pod.add("query", -1); + + //build variable map + Build_Variable_Map(argc,argv,desc,pod); + + //process immediate options + Process_Immediate_Options(desc); + + //validate the mandatory flags + Check_For_Mandatory_Flags_Not_Passed(); +} +boost::program_options::options_description Program_Options::Get_Options_Description(void){ + using namespace boost::program_options; + + //Program Description + options_description desc("adjust bazel visibility across a codebase."); + + //Program Flags + desc.add_options() + + //these are flag descriptions of that can be passed into the class. + //the code inserted, are the flags added by the user through the + //program_options_maker flag interface + ("run_dir",value(),"where to run the analysis") + ("file",value(),"the file to remove headers from") + ("dir",value(),"the dir to remove headers from") + ("target",value(),"target to check with") + ("commands",value>(),"commands to check with") + ("start-at",value(),"where to start in the file iteration") + ("find",value(),"regex to match on") + ("replace",value(),"what to replace the regex match with") + + //+----------------------------------------------------------+ + //| Obligatory | + //+----------------------------------------------------------+ + ("help,h","produce this help message") + ("version,v","display version") + ; + + return desc; +} +std::string Program_Options::Get_Help_Message(){ + std::stringstream ss; + ss << Get_Options_Description(); + return ss.str(); +} +void Program_Options::Build_Variable_Map(int const& argc, char** const& argv, boost::program_options::options_description const& desc, boost::program_options::positional_options_description const& pod){ + using namespace boost::program_options; + + //store user flag data. crash elegantly if they pass incorrect flags. + try{ + store(command_line_parser(argc, argv).options(desc).positional(pod).run(), vm); + notify(vm); + } + catch(error& e){ + std::cerr << "ERROR: " << e.what() << std::endl; + std::cerr << desc << std::endl; + exit(EXIT_FAILURE); + } + + return; +} +void Program_Options::Process_Immediate_Options( boost::program_options::options_description const& desc){ + + //do not continue the program if the user wanted to see the version or help data + if (vm.count("version")){ + std::cout << "\nThis is version " << "1" << " of noogle.\n\n"; + exit(EXIT_SUCCESS); + } + else if (vm.count("help")){ + std::cout << '\n' << desc << '\n'; + exit(EXIT_SUCCESS); + } + + return; +} + +void Program_Options::Check_For_Mandatory_Flags_Not_Passed(){ + std::vector flags_not_passed; + //if(!vm.count("input_files")){flags_not_passed.push_back("input_files");} + //if(!vm.count("exporter")){flags_not_passed.push_back("exporter");} + //if(!vm.count("language")){flags_not_passed.push_back("language");} + + if (!flags_not_passed.empty()){ + std::cerr << "you need to pass the following flags still:\n"; + for (auto it: flags_not_passed){ + std::cerr << '\t' << it << '\n'; + } + exit(EXIT_FAILURE); + } + return; +} +std::string Program_Options::Run_Dir() const{ + std::string data; + if (vm.count("run_dir")){ + data = vm["run_dir"].as(); + } + + return data; +} +std::string Program_Options::File() const{ + std::string data; + if (vm.count("file")){ + data = vm["file"].as(); + } + + return data; +} +std::string Program_Options::Target() const{ + std::string data; + if (vm.count("target")){ + data = vm["target"].as(); + } + + return data; +} +std::string Program_Options::Dir() const{ + std::string data; + if (vm.count("dir")){ + data = vm["dir"].as(); + } + + return data; +} + +int Program_Options::Start_At() const{ + int data = 0; + if (vm.count("start-at")){ + data = vm["start-at"].as(); + } + + return data; +} + +std::string Program_Options::Find() const{ + std::string data; + if (vm.count("find")){ + data = vm["find"].as(); + } + return data; +} +std::string Program_Options::Replace() const{ + std::string data; + if (vm.count("replace")){ + data = vm["replace"].as(); + } + return data; +} + +std::vector Program_Options::Commands() const{ + std::vector data; + if (vm.count("commands")){ + data = vm["commands"].as>(); + } + + return data; +} diff --git a/source/code/programs/repo_tools/visibility_adjuster/program_options/program_options.hpp b/source/code/programs/repo_tools/visibility_adjuster/program_options/program_options.hpp new file mode 100644 index 000000000..87580714d --- /dev/null +++ b/source/code/programs/repo_tools/visibility_adjuster/program_options/program_options.hpp @@ -0,0 +1,45 @@ +#pragma once + +//Boost Libraries +#include "boost/program_options.hpp" + +class Program_Options { + + public: + + //Constructor + explicit Program_Options(int const& argc, char** const& argv); + + //These are functions for the client who uses the Program Options object. + //They include all of the functions passed to the program_options_maker. + //The options "help" and "version", do not need to be implemented by the user. + //The "help" and "version" flags are always added automatically unless specified not to be. + //+----------------------------------------------------------+ + //| USER FLAGS | + //+----------------------------------------------------------+ + std::string Run_Dir() const; + std::string File() const; + std::string Dir() const; + std::string Target() const; + std::vector Commands() const; + int Start_At() const; + std::string Find() const; + std::string Replace() const; + + + std::string Get_Help_Message(); + + + private: + + //functions used to parse, store, verify, and immediately process SOME of the flags. + //other verification of flag data is passed on as a responsibility of the Program_Options_Checker + auto Get_Options_Description() -> boost::program_options::options_description; + auto Build_Variable_Map(int const& argc, char** const& argv, boost::program_options::options_description const& desc, boost::program_options::positional_options_description const& pod) -> void; + auto Process_Immediate_Options(boost::program_options::options_description const& desc) -> void; + auto Check_For_Mandatory_Flags_Not_Passed() -> void; + + //Data Members + //the variables map, holds all of the flag data passed in through the constructor. + boost::program_options::variables_map vm; +}; diff --git a/source/code/programs/repo_tools/visibility_adjuster/task_executer.hcp b/source/code/programs/repo_tools/visibility_adjuster/task_executer.hcp new file mode 100644 index 000000000..e86a3c491 --- /dev/null +++ b/source/code/programs/repo_tools/visibility_adjuster/task_executer.hcp @@ -0,0 +1,158 @@ +class +❪iostream❫ +❪string❫ +❪utility❫ +❪regex❫ +❪"code/programs/repo_tools/visibility_adjuster/program_options/program_options"❫ +❪"code/utilities/filesystem/paths/lib"❫ +❪"code/utilities/streams/filestreams/read_all/lib"❫ +❪"code/utilities/streams/filestreams/write_all/lib"❫ +❪"code/utilities/filesystem/files/getting/lib"❫ + +❪"code/utilities/program/call/process_spawn/process_spawner"❫ +❪"code/utilities/types/strings/observers/other/lib"❫ +❪"code/utilities/types/strings/transformers/trimming/lib"❫ +❪"code/utilities/build/profiler/profile_compilation_timer"❫ +❪"code/utilities/types/strings/transformers/other/lib"❫ +❪"code/utilities/linguistics/computer/header_detection/cpp_header_detector"❫ +❪"code/utilities/types/strings/observers/regex/lib"❫ +⚯ +⚞⚟ + + +◀public: static▶ void ☀Execute_Needed_Tasks(Program_Options const& options) ❰ + + + //step into the repo + Set_Path(options.Run_Dir()); + + bool passes = Test_That_Code_Builds(options); + if (!passes){ + std::cerr << "Doesn't pass to begin with." << std::endl; + std::cerr << "We won't be able to evaluate pruning if the build is already failing." << std::endl; + exit(-1); + } + + //get all the files to prune + auto files = Get_All_Files_To_Prune(options); + std::cout << "Files to prune: " << files.size(); + for (size_t i = options.Start_At(); i < files.size(); ++i){ + std::cout << "[ " << i+1 << " / " << files.size() << " ]" << std::endl; + Prune_File(files[i],options); + } + +❱ + +◀private: static▶ std::string ☀Search_And_Replace(const std::string& input, const std::regex& pattern, const std::string& replacement) ❰ + return std::regex_replace(input, pattern, replacement); +❱ + +◀private: static▶ void ☀Prune_File(std::string file, Program_Options const& options) ❰ + + //open the file + auto file_lines = Read_Each_Line_Of_File_Into_Vector(file); + + auto file_indexes = Get_Indexes_Where_Regex_Matches(file_lines,options.Find()); + + std::cout << file_indexes.size() << " visibilities detected." << std::endl; + //std::cout << Profile_Compilation_Timer::Profile(file) << std::endl; + + //try to remove each header + for (auto index: file_indexes){ + + auto visibility_line = file_lines[index]; + + //get rid of the include statement + file_lines[index] = Search_And_Replace(file_lines[index],std::regex(options.Find()),options.Replace()); + Write_Each_Line_Of_Vector_Into_File(file,file_lines); + + std::cout << "removing " << visibility_line << " "; + + //test the removal + //auto profile_time = Profile_Compilation_Timer::Profile(file); + auto successfully_removed = Test_That_Code_Builds(options); + + + //the header can stay removed + if (successfully_removed){ + std::cout << "REMOVED " << std::endl; + } + + + //the header can not stay removed + else{ + std::cout << "REQUIRED" << std::endl; + + //restore header + file_lines[index] = visibility_line; + Write_Each_Line_Of_Vector_Into_File(file,file_lines); + } + } + + + //print how many visibilities were fixed + auto file_indexes_after = Get_Indexes_Where_Regex_Matches(file_lines,options.Find()); + auto visibilities_fixed = file_indexes.size() - file_indexes_after.size(); + std::cout << visibilities_fixed << " visibilities fixed." << std::endl; + +❱ + +◀private: static▶ std::vector ☀Get_All_Files_To_Prune(Program_Options const& options) ❰ + std::vector files; + + // Do a single file + if (!options.File().empty()){ + files.emplace_back(options.File()); + return files; + } + + //Do many files + files = Recursively_Get_All_Paths_To_Files_From_Path(options.Dir()); + + return files; + +❱ + +◀private: static▶ bool ☀Test_Via_Compilation_Target(Program_Options const& options) ❰ + + std::string command; + command += "./bazel build "; + command += options.Target(); + + auto results = Process_Spawner::Execute_And_Get_Back_Results(command); + + if (results.return_code != 0){ + return false; + } + + return true; +❱ + +◀private: static▶ bool ☀Test_That_Code_Builds(Program_Options const& options) ❰ + + bool show_stderr = false; + + //precondition check + if (options.Commands().empty() && options.Target().empty()){ + std::cerr << "Need to pass commands or target." << std::endl; + exit(0); + } + + //strategy 1 + if (!options.Target().empty()){ + return Test_Via_Compilation_Target(options); + } + + //strategy 2 + for (auto command: options.Commands()){ + auto results = Process_Spawner::Execute_And_Get_Back_Results(command); + if (results.return_code != 0){ + if (show_stderr){ + std::cerr << "ERROR: " << results.stderr << std::endl; + } + return false; + } + } + + return true; +❱ \ No newline at end of file diff --git a/source/code/programs/repo_tools/visibility_adjuster/visibility_adjuster.cpp b/source/code/programs/repo_tools/visibility_adjuster/visibility_adjuster.cpp new file mode 100644 index 000000000..e7d5c2b26 --- /dev/null +++ b/source/code/programs/repo_tools/visibility_adjuster/visibility_adjuster.cpp @@ -0,0 +1,11 @@ +#include +#include "code/programs/repo_tools/visibility_adjuster/task_executer.hpp" +#include "code/programs/repo_tools/visibility_adjuster/program_options/program_options.hpp" + + +int main(int const argc, char** const argv){ + + Program_Options program_options(argc, argv); + Task_Executer::Execute_Needed_Tasks(program_options); +} + diff --git a/source/code/utilities/types/strings/observers/regex/lib.cpp b/source/code/utilities/types/strings/observers/regex/lib.cpp index 23d318719..04ca606fc 100644 --- a/source/code/utilities/types/strings/observers/regex/lib.cpp +++ b/source/code/utilities/types/strings/observers/regex/lib.cpp @@ -28,4 +28,16 @@ std::vector Get_Regex_Matches(std::vector lines, std:: } return result; +} + +std::vector Get_Indexes_Where_Regex_Matches(std::vector lines, std::string const& regex) +{ + std::vector results; + for (size_t i = 0; i < lines.size(); ++i) + { + if (Matches_Regex(lines[i],regex)){ + results.emplace_back(i); + } + } + return results; } \ No newline at end of file diff --git a/source/code/utilities/types/strings/observers/regex/lib.hpp b/source/code/utilities/types/strings/observers/regex/lib.hpp index c8ca1ee32..203df08fc 100644 --- a/source/code/utilities/types/strings/observers/regex/lib.hpp +++ b/source/code/utilities/types/strings/observers/regex/lib.hpp @@ -8,3 +8,5 @@ bool Matches_Regex(std::string const& str, std::string const& regex); bool Matches_Any_Regex(std::string const& str, std::vector const& regexes); std::vector Get_Regex_Matches(std::vector lines, std::string const& regex); + +std::vector Get_Indexes_Where_Regex_Matches(std::vector lines, std::string const& regex);