#include "filelocationchecktask.h"
#include "database.h"
+#include "renameutils.h"
+
#include <QFileInfo>
#include <QDebug>
db->transaction();
QList<FileLocation> fileLocations = db->getFileLocationBatch(lastLocationId, OPERATIONS_PER_UNIT);
- for (const FileLocation &fl : fileLocations)
+ for (FileLocation &fl : fileLocations)
{
if (!QFileInfo(fl.path).exists())
{
.arg(fl.path));
db->removeFileLocation(fl.locationId);
}
+ else
+ {
+ QString canonicalPath = exactPath(QFileInfo(fl.path).canonicalFilePath());
+
+ if (!canonicalPath.isEmpty() && canonicalPath != fl.path)
+ {
+ qDebug() << QObject::tr("Fixing File location %1: %2")
+ .arg(fl.locationId)
+ .arg(fl.path);
+ fl.path = canonicalPath;
+ db->setFileLocation(fl);
+ }
+
+ }
+
lastLocationId = fl.locationId;
}
db->commit();
QString newFileString = newFilePath + "/" + newFileName;
QFileInfo newFile(newFileString);
-#ifdef Q_OS_WIN
- bool isSamePath = oldFile.canonicalFilePath().compare(newFileString, Qt::CaseInsensitive) == 0;
-#else
bool isSamePath = oldFile.canonicalFilePath() == newFileString;
-#endif
+ bool differenceInCaseOnly = !isSamePath && oldFile.canonicalFilePath().compare(newFileString, Qt::CaseInsensitive) == 0;
if (isSamePath)
{
continue;
}
- if (newFile.exists())
+ if (!differenceInCaseOnly && newFile.exists())
{
fl.failedRename = true;
fl.renameError = tr("Rename: Failed to rename file <%1>. Destination <%2> exists.").arg(oldFile.filePath()).arg(newFileString);
}
#endif
- if (!QFile::rename(oldFile.canonicalFilePath(), newFileString))
+ QString exactFileName;
+ if (!renameFile(oldFile.canonicalFilePath(), newFileString, &exactFileName))
{
fl.failedRename = true;
fl.renameError = tr("Rename: Failed to rename file <%1>. Failed to rename file to <%2>").arg(oldFile.canonicalFilePath()).arg(newFileString);
continue;
}
- fl.path = newFileString;
+ if (exactFileName.isEmpty())
+ {
+ qWarning() << "exactFileName is empty";
+ fl.path = newFileString;
+ }
+ else
+ {
+ fl.path = exactFileName;
+ }
+
fl.failedRename = false;
fl.renameError = "";
db->setFileLocation(fl);
- db->log(tr("Rename: File <%1> was renamed to <%2>").arg(oldFile.canonicalFilePath()).arg(newFileString));
+ db->log(tr("Rename: File <%1> was renamed to <%2>").arg(oldFile.canonicalFilePath()).arg(fl.path));
if (settings->get("renameRemoveEmptyDirectories", false))
{
#include <QDateTime>
#include <QFileInfo>
+#include <QDebug>
+
namespace LocalMyList {
void setupRenameEnv(const QSqlRecord &record, RenameParser::Environment &env)
env["MaxRelatedEpNo"] = record.value("max_related_epno").toString();
}
+#ifdef Q_OS_WIN
+#include <QDir>
+#include <windows.h>
+#endif
+
+
+QString toWindowsPath(const QString &path)
+{
+ return QDir::toNativeSeparators(path).prepend("\\\\?\\");
+}
+
+QString exactPath(const QString &path)
+{
+#ifndef Q_OS_WIN
+ return QFileInfo(path).canonicalFilePath();
+#else
+ HANDLE handle = INVALID_HANDLE_VALUE;
+ static const DWORD BUFFERSIZE = 10000;
+ wchar_t finalName[BUFFERSIZE];
+
+ QString pathWindows = toWindowsPath(path);
+ const wchar_t *pathW = reinterpret_cast<const wchar_t *>(pathWindows.utf16());
+
+ handle = CreateFileW(pathW,
+ 0,
+ FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ DWORD lastError = GetLastError();
+ qDebug() << "exactPath invalid handle" << lastError << path;
+ return QString();
+ }
+
+ DWORD length = GetFinalPathNameByHandleW(handle,
+ finalName,
+ BUFFERSIZE,
+ VOLUME_NAME_DOS);
+
+ if (length > BUFFERSIZE)
+ return QString();
+
+ QString ret = QString::fromWCharArray(finalName, length);
+ CloseHandle(handle);
+
+ ret = ret.mid(4);
+ ret = QDir::fromNativeSeparators(ret);
+
+ return ret;
+#endif
+}
+
+bool renameFile(const QString &oldName, const QString &newName, QString *actualPath)
+{
+#ifndef Q_OS_WIN
+ if (!QFile::rename(oldName, newName))
+ return false;
+
+ if (actualPath) *actualPath = exactPath(oldName);
+ return true;
+
+#else
+ if (oldName == newName)
+ {
+ if (actualPath) *actualPath = exactPath(oldName);
+ return true;
+ }
+
+ const QString oldNameWindows = toWindowsPath(oldName);
+ const QString newNameWindows = toWindowsPath(newName);
+ const wchar_t *oldNameW = reinterpret_cast<const wchar_t *>(oldNameWindows.utf16());
+ const wchar_t *newNameW = reinterpret_cast<const wchar_t *>(newNameWindows.utf16());
+
+ bool ret = MoveFileW(oldNameW, newNameW);
+
+ if (!ret)
+ {
+ DWORD lastError = GetLastError();
+ qDebug() << "Move Failed" << lastError;
+ return false;
+ }
+
+ const QString newNameExact = exactPath(newName);
+
+ if (newNameExact.isEmpty())
+ {
+ qDebug() << "Failed to get exact path";
+ return false;
+ }
+
+ const QString newNameDir = QFileInfo(newName).absolutePath();
+ const QString newNameExactDir = QFileInfo(newNameExact).absolutePath();
+
+ // Paths differ in case only
+ if (newNameDir != newNameExactDir && newNameDir.compare(newNameExactDir, Qt::CaseInsensitive) == 0)
+ {
+ bool ret = renameFile(newNameExactDir, newNameDir);
+ if (actualPath) *actualPath = exactPath(newName);
+ return ret;
+ }
+
+ // Either paths are identical or the new path differs by more than case.
+ if (actualPath) *actualPath = newNameExact;
+
+ return true;
+#endif
+}
+
+
} // namespace LocalMyList