Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 1 | // Copyright 2018 The Bazel Authors. All rights reserved. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | #ifndef BAZEL_SRC_MAIN_CPP_RC_FILE_H_ |
| 15 | #define BAZEL_SRC_MAIN_CPP_RC_FILE_H_ |
| 16 | |
Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 17 | #include <memory> |
Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 18 | #include <string> |
| 19 | #include <vector> |
| 20 | |
| 21 | #include "src/main/cpp/workspace_layout.h" |
Googler | d7feff5 | 2024-08-09 00:07:35 -0700 | [diff] [blame] | 22 | #include "absl/container/flat_hash_map.h" |
Googler | b74b7cf | 2024-09-11 23:30:14 -0700 | [diff] [blame] | 23 | #include "absl/functional/function_ref.h" |
Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 24 | |
| 25 | namespace blaze { |
| 26 | |
| 27 | // Single option in an rc file. |
| 28 | struct RcOption { |
Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 29 | std::string option; |
Googler | 1980fdb | 2020-09-01 13:49:34 -0700 | [diff] [blame] | 30 | // Only keep the index of the source file to avoid copying the paths all over. |
| 31 | // This index points into the RcFile's canonical_source_paths() vector. |
| 32 | int source_index; |
Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 33 | }; |
| 34 | |
| 35 | // Reads and parses a single rc file with all its imports. |
| 36 | class RcFile { |
| 37 | public: |
| 38 | // Constructs a parsed rc file object, or returns a nullptr and sets the |
| 39 | // error and error text on failure. |
Googler | b74b7cf | 2024-09-11 23:30:14 -0700 | [diff] [blame] | 40 | using ReadFileFn = |
| 41 | absl::FunctionRef<bool(const std::string&, std::string*, std::string*)>; |
| 42 | using CanonicalizePathFn = absl::FunctionRef<std::string(const std::string&)>; |
Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 43 | enum class ParseError { NONE, UNREADABLE_FILE, INVALID_FORMAT, IMPORT_LOOP }; |
| 44 | static std::unique_ptr<RcFile> Parse( |
Googler | d7feff5 | 2024-08-09 00:07:35 -0700 | [diff] [blame] | 45 | const std::string& filename, const WorkspaceLayout* workspace_layout, |
Googler | b74b7cf | 2024-09-11 23:30:14 -0700 | [diff] [blame] | 46 | const std::string& workspace, ParseError* error, std::string* error_text, |
| 47 | ReadFileFn read_file = &ReadFileDefault, |
| 48 | CanonicalizePathFn canonicalize_path = &CanonicalizePathDefault); |
Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 49 | |
Googler | 1980fdb | 2020-09-01 13:49:34 -0700 | [diff] [blame] | 50 | // Movable and copyable. |
| 51 | RcFile(const RcFile&) = default; |
| 52 | RcFile(RcFile&&) = default; |
| 53 | RcFile& operator=(const RcFile&) = default; |
| 54 | RcFile& operator=(RcFile&&) = default; |
| 55 | |
Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 56 | // Returns all relevant rc sources for this file (including itself). |
Googler | 1980fdb | 2020-09-01 13:49:34 -0700 | [diff] [blame] | 57 | const std::vector<std::string>& canonical_source_paths() const { |
Laszlo Csomor | 9b83bd7 | 2018-12-17 08:42:44 -0800 | [diff] [blame] | 58 | return canonical_rcfile_paths_; |
| 59 | } |
Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 60 | |
| 61 | // Command -> all options for that command (in order of appearance). |
Googler | d7feff5 | 2024-08-09 00:07:35 -0700 | [diff] [blame] | 62 | using OptionMap = absl::flat_hash_map<std::string, std::vector<RcOption>>; |
Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 63 | const OptionMap& options() const { return options_; } |
| 64 | |
| 65 | private: |
Googler | d7feff5 | 2024-08-09 00:07:35 -0700 | [diff] [blame] | 66 | RcFile() = default; |
Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 67 | |
| 68 | // Recursive call to parse a file and its imports. |
| 69 | ParseError ParseFile(const std::string& filename, |
Googler | d7feff5 | 2024-08-09 00:07:35 -0700 | [diff] [blame] | 70 | const std::string& workspace, |
| 71 | const WorkspaceLayout& workspace_layout, |
Googler | b74b7cf | 2024-09-11 23:30:14 -0700 | [diff] [blame] | 72 | ReadFileFn read_file, |
| 73 | CanonicalizePathFn canonicalize_path, |
Googler | d7feff5 | 2024-08-09 00:07:35 -0700 | [diff] [blame] | 74 | std::vector<std::string>& import_stack, |
Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 75 | std::string* error_text); |
| 76 | |
Googler | b74b7cf | 2024-09-11 23:30:14 -0700 | [diff] [blame] | 77 | static bool ReadFileDefault(const std::string& filename, |
| 78 | std::string* contents, std::string* error_msg); |
| 79 | static std::string CanonicalizePathDefault(const std::string& filename); |
| 80 | |
Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 81 | // Full closure of rcfile paths imported from this file (including itself). |
Laszlo Csomor | 9b83bd7 | 2018-12-17 08:42:44 -0800 | [diff] [blame] | 82 | // These are all canonical paths, created with blaze_util::MakeCanonical. |
| 83 | // This also means all of these paths should exist. |
Googler | 1980fdb | 2020-09-01 13:49:34 -0700 | [diff] [blame] | 84 | std::vector<std::string> canonical_rcfile_paths_; |
Googler | ebd28a9 | 2018-02-07 08:46:31 -0800 | [diff] [blame] | 85 | // All options parsed from the file. |
| 86 | OptionMap options_; |
| 87 | }; |
| 88 | |
| 89 | } // namespace blaze |
| 90 | |
| 91 | #endif // BAZEL_SRC_MAIN_CPP_RC_FILE_H_ |