mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-10 00:48:23 -06:00
Return strings directly from read_file_as_utf8_string_if_exists (#17667)
* Every single place that called `read_file_as_utf8_string_if_exists`
would immediately do a `.value_or(std::string{})`.
As such, the function now returns a string directly.
* There was just one caller to `read_file_as_utf8_string`
and it only cared about files that are non-empty.
As such, the specialization got removed.
Both of these make sense to me, as in practice there's seldom
a difference between an empty file and a non-existent one.
## Validation Steps Performed
* Compiles ✅
* Starts ✅
* Deleting the `settings.json` contents triggers a reload ✅
This commit is contained in:
parent
9a0d784500
commit
dd5f2ad755
@ -923,13 +923,12 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||||||
{
|
{
|
||||||
// This returns an empty string if we fail to load the file.
|
// This returns an empty string if we fail to load the file.
|
||||||
std::filesystem::path localSnippetsPath{ std::wstring_view{ currentWorkingDirectory + L"\\.wt.json" } };
|
std::filesystem::path localSnippetsPath{ std::wstring_view{ currentWorkingDirectory + L"\\.wt.json" } };
|
||||||
const auto localTasksFileContents = til::io::read_file_as_utf8_string_if_exists(localSnippetsPath);
|
const auto data = til::io::read_file_as_utf8_string_if_exists(localSnippetsPath);
|
||||||
if (!localTasksFileContents.has_value() || localTasksFileContents->empty())
|
if (data.empty())
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& data = *localTasksFileContents;
|
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
std::string errs;
|
std::string errs;
|
||||||
const std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder{}.newCharReader() };
|
const std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder{}.newCharReader() };
|
||||||
|
|||||||
@ -146,7 +146,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||||||
std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder{}.newCharReader() };
|
std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder{}.newCharReader() };
|
||||||
|
|
||||||
// First get shared state out of `state.json`.
|
// First get shared state out of `state.json`.
|
||||||
const auto sharedData = _readSharedContents().value_or(std::string{});
|
const auto sharedData = _readSharedContents();
|
||||||
if (!sharedData.empty())
|
if (!sharedData.empty())
|
||||||
{
|
{
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
@ -165,7 +165,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||||||
FromJson(root, FileSource::Shared);
|
FromJson(root, FileSource::Shared);
|
||||||
|
|
||||||
// Then, try and get anything in elevated-state
|
// Then, try and get anything in elevated-state
|
||||||
if (const auto localData{ _readLocalContents().value_or(std::string{}) }; !localData.empty())
|
if (const auto localData{ _readLocalContents() }; !localData.empty())
|
||||||
{
|
{
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
if (!reader->parse(localData.data(), localData.data() + localData.size(), &root, &errs))
|
if (!reader->parse(localData.data(), localData.data() + localData.size(), &root, &errs))
|
||||||
@ -216,7 +216,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||||||
// First load the contents of state.json into a json blob. This will
|
// First load the contents of state.json into a json blob. This will
|
||||||
// contain the Shared properties and the unelevated instance's Local
|
// contain the Shared properties and the unelevated instance's Local
|
||||||
// properties.
|
// properties.
|
||||||
const auto sharedData = _readSharedContents().value_or(std::string{});
|
const auto sharedData = _readSharedContents();
|
||||||
if (!sharedData.empty())
|
if (!sharedData.empty())
|
||||||
{
|
{
|
||||||
if (!reader->parse(sharedData.data(), sharedData.data() + sharedData.size(), &root, &errs))
|
if (!reader->parse(sharedData.data(), sharedData.data() + sharedData.size(), &root, &errs))
|
||||||
@ -334,7 +334,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||||||
// - Read the contents of our "shared" state - state that should be shared
|
// - Read the contents of our "shared" state - state that should be shared
|
||||||
// for elevated and unelevated instances. This is things like the list of
|
// for elevated and unelevated instances. This is things like the list of
|
||||||
// generated profiles, the command palette commandlines.
|
// generated profiles, the command palette commandlines.
|
||||||
std::optional<std::string> ApplicationState::_readSharedContents() const
|
std::string ApplicationState::_readSharedContents() const
|
||||||
{
|
{
|
||||||
return til::io::read_file_as_utf8_string_if_exists(_sharedPath);
|
return til::io::read_file_as_utf8_string_if_exists(_sharedPath);
|
||||||
}
|
}
|
||||||
@ -346,7 +346,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||||||
// those don't matter when unelevated).
|
// those don't matter when unelevated).
|
||||||
// - When elevated, this will DELETE `elevated-state.json` if it has bad
|
// - When elevated, this will DELETE `elevated-state.json` if it has bad
|
||||||
// permissions, so we don't potentially read malicious data.
|
// permissions, so we don't potentially read malicious data.
|
||||||
std::optional<std::string> ApplicationState::_readLocalContents() const
|
std::string ApplicationState::_readLocalContents() const
|
||||||
{
|
{
|
||||||
return ::Microsoft::Console::Utils::IsRunningElevated() ?
|
return ::Microsoft::Console::Utils::IsRunningElevated() ?
|
||||||
til::io::read_file_as_utf8_string_if_exists(_elevatedPath, true) :
|
til::io::read_file_as_utf8_string_if_exists(_elevatedPath, true) :
|
||||||
|
|||||||
@ -95,9 +95,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
|||||||
|
|
||||||
Json::Value _toJsonWithBlob(Json::Value& root, FileSource parseSource) const noexcept;
|
Json::Value _toJsonWithBlob(Json::Value& root, FileSource parseSource) const noexcept;
|
||||||
|
|
||||||
std::optional<std::string> _readSharedContents() const;
|
std::string _readSharedContents() const;
|
||||||
void _writeSharedContents(const std::string_view content) const;
|
void _writeSharedContents(const std::string_view content) const;
|
||||||
std::optional<std::string> _readLocalContents() const;
|
std::string _readLocalContents() const;
|
||||||
void _writeLocalContents(const std::string_view content) const;
|
void _writeLocalContents(const std::string_view content) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -237,9 +237,12 @@ void SettingsLoader::FindFragmentsAndMergeIntoUserSettings()
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto content = til::io::read_file_as_utf8_string(fragmentExt.path());
|
const auto content = til::io::read_file_as_utf8_string_if_exists(fragmentExt.path());
|
||||||
|
if (!content.empty())
|
||||||
|
{
|
||||||
_parseFragment(source, content, fragmentSettings);
|
_parseFragment(source, content, fragmentSettings);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
CATCH_LOG();
|
CATCH_LOG();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -934,7 +937,7 @@ Model::CascadiaSettings CascadiaSettings::LoadAll()
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
FILETIME lastWriteTime{};
|
FILETIME lastWriteTime{};
|
||||||
auto settingsString = til::io::read_file_as_utf8_string_if_exists(_settingsPath(), false, &lastWriteTime).value_or(std::string{});
|
auto settingsString = til::io::read_file_as_utf8_string_if_exists(_settingsPath(), false, &lastWriteTime);
|
||||||
auto firstTimeSetup = settingsString.empty();
|
auto firstTimeSetup = settingsString.empty();
|
||||||
|
|
||||||
// If it's the firstTimeSetup and a preview build, then try to
|
// If it's the firstTimeSetup and a preview build, then try to
|
||||||
@ -947,7 +950,7 @@ try
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
settingsString = til::io::read_file_as_utf8_string_if_exists(_releaseSettingsPath()).value_or(std::string{});
|
settingsString = til::io::read_file_as_utf8_string_if_exists(_releaseSettingsPath());
|
||||||
releaseSettingExists = settingsString.empty() ? false : true;
|
releaseSettingExists = settingsString.empty() ? false : true;
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
|
|||||||
@ -53,8 +53,8 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||||||
} // details
|
} // details
|
||||||
|
|
||||||
// Tries to read a file somewhat atomically without locking it.
|
// Tries to read a file somewhat atomically without locking it.
|
||||||
// Strips the UTF8 BOM if it exists.
|
// Returns an empty string if the file couldn't be opened.
|
||||||
_TIL_INLINEPREFIX std::string read_file_as_utf8_string(const std::filesystem::path& path, const bool elevatedOnly = false, FILETIME* lastWriteTime = nullptr)
|
_TIL_INLINEPREFIX std::string read_file_as_utf8_string_if_exists(const std::filesystem::path& path, const bool elevatedOnly = false, FILETIME* lastWriteTime = nullptr)
|
||||||
{
|
{
|
||||||
// From some casual observations we can determine that:
|
// From some casual observations we can determine that:
|
||||||
// * ReadFile() always returns the requested amount of data (unless the file is smaller)
|
// * ReadFile() always returns the requested amount of data (unless the file is smaller)
|
||||||
@ -69,7 +69,16 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
nullptr) };
|
nullptr) };
|
||||||
THROW_LAST_ERROR_IF(!file);
|
|
||||||
|
if (!file)
|
||||||
|
{
|
||||||
|
const auto gle = GetLastError();
|
||||||
|
if (gle == ERROR_FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
THROW_WIN32(gle);
|
||||||
|
}
|
||||||
|
|
||||||
// Open the file _first_, then check if it has the right
|
// Open the file _first_, then check if it has the right
|
||||||
// permissions. This prevents a "Time-of-check to time-of-use"
|
// permissions. This prevents a "Time-of-check to time-of-use"
|
||||||
@ -92,7 +101,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||||||
LOG_LAST_ERROR_IF(!DeleteFile(path.c_str()));
|
LOG_LAST_ERROR_IF(!DeleteFile(path.c_str()));
|
||||||
|
|
||||||
// Exit early, because obviously there's nothing to read from the deleted file.
|
// Exit early, because obviously there's nothing to read from the deleted file.
|
||||||
return "";
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,24 +146,6 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||||||
THROW_WIN32_MSG(ERROR_READ_FAULT, "file size changed while reading");
|
THROW_WIN32_MSG(ERROR_READ_FAULT, "file size changed while reading");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same as read_file_as_utf8_string, but returns an empty optional, if the file couldn't be opened.
|
|
||||||
_TIL_INLINEPREFIX std::optional<std::string> read_file_as_utf8_string_if_exists(const std::filesystem::path& path, const bool elevatedOnly = false, FILETIME* lastWriteTime = nullptr)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return { read_file_as_utf8_string(path, elevatedOnly, lastWriteTime) };
|
|
||||||
}
|
|
||||||
catch (const wil::ResultException& exception)
|
|
||||||
{
|
|
||||||
if (exception.GetErrorCode() == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_TIL_INLINEPREFIX void write_utf8_string_to_file(const std::filesystem::path& path, const std::string_view& content, const bool elevatedOnly = false, FILETIME* lastWriteTime = nullptr)
|
_TIL_INLINEPREFIX void write_utf8_string_to_file(const std::filesystem::path& path, const std::string_view& content, const bool elevatedOnly = false, FILETIME* lastWriteTime = nullptr)
|
||||||
{
|
{
|
||||||
SECURITY_ATTRIBUTES sa;
|
SECURITY_ATTRIBUTES sa;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user