blob: c49d94bdde0733f5bae481a7e3e3fe28cde99bd2 [file] [log] [blame] [edit]
// Copyright 2018 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef BAZEL_SRC_MAIN_CPP_RC_FILE_H_
#define BAZEL_SRC_MAIN_CPP_RC_FILE_H_
#include <memory>
#include <string>
#include <vector>
#include "src/main/cpp/sem_ver.h"
#include "src/main/cpp/workspace_layout.h"
#include "absl/container/flat_hash_map.h"
#include "absl/functional/function_ref.h"
namespace blaze {
// Single option in an rc file.
struct RcOption {
std::string option;
// Only keep the index of the source file to avoid copying the paths all over.
// This index points into the RcFile's canonical_source_paths() vector.
int source_index;
};
// Reads and parses a single rc file with all its imports.
class RcFile {
public:
// Constructs a parsed rc file object, or returns a nullptr and sets the
// error and error text on failure.
using ReadFileFn =
absl::FunctionRef<bool(const std::string&, std::string*, std::string*)>;
using CanonicalizePathFn = absl::FunctionRef<std::string(const std::string&)>;
enum class ParseError { NONE, UNREADABLE_FILE, INVALID_FORMAT, IMPORT_LOOP };
static std::unique_ptr<RcFile> Parse(
const std::string& filename, const WorkspaceLayout* workspace_layout,
const std::string& workspace, const std::string& build_label,
const std::optional<SemVer>& sem_ver, ParseError* error,
std::string* error_text, ReadFileFn read_file = &ReadFileDefault,
CanonicalizePathFn canonicalize_path = &CanonicalizePathDefault);
static std::unique_ptr<RcFile> Parse(
const std::string& filename, const WorkspaceLayout* workspace_layout,
const std::string& workspace, ParseError* error,
std::string* error_text, ReadFileFn read_file = &ReadFileDefault,
CanonicalizePathFn canonicalize_path = &CanonicalizePathDefault);
// Movable and copyable.
RcFile(const RcFile&) = default;
RcFile(RcFile&&) = default;
RcFile& operator=(const RcFile&) = default;
RcFile& operator=(RcFile&&) = default;
// Returns all relevant rc sources for this file (including itself).
const std::vector<std::string>& canonical_source_paths() const {
return canonical_rcfile_paths_;
}
// Command -> all options for that command (in order of appearance).
using OptionMap = absl::flat_hash_map<std::string, std::vector<RcOption>>;
const OptionMap& options() const { return options_; }
private:
RcFile() = default;
// Recursive call to parse a file and its imports.
ParseError ParseFile(
const std::string& filename, const std::string& workspace,
const WorkspaceLayout& workspace_layout, const std::string& build_label,
const std::optional<SemVer>& sem_ver, ReadFileFn read_file,
CanonicalizePathFn canonicalize_path,
std::vector<std::string>& import_stack, std::string* error_text);
ParseError ParseFile(
const std::string& filename, const std::string& workspace,
const WorkspaceLayout& workspace_layout, ReadFileFn read_file,
CanonicalizePathFn canonicalize_path,
std::vector<std::string>& import_stack, std::string* error_text);
static bool ReadFileDefault(const std::string& filename,
std::string* contents, std::string* error_msg);
static std::string CanonicalizePathDefault(const std::string& filename);
// Full closure of rcfile paths imported from this file (including itself).
// These are all canonical paths, created with blaze_util::MakeCanonical.
// This also means all of these paths should exist.
std::vector<std::string> canonical_rcfile_paths_;
// All options parsed from the file.
OptionMap options_;
};
// Checks if the build label passes the given comparison operation and
// condition. An empty return (nullopt) indicates a failure and error_text will
// be filled.
//
// Eg. The following values would evaluate to true since 8.4.5 >= 5.4.0
// - build_label=8.4.5
// - op='>='
// - compare_version=5.4.0
std::optional<bool> BazelVersionMatchesCondition(
const SemVer& build_label, absl::string_view op,
const std::string& compare_version, std::string* error_text);
} // namespace blaze
#endif // BAZEL_SRC_MAIN_CPP_RC_FILE_H_