sapling/eden/fs/config/ConfigSource.h
Chad Austin fc48ab8614 add a ConfigSource layer of indirection between EdenConfig and the toml files
Summary:
EdenConfig had a bunch of hard-coded logic around stat()ing files and
parsing TOML.

Besides code clarity, this had several problems:
* Using an EdenConfig in a unit test would touch the actual filesystem.
* We didn't support reading configs from other sources. For example,
  we've talked about reading EdenConfig from .hgrc.
* ReloadableConfig knew too much about EdenConfig's internal working.
* Changing configs in tests involves calling setValue(), which is an
  unsafe API in the limit.

This diff introduces a new abstraction called ConfigSource, with one
implementation, TomlFileConfigSource.

ConfigSource can indicate that it's time for a reload, and can apply
its values to a non-const EdenConfig instance.

Reviewed By: kmancini

Differential Revision: D41830417

fbshipit-source-id: a0ff90c4a1adb870e4b34da5d16238a6e7b75be2
2023-01-04 12:53:34 -08:00

77 lines
1.9 KiB
C++

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This software may be used and distributed according to the terms of the
* GNU General Public License version 2.
*/
#pragma once
#include "eden/fs/config/FileChangeMonitor.h"
#include "eden/fs/config/gen-cpp2/eden_config_types.h"
namespace facebook::eden {
class ConfigSettingBase;
class ConfigVariables;
// This is a little gross. EdenConfig exposes its internal data structure here
// so ConfigSource can apply values to each setting with
// ConfigSettingBase::setStringValue.
//
// An intermediate abstraction might make sense in the future.
using ConfigSettingMap =
std::map<std::string, std::map<std::string, ConfigSettingBase*>>;
class ConfigSource {
public:
virtual ~ConfigSource() = default;
/**
* Returns the slot where this source lives in the config hierarchy.
*/
virtual ConfigSourceType getSourceType() = 0;
/**
* Returns the path to the file or URL backing this source.
* Returns an empty string if not relevant.
*/
virtual std::string getSourcePath() = 0;
/**
* Has the backing data changed? Should reload() be called?
*/
virtual FileChangeReason shouldReload() = 0;
/**
* Load and apply new values to the configuration `map`.
*/
virtual void reload(
const ConfigVariables& substitutions,
ConfigSettingMap& map) = 0;
};
class NullConfigSource final : public ConfigSource {
public:
explicit NullConfigSource(ConfigSourceType sourceType)
: sourceType_{sourceType} {}
ConfigSourceType getSourceType() override {
return sourceType_;
}
std::string getSourcePath() override {
return "";
}
FileChangeReason shouldReload() override {
return FileChangeReason::NONE;
}
void reload(
const ConfigVariables& /*substitutions*/,
ConfigSettingMap& /*map*/) override {}
private:
ConfigSourceType sourceType_;
};
} // namespace facebook::eden