diff --git a/cockatrice/src/interface/deck_loader/deck_loader.cpp b/cockatrice/src/interface/deck_loader/deck_loader.cpp index 9a58cf3f9..39a0c1071 100644 --- a/cockatrice/src/interface/deck_loader/deck_loader.cpp +++ b/cockatrice/src/interface/deck_loader/deck_loader.cpp @@ -458,51 +458,54 @@ bool DeckLoader::convertToCockatriceFormat(LoadedDeck &deck) return false; } + // Determine the format before touching any file, so an already-converted or + // unsupported deck never truncates or deletes anything. + switch (DeckFileFormat::getFormatFromName(fileName)) { + case DeckFileFormat::PlainText: + break; + case DeckFileFormat::Cockatrice: + qCInfo(DeckLoaderLog) << "File is already in Cockatrice format. No conversion needed."; + return true; + default: + qCWarning(DeckLoaderLog) << "Unsupported file format for conversion:" << fileName; + return false; + } + // Change the file extension to .cod QFileInfo fileInfo(fileName); QString newFileName = QDir::toNativeSeparators(fileInfo.path() + "/" + fileInfo.completeBaseName() + ".cod"); - // Open the new file for writing - QFile file(newFileName); + // Use QSaveFile so a failed write (e.g. a full disk) cannot leave a 0-byte .cod + // behind and then delete the original deck. + QSaveFile file(newFileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qCWarning(DeckLoaderLog) << "Failed to open file for writing:" << newFileName; return false; } - bool result = false; - - // Perform file modifications based on the detected format - switch (DeckFileFormat::getFormatFromName(fileName)) { - case DeckFileFormat::PlainText: - // Save in Cockatrice's native format - result = deck.deckList.saveToFile_Native(&file); - break; - case DeckFileFormat::Cockatrice: - qCInfo(DeckLoaderLog) << "File is already in Cockatrice format. No conversion needed."; - result = true; - break; - default: - qCWarning(DeckLoaderLog) << "Unsupported file format for conversion:" << fileName; - result = false; - break; + if (!deck.deckList.saveToFile_Native(&file)) { + file.cancelWriting(); + qCWarning(DeckLoaderLog) << "Failed to serialize deck for file:" << newFileName; + return false; } - file.close(); - - // Delete the old file if conversion was successful - if (result) { - if (!QFile::remove(fileName)) { - qCWarning(DeckLoaderLog) << "Failed to delete original file:" << fileName; - } else { - qCInfo(DeckLoaderLog) << "Original file deleted successfully:" << fileName; - } - deck.lastLoadInfo = { - .fileName = newFileName, - .fileFormat = DeckFileFormat::Cockatrice, - }; + if (!file.commit()) { + qCWarning(DeckLoaderLog) << "Failed to convert deck to " << newFileName << ":" << file.errorString(); + return false; } - return result; + // Conversion succeeded: delete the original file. + if (!QFile::remove(fileName)) { + qCWarning(DeckLoaderLog) << "Failed to delete original file:" << fileName; + } else { + qCInfo(DeckLoaderLog) << "Original file deleted successfully:" << fileName; + } + deck.lastLoadInfo = { + .fileName = newFileName, + .fileFormat = DeckFileFormat::Cockatrice, + }; + + return true; } void DeckLoader::printDeckListNode(QTextCursor *cursor, const InnerDecklistNode *node)