mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-10 12:03:25 -08:00
[Installer][Client] Fix review findings: usable session reuse, loose decks, NSIS pics, symlinks
This commit is contained in:
parent
3bde484244
commit
e9b05a3d46
5 changed files with 256 additions and 33 deletions
|
|
@ -80,7 +80,19 @@ bool copyDirectoryRecursively(const QString &sourceDir, const QString &destDir)
|
|||
it.next();
|
||||
QString entryRel = source.relativeFilePath(it.filePath());
|
||||
QString target = QDir(destDir).absoluteFilePath(entryRel);
|
||||
if (it.fileInfo().isDir()) {
|
||||
if (it.fileInfo().isSymLink()) {
|
||||
// Copy the link itself best-effort without dereferencing it. QDirIterator does not
|
||||
// follow symlinks here, so a symlink-to-directory must not take the isDir() branch
|
||||
// below (which would create an empty dir and silently drop the contents).
|
||||
QDir().mkpath(QFileInfo(target).absolutePath());
|
||||
if (QFile::exists(target) && !QFile::remove(target)) {
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
if (!QFile::copy(it.filePath(), target)) {
|
||||
ok = false;
|
||||
}
|
||||
} else if (it.fileInfo().isDir()) {
|
||||
if (!QDir().mkpath(target)) {
|
||||
ok = false;
|
||||
}
|
||||
|
|
@ -284,10 +296,10 @@ QString findRecentBackupSession(const QString &backupRoot, int maxAgeHours)
|
|||
if (!info.exists()) {
|
||||
continue;
|
||||
}
|
||||
// Sessions are newest-first, so once an entry is too old every later
|
||||
// one is older as well and the search can stop.
|
||||
// No early break: filename order is not guaranteed to match mtime order
|
||||
// (clock adjustments, externally touched dirs), and session counts are tiny.
|
||||
if (info.lastModified().secsTo(now) >= static_cast<qint64>(maxAgeHours) * 3600) {
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
// Skip empty sessions from failed attempts: they must never block a retry.
|
||||
if (listSessionBackupLocations(session).isEmpty()) {
|
||||
|
|
@ -298,6 +310,58 @@ QString findRecentBackupSession(const QString &backupRoot, int maxAgeHours)
|
|||
return {};
|
||||
}
|
||||
|
||||
QString findRecentCoveringBackupSession(const QString &backupRoot, const QStringList &sourcePaths, int maxAgeHours)
|
||||
{
|
||||
const QStringList sessions = listBackupSessions(backupRoot);
|
||||
const QDateTime now = QDateTime::currentDateTime();
|
||||
for (const QString &session : sessions) {
|
||||
const QFileInfo info(session);
|
||||
if (!info.exists()) {
|
||||
continue;
|
||||
}
|
||||
if (info.lastModified().secsTo(now) >= static_cast<qint64>(maxAgeHours) * 3600) {
|
||||
continue;
|
||||
}
|
||||
if (listSessionBackupLocations(session).isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (!sessionCoversSources(session, sourcePaths)) {
|
||||
continue;
|
||||
}
|
||||
return session;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
QString findRecentUsableBackupSession(const QString &backupRoot, const QStringList &sourcePaths, int maxAgeHours)
|
||||
{
|
||||
if (sourcePaths.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
const QStringList sessions = listBackupSessions(backupRoot);
|
||||
const QDateTime now = QDateTime::currentDateTime();
|
||||
for (const QString &session : sessions) {
|
||||
const QFileInfo info(session);
|
||||
if (!info.exists()) {
|
||||
continue;
|
||||
}
|
||||
if (info.lastModified().secsTo(now) >= static_cast<qint64>(maxAgeHours) * 3600) {
|
||||
continue;
|
||||
}
|
||||
if (listSessionBackupLocations(session).isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (!isBackupSessionComplete(session)) {
|
||||
continue;
|
||||
}
|
||||
if (!sessionCoversSources(session, sourcePaths)) {
|
||||
continue;
|
||||
}
|
||||
return session;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
bool isBackupSessionComplete(const QString &sessionDir)
|
||||
{
|
||||
const QDir session(sessionDir);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ constexpr qint64 MAX_AUTO_BACKUP_BYTES = 500LL * 1024 * 1024;
|
|||
/**
|
||||
* @brief Recursively copies @p sourceDir into @p destDir, creating it as needed.
|
||||
* @returns true when every file was copied (or there was nothing to copy).
|
||||
* Symlinks are copied best-effort via QFile::copy; a dangling link fails that entry only.
|
||||
* Symlinks (file or directory) are copied best-effort via QFile::copy without
|
||||
* dereferencing them; a dangling link fails that entry only.
|
||||
*/
|
||||
bool copyDirectoryRecursively(const QString &sourceDir, const QString &destDir);
|
||||
|
||||
|
|
@ -96,11 +97,30 @@ QStringList listBackupSessions(const QString &backupRoot);
|
|||
*
|
||||
* Used to throttle startup safety backups so dismissing the warning without
|
||||
* "Don't show again" does not create a full duplicate on every launch.
|
||||
* Empty sessions (failed attempts) are skipped so they never block a retry,
|
||||
* and an expired newest entry stops the search since sessions are newest-first.
|
||||
* Empty sessions (failed attempts) are skipped so they never block a retry.
|
||||
* Every session is age-checked individually; no early exit assumes filename
|
||||
* order matches mtime order (clock adjustments or externally touched dirs
|
||||
* can break that assumption).
|
||||
*/
|
||||
QString findRecentBackupSession(const QString &backupRoot, int maxAgeHours = 24);
|
||||
|
||||
/**
|
||||
* @brief Returns the newest session that is non-empty, complete and covering @p sourcePaths, or empty.
|
||||
*
|
||||
* Unlike findRecentBackupSession(), an incomplete newest session (partial failure) or one
|
||||
* covering a different source set does not block reuse of an older good session.
|
||||
*/
|
||||
QString findRecentUsableBackupSession(const QString &backupRoot, const QStringList &sourcePaths, int maxAgeHours = 24);
|
||||
|
||||
/**
|
||||
* @brief Returns the newest non-empty session covering @p sourcePaths, regardless of completeness.
|
||||
*
|
||||
* Used as a fallback pointer when a fresh copy fails entirely, so the dialog can still
|
||||
* point at salvaged content. Completeness is left to the caller to report.
|
||||
*/
|
||||
QString
|
||||
findRecentCoveringBackupSession(const QString &backupRoot, const QStringList &sourcePaths, int maxAgeHours = 24);
|
||||
|
||||
/**
|
||||
* @brief Reports whether @p sessionDir holds a complete backup.
|
||||
* @returns true when the session carries the complete marker, or when it predates
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue