[Updating] Add versioning to UpdateState.json (#12744)

- fix "Check for updates" hang if UpdateState.json was deleted while the page is open
This commit is contained in:
Andrey Nekrasov
2021-08-12 14:53:51 +03:00
committed by GitHub
parent 0b509a2d0b
commit 05f12dcdf1
8 changed files with 141 additions and 73 deletions

View File

@@ -3,12 +3,15 @@
#include <common/utils/json.h>
#include <common/utils/timeutil.h>
#include <common/version/helper.h>
#include <common/version/version.h>
#include <common/SettingsAPI/settings_helpers.h>
namespace
{
const wchar_t PERSISTENT_STATE_FILENAME[] = L"\\UpdateState.json";
const wchar_t UPDATE_STATE_MUTEX[] = L"Local\\PowerToysRunnerUpdateStateMutex";
const VersionHelper CURRENT_VERSION(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION);
}
UpdateState deserialize(const json::JsonObject& json)
@@ -34,19 +37,40 @@ json::JsonObject serialize(const UpdateState& state)
json.SetNamedValue(L"state", json::value(static_cast<double>(state.state)));
json.SetNamedValue(L"downloadedInstallerFilename", json::value(state.downloadedInstallerFilename));
json.SetNamedValue(L"updateStateFileVersion", json::value(CURRENT_VERSION.toWstring()));
return json;
}
bool IsOldFileVersion(const std::wstring_view fileVersion)
{
if (fileVersion == L"")
{
return true;
}
const auto parsedVer = VersionHelper::fromString(fileVersion);
return !parsedVer.has_value() || *parsedVer != CURRENT_VERSION;
}
UpdateState UpdateState::read()
{
const auto filename = PTSettingsHelper::get_root_save_folder_location() + PERSISTENT_STATE_FILENAME;
std::optional<json::JsonObject> json;
wil::unique_mutex_nothrow mutex{ CreateMutexW(nullptr, FALSE, UPDATE_STATE_MUTEX) };
auto lock = mutex.acquire();
json = json::from_file(filename);
if (json.has_value() && !IsOldFileVersion(json->GetNamedString(L"updateStateFileVersion", L"").c_str()))
{
wil::unique_mutex_nothrow mutex{ CreateMutexW(nullptr, FALSE, UPDATE_STATE_MUTEX) };
auto lock = mutex.acquire();
json = json::from_file(filename);
return deserialize(*json);
}
else
{
std::error_code _;
fs::remove(filename, _);
return UpdateState{};
}
return json ? deserialize(*json) : UpdateState{};
}
void UpdateState::store(std::function<void(UpdateState&)> stateModifier)