Crudely bodge image writes into working.

This commit is contained in:
David Given
2025-10-17 23:41:16 +02:00
parent 5b7f9d84f9
commit 0fd1aa82a6
11 changed files with 174 additions and 51 deletions

View File

@@ -451,6 +451,29 @@ bool Config::applyOption(const std::string& name, const std::string value)
return optionInfo.usesValue;
}
void Config::applyOptionsFile(const std::string& data)
{
if (!data.empty())
{
for (auto setting : split(data, '\n'))
{
setting = trimWhitespace(setting);
if (setting.size() == 0)
continue;
if (setting[0] == '#')
continue;
auto equals = setting.find('=');
if (equals == std::string::npos)
error("Malformed setting line '{}'", setting);
auto key = setting.substr(0, equals);
auto value = setting.substr(equals + 1);
globalConfig().set(key, value);
}
}
}
void Config::applyDefaultOptions()
{
std::set<const OptionGroupProto*> appliedOptionGroups;

View File

@@ -142,6 +142,7 @@ public:
bool isOptionValid(const OptionProto& option);
void applyOption(const OptionInfo& optionInfo);
bool applyOption(const std::string& name, const std::string value = "");
void applyOptionsFile(const std::string& data);
void applyDefaultOptions();
void clearOptions();

View File

@@ -540,12 +540,13 @@ findAllPossibleProtoFields(const google::protobuf::Descriptor* descriptor)
return fields;
}
std::vector<ProtoField> findAllProtoFields(google::protobuf::Message* message)
std::vector<ProtoField> findAllProtoFields(
const google::protobuf::Message* message)
{
std::vector<ProtoField> allFields;
std::function<void(google::protobuf::Message*, const std::string&)>
recurse = [&](auto* message, const auto& name)
std::function<void(const google::protobuf::Message*, const std::string&)>
recurse = [&](const auto* message, const auto& name)
{
const auto* reflection = message->GetReflection();
std::vector<const google::protobuf::FieldDescriptor*> fields;
@@ -565,18 +566,19 @@ std::vector<ProtoField> findAllProtoFields(google::protobuf::Message* message)
const auto n = fmt::format("{}[{}]", basename, i);
if (shouldRecurse(f))
recurse(
reflection->MutableRepeatedMessage(message, f, i),
n);
&reflection->GetRepeatedMessage(*message, f, i), n);
else
allFields.push_back(ProtoField(n, message, f, i));
allFields.push_back(ProtoField(
n, (google::protobuf::Message*)message, f, i));
}
}
else
{
if (shouldRecurse(f))
recurse(reflection->MutableMessage(message, f), basename);
recurse(&reflection->GetMessage(*message, f), basename);
else
allFields.push_back(ProtoField(basename, message, f));
allFields.push_back(ProtoField(
basename, (google::protobuf::Message*)message, f));
}
}
};
@@ -584,3 +586,12 @@ std::vector<ProtoField> findAllProtoFields(google::protobuf::Message* message)
recurse(message, "");
return allFields;
}
std::string renderProtoAsConfig(const google::protobuf::Message* message)
{
auto allFields = findAllProtoFields(message);
std::stringstream ss;
for (const auto& field : allFields)
ss << field.path() << "=" << field.get() << "\n";
return ss.str();
}

View File

@@ -72,7 +72,9 @@ extern std::map<std::string, const google::protobuf::FieldDescriptor*>
findAllPossibleProtoFields(const google::protobuf::Descriptor* descriptor);
extern std::vector<ProtoField> findAllProtoFields(
google::protobuf::Message* message);
const google::protobuf::Message* message);
extern std::string renderProtoAsConfig(
const google::protobuf::Message* message);
template <class T>
static inline const T parseProtoBytes(const std::string_view& bytes)

View File

@@ -11,9 +11,7 @@ std::unique_ptr<FluxSource> FluxSource::create(Config& config)
{
if (!config.hasFluxSource())
error("no flux source configured");
auto fluxSource = create(config->flux_source());
globalConfig().base()->MergeFrom(fluxSource->getExtraConfig());
return fluxSource;
return create(config->flux_source());
}
std::unique_ptr<FluxSource> FluxSource::create(const FluxSourceProto& config)

View File

@@ -111,6 +111,8 @@ public:
}
}
_extraConfig.mutable_layout()->add_layoutdata()->set_sector_size(524);
image->setGeometry({.numCylinders = numCylinders,
.numHeads = numHeads,
.numSectors = 12,

View File

@@ -54,6 +54,7 @@ int mainWrite(int argc, const char* argv[])
auto reader = ImageReader::create(globalConfig());
std::shared_ptr<Image> image = reader->readImage();
globalConfig().overrides()->MergeFrom(reader->getExtraConfig());
auto diskLayout = createDiskLayout();
auto encoder = Arch::createEncoder(globalConfig());

View File

@@ -18,9 +18,25 @@ using namespace hex;
static DynamicSettingFactory settings("fluxengine.settings");
static constexpr const char* DEFAULT_CUSTOM_SETTINGS = R"R(
# These settings will override the ones above.
# Here are some useful ones:
# decoder.retries=0
# drive.revolutions=1.2
)R";
ConfigView::ConfigView():
View::Window("fluxengine.view.config.name", ICON_VS_COMPASS)
{
Events::SetSystemConfig::subscribe(
[](std::string customConfig)
{
auto customSetting = settings.get<std::string>("systemProperties");
customSetting =
"# These settings were set by a file and\n"
"# may contradict the ones above (it's a bug).\n" +
customConfig;
});
}
static void emitOptions(DynamicSetting<std::string>& setting,
@@ -336,11 +352,33 @@ void ConfigView::drawContent()
ImGui::SeparatorText("fluxengine.view.config.customProperties"_lang);
auto customSetting = settings.get<std::string>("custom");
std::string buffer = customSetting;
if (ImGui::InputTextMultiline("##customProperties",
buffer,
ImGui::GetContentRegionAvail(),
ImGuiInputTextFlags_None))
customSetting = buffer;
if (ImGui::BeginTabBar("customconfig", ImGuiTabBarFlags_None))
{
DEFER(ImGui::EndTabBar());
if (ImGui::BeginTabItem("User"))
{
DEFER(ImGui::EndTabItem());
auto setting =
settings.get<std::string>("custom", DEFAULT_CUSTOM_SETTINGS);
std::string buffer = setting;
if (ImGui::InputTextMultiline("##customProperties",
buffer,
ImGui::GetContentRegionAvail(),
ImGuiInputTextFlags_None))
setting = buffer;
}
if (ImGui::BeginTabItem("System"))
{
DEFER(ImGui::EndTabItem());
auto setting = settings.get<std::string>("systemProperties");
std::string buffer = setting;
if (ImGui::InputTextMultiline("##systemProperties",
buffer,
ImGui::GetContentRegionAvail(),
ImGuiInputTextFlags_None))
setting = buffer;
}
}
}

View File

@@ -8,6 +8,7 @@
#include "lib/core/globals.h"
#include "lib/core/utils.h"
#include "lib/config/config.h"
#include "lib/config/proto.h"
#include "lib/data/disk.h"
#include "lib/data/image.h"
#include "lib/fluxsource/fluxsource.h"
@@ -50,7 +51,7 @@ static bool formattingSupported;
static std::map<std::string, Datastore::Device> devices;
static std::shared_ptr<const DiskLayout> diskLayout;
static void wtRebuildConfiguration();
static void wtRebuildConfiguration(bool useCustom);
static void workerThread_cb()
{
@@ -271,7 +272,11 @@ void Datastore::init()
hex::Region{startOffset, endOffset - startOffset});
});
runOnWorkerThread(wtRebuildConfiguration);
runOnWorkerThread(
[]
{
wtRebuildConfiguration(true);
});
}
bool Datastore::isBusy()
@@ -338,7 +343,7 @@ static void wtClearDiskData()
});
}
void wtRebuildConfiguration()
void wtRebuildConfiguration(bool withCustom = false)
{
/* Reset and apply the format configuration. */
@@ -392,26 +397,10 @@ void wtRebuildConfiguration()
/* Custom settings. */
auto customSettings = readSettingFromUiThread<std::string>("custom", "");
if (!customSettings.empty())
{
for (auto setting : split(customSettings, '\n'))
{
setting = trimWhitespace(setting);
if (setting.size() == 0)
continue;
if (setting[0] == '#')
continue;
auto equals = setting.find('=');
if (equals == std::string::npos)
error("Malformed setting line '{}'", setting);
auto key = setting.substr(0, equals);
auto value = setting.substr(equals + 1);
globalConfig().set(key, value);
}
}
globalConfig().applyOptionsFile(
readSettingFromUiThread<std::string>("systemProperties", ""));
globalConfig().applyOptionsFile(
readSettingFromUiThread<std::string>("custom", ""));
/* Finalise the options. */
@@ -540,7 +529,7 @@ void Datastore::beginRead(bool rereadBadSectors)
try
{
wtRebuildConfiguration();
wtRebuildConfiguration(true);
if (!rereadBadSectors)
wtClearDiskData();
@@ -576,7 +565,7 @@ void Datastore::beginWrite()
try
{
wtRebuildConfiguration();
wtRebuildConfiguration(true);
wtWaitForUiThreadToCatchUp();
auto fluxSinkFactory = FluxSinkFactory::create(globalConfig());
@@ -642,7 +631,7 @@ void Datastore::reset()
try
{
wtRebuildConfiguration();
wtRebuildConfiguration(false);
wtClearDiskData();
wtWaitForUiThreadToCatchUp();
}
@@ -682,7 +671,7 @@ void Datastore::writeImage(const std::fs::path& path)
try
{
wtRebuildConfiguration();
wtRebuildConfiguration(true);
wtWaitForUiThreadToCatchUp();
globalConfig().setImageWriter(path.string());
ImageWriter::create(globalConfig())
@@ -708,11 +697,23 @@ void Datastore::readImage(const std::fs::path& path)
try
{
wtRebuildConfiguration();
wtRebuildConfiguration(true);
wtWaitForUiThreadToCatchUp();
globalConfig().setImageReader(path.string());
std::shared_ptr<Image> image =
ImageReader::create(globalConfig())->readImage();
auto imageReader = ImageReader::create(globalConfig());
std::shared_ptr<Image> image = imageReader->readImage();
const auto& extraConfig = imageReader->getExtraConfig();
auto customConfig = renderProtoAsConfig(&extraConfig);
/* Update the setting, and then rebuild the config again as it
* will have changed. */
wtRunSynchronouslyOnUiThread((std::function<void()>)[=] {
Events::SetSystemConfig::post(customConfig);
});
wtRebuildConfiguration(true);
wtWaitForUiThreadToCatchUp();
auto disk = wtMakeDiskDataFromImage(image);
hex::TaskManager::doLater(
@@ -741,7 +742,7 @@ void Datastore::writeFluxFile(const std::fs::path& path)
try
{
wtRebuildConfiguration();
wtRebuildConfiguration(true);
wtWaitForUiThreadToCatchUp();
if (!disk || !disk->image)
@@ -777,7 +778,7 @@ void Datastore::createBlankImage()
try
{
wtRebuildConfiguration();
wtRebuildConfiguration(false);
wtClearDiskData();
wtWaitForUiThreadToCatchUp();
@@ -794,6 +795,7 @@ void Datastore::createBlankImage()
hex::TaskManager::doLater(
[=]
{
Events::SetSystemConfig::post("");
::disk = disk;
});
}

View File

@@ -39,6 +39,7 @@ namespace Events
EVENT_DEF(DiskActivityNotification, DiskActivityType, unsigned, unsigned);
EVENT_DEF(OperationStart, std::string);
EVENT_DEF(OperationStop, OperationState);
EVENT_DEF(SetSystemConfig, std::string);
}
#define DEFER(_stmt) \

View File

@@ -226,6 +226,49 @@ static void test_findallfields(void)
"u64"}));
}
static void test_rendering(void)
{
std::string s = R"M(
i64: -1
i32: -2
u64: 3
u32: 4
d: 5.5
f: 6.7
m {
s: "string"
}
r {
s: "val2"
}
r {
s: "val3"
}
secondoption {
s: "2"
}
)M";
TestProto proto;
if (!google::protobuf::TextFormat::MergeFromString(cleanup(s), &proto))
error("couldn't load test proto");
auto config = renderProtoAsConfig(&proto);
AssertThat(cleanup(config), Equals(cleanup(R"M(
i64=-1
i32=-2
u64=3
u32=4
d=5.5
m.s=string
r[0].s=val2
r[1].s=val3
secondoption.s=2
f=6.7
)M")));
}
int main(int argc, const char* argv[])
{
try
@@ -237,6 +280,7 @@ int main(int argc, const char* argv[])
test_fields();
test_options();
test_findallfields();
test_rendering();
}
catch (const ErrorException& e)
{