mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-09 03:23:24 -08:00
[Installer][Client] Fix review findings: sounds, session coverage, NSIS wording
Client: back up data/sounds in portable mode and mention it in the warning; reuse a recent session only when complete and covering the current sources (source manifest), estimate size only for fresh copies, normalize dedup via isInsideDir. Helper: source manifest per session with sessionCoversSources(), clear out-params on all failure paths. NSIS: document defensive portable branch, merge backup over surviving data/ to repair partial deletes, copy (not move) wording in relocate, note .txt exclusion in deck notice.
This commit is contained in:
parent
d10ec8a113
commit
53e8421885
5 changed files with 209 additions and 50 deletions
|
|
@ -15,10 +15,20 @@ namespace
|
|||
|
||||
const QString COMPLETE_MARKER = QStringLiteral("backup.complete");
|
||||
const QString INCOMPLETE_MARKER = QStringLiteral("backup.incomplete");
|
||||
const QString SOURCES_MANIFEST = QStringLiteral("backup.sources");
|
||||
|
||||
bool isMarkerFile(const QString &fileName)
|
||||
{
|
||||
return fileName == COMPLETE_MARKER || fileName == INCOMPLETE_MARKER;
|
||||
return fileName == COMPLETE_MARKER || fileName == INCOMPLETE_MARKER || fileName == SOURCES_MANIFEST;
|
||||
}
|
||||
|
||||
bool pathsEqual(const QString &a, const QString &b)
|
||||
{
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
|
||||
return QDir::cleanPath(a).compare(QDir::cleanPath(b), Qt::CaseInsensitive) == 0;
|
||||
#else
|
||||
return QDir::cleanPath(a) == QDir::cleanPath(b);
|
||||
#endif
|
||||
}
|
||||
|
||||
void writeCompletionMarker(const QString &sessionDir, bool complete)
|
||||
|
|
@ -114,8 +124,12 @@ bool backupAtRiskPath(const QString &sourcePath, const QString &backupRoot, QStr
|
|||
{
|
||||
QStringList locations;
|
||||
const bool ok = backupAtRiskPaths({sourcePath}, backupRoot, &locations, nullptr);
|
||||
if (!locations.isEmpty() && backupLocationOut) {
|
||||
*backupLocationOut = locations.first();
|
||||
if (backupLocationOut) {
|
||||
if (!locations.isEmpty()) {
|
||||
*backupLocationOut = locations.first();
|
||||
} else {
|
||||
backupLocationOut->clear();
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
|
@ -143,6 +157,12 @@ bool backupAtRiskPaths(const QStringList &sourcePaths,
|
|||
|
||||
QString sessionDir;
|
||||
if (!createBackupSessionDir(backupRoot, &sessionDir)) {
|
||||
if (backupLocationsOut) {
|
||||
backupLocationsOut->clear();
|
||||
}
|
||||
if (sessionDirOut) {
|
||||
sessionDirOut->clear();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (sessionDirOut) {
|
||||
|
|
@ -184,6 +204,14 @@ bool backupAtRiskPaths(const QStringList &sourcePaths,
|
|||
return false;
|
||||
}
|
||||
writeCompletionMarker(sessionDir, allOk);
|
||||
// Record which sources this session covers so callers can reuse it only
|
||||
// when it actually covers the current source set (see sessionCoversSources).
|
||||
QFile manifest(QDir(sessionDir).absoluteFilePath(SOURCES_MANIFEST));
|
||||
if (manifest.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
for (const QString &sourcePath : existing) {
|
||||
manifest.write(QDir::cleanPath(sourcePath).toUtf8() + "\n");
|
||||
}
|
||||
}
|
||||
if (backupLocationsOut) {
|
||||
*backupLocationsOut = locations;
|
||||
}
|
||||
|
|
@ -325,4 +353,34 @@ QStringList listSessionBackupLocations(const QString &sessionDir)
|
|||
return locations;
|
||||
}
|
||||
|
||||
bool sessionCoversSources(const QString &sessionDir, const QStringList &sourcePaths)
|
||||
{
|
||||
QFile manifest(QDir(sessionDir).absoluteFilePath(SOURCES_MANIFEST));
|
||||
if (!manifest.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
// Legacy sessions predate the manifest: coverage cannot be verified,
|
||||
// so report not-covered and let the caller take a fresh copy.
|
||||
return false;
|
||||
}
|
||||
QStringList recorded;
|
||||
while (!manifest.atEnd()) {
|
||||
const QString line = QString::fromUtf8(manifest.readLine()).trimmed();
|
||||
if (!line.isEmpty()) {
|
||||
recorded.append(line);
|
||||
}
|
||||
}
|
||||
for (const QString &source : sourcePaths) {
|
||||
bool found = false;
|
||||
for (const QString &entry : recorded) {
|
||||
if (pathsEqual(source, entry)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace UserDataBackup
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue