mirror of
https://github.com/nextcloud/desktop.git
synced 2025-10-26 11:17:43 +00:00
Update Word files VFS placeholders each time they get opened by tracking the 'lock' files
Signed-off-by: alex-z <blackslayer4@gmail.com>
This commit is contained in:
parent
79b419816b
commit
f3db221314
@ -641,8 +641,11 @@ void Folder::slotFilesLockReleased(const QSet<QString> &files)
|
||||
for (const auto &file : files) {
|
||||
const auto fileRecordPath = fileFromLocalPath(file);
|
||||
SyncJournalFileRecord rec;
|
||||
const auto canUnlockFile = journalDb()->getFileRecord(fileRecordPath, &rec)
|
||||
&& rec.isValid()
|
||||
const auto isFileRecordValid = journalDb()->getFileRecord(fileRecordPath, &rec) && rec.isValid();
|
||||
if (isFileRecordValid) {
|
||||
[[maybe_unused]] const auto result = _vfs->updateMetadata(path() + rec.path(), rec._modtime, rec._fileSize, rec._fileId);
|
||||
}
|
||||
const auto canUnlockFile = isFileRecordValid
|
||||
&& rec._lockstate._locked
|
||||
&& rec._lockstate._lockOwnerType == static_cast<qint64>(SyncFileItem::LockOwnerType::UserLock)
|
||||
&& rec._lockstate._lockOwnerId == _accountState->account()->davUser();
|
||||
@ -667,6 +670,18 @@ void Folder::slotFilesLockReleased(const QSet<QString> &files)
|
||||
}
|
||||
}
|
||||
|
||||
void Folder::slotFilesLockImposed(const QSet<QString> &files)
|
||||
{
|
||||
qCDebug(lcFolder) << "Lock files detected for office files" << files;
|
||||
for (const auto &file : files) {
|
||||
const auto fileRecordPath = fileFromLocalPath(file);
|
||||
SyncJournalFileRecord rec;
|
||||
if (journalDb()->getFileRecord(fileRecordPath, &rec) && rec.isValid()) {
|
||||
[[maybe_unused]] const auto result = _vfs->updateMetadata(path() + rec.path(), rec._modtime, rec._fileSize, rec._fileId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Folder::implicitlyHydrateFile(const QString &relativepath)
|
||||
{
|
||||
qCInfo(lcFolder) << "Implicitly hydrate virtual file:" << relativepath;
|
||||
@ -1498,6 +1513,7 @@ void Folder::registerFolderWatcher()
|
||||
if (_accountState->account()->capabilities().filesLockAvailable()) {
|
||||
connect(_folderWatcher.data(), &FolderWatcher::filesLockReleased, this, &Folder::slotFilesLockReleased);
|
||||
}
|
||||
connect(_folderWatcher.data(), &FolderWatcher::filesLockImposed, this, &Folder::slotFilesLockImposed, Qt::UniqueConnection);
|
||||
_folderWatcher->init(path());
|
||||
_folderWatcher->startNotificatonTest(path() + QLatin1String(".nextcloudsync.log"));
|
||||
}
|
||||
|
||||
@ -353,6 +353,11 @@ public slots:
|
||||
*/
|
||||
void slotFilesLockReleased(const QSet<QString> &files);
|
||||
|
||||
/*
|
||||
* Triggered when lock files were added
|
||||
*/
|
||||
void slotFilesLockImposed(const QSet<QString> &files);
|
||||
|
||||
/**
|
||||
* Mark a virtual file as being requested for download, and start a sync.
|
||||
*
|
||||
|
||||
@ -170,6 +170,7 @@ void FolderWatcher::changeDetected(const QStringList &paths)
|
||||
|
||||
QSet<QString> changedPaths;
|
||||
QSet<QString> unlockedFiles;
|
||||
QSet<QString> lockedFiles;
|
||||
|
||||
for (int i = 0; i < paths.size(); ++i) {
|
||||
QString path = paths[i];
|
||||
@ -178,15 +179,21 @@ void FolderWatcher::changeDetected(const QStringList &paths)
|
||||
_testNotificationPath.clear();
|
||||
}
|
||||
|
||||
const auto checkResult = checkIfFileIsLockOrUnlock(path);
|
||||
if (_shouldWatchForFileUnlocking) {
|
||||
const auto unlockedFilePath = possiblyAddUnlockedFilePath(path);
|
||||
if (!unlockedFilePath.isEmpty()) {
|
||||
unlockedFiles.insert(unlockedFilePath);
|
||||
if (checkResult.type == FileLockingInfo::Type::Unlocked && !checkResult.path.isEmpty()) {
|
||||
unlockedFiles.insert(checkResult.path);
|
||||
}
|
||||
|
||||
qCDebug(lcFolderWatcher) << "Unlocked files:" << unlockedFiles.values();
|
||||
}
|
||||
|
||||
if (checkResult.type == FileLockingInfo::Type::Locked && !checkResult.path.isEmpty()) {
|
||||
lockedFiles.insert(checkResult.path);
|
||||
}
|
||||
|
||||
qCDebug(lcFolderWatcher) << "Locked files:" << lockedFiles.values();
|
||||
|
||||
// ------- handle ignores:
|
||||
if (pathIsIgnored(path)) {
|
||||
continue;
|
||||
@ -199,6 +206,10 @@ void FolderWatcher::changeDetected(const QStringList &paths)
|
||||
emit filesLockReleased(unlockedFiles);
|
||||
}
|
||||
|
||||
if (!lockedFiles.isEmpty()) {
|
||||
emit filesLockImposed(lockedFiles);
|
||||
}
|
||||
|
||||
if (changedPaths.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@ -214,12 +225,14 @@ void FolderWatcher::folderAccountCapabilitiesChanged()
|
||||
_shouldWatchForFileUnlocking = _folder->accountState()->account()->capabilities().filesLockAvailable();
|
||||
}
|
||||
|
||||
QString FolderWatcher::possiblyAddUnlockedFilePath(const QString &path)
|
||||
FolderWatcher::FileLockingInfo FolderWatcher::checkIfFileIsLockOrUnlock(const QString &path) const
|
||||
{
|
||||
qCDebug(lcFolderWatcher) << "Checking if it is a lock file:" << path;
|
||||
|
||||
FileLockingInfo result;
|
||||
const auto pathSplit = path.split(QLatin1Char('/'), Qt::SkipEmptyParts);
|
||||
if (pathSplit.isEmpty()) {
|
||||
return {};
|
||||
return result;
|
||||
}
|
||||
QString lockFilePatternFound;
|
||||
for (const auto &lockFilePattern : lockFilePatterns) {
|
||||
@ -229,8 +242,8 @@ QString FolderWatcher::possiblyAddUnlockedFilePath(const QString &path)
|
||||
}
|
||||
}
|
||||
|
||||
if (lockFilePatternFound.isEmpty() || QFileInfo::exists(path)) {
|
||||
return {};
|
||||
if (lockFilePatternFound.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
qCDebug(lcFolderWatcher) << "Found a lock file with prefix:" << lockFilePatternFound << "in path:" << path;
|
||||
@ -239,7 +252,7 @@ QString FolderWatcher::possiblyAddUnlockedFilePath(const QString &path)
|
||||
auto lockFilePathWithoutPrefixSplit = lockFilePathWitoutPrefix.split(QLatin1Char('.'));
|
||||
|
||||
if (lockFilePathWithoutPrefixSplit.size() < 2) {
|
||||
return {};
|
||||
return result;
|
||||
}
|
||||
|
||||
auto extensionSanitized = lockFilePathWithoutPrefixSplit.takeLast().toStdString();
|
||||
@ -252,26 +265,26 @@ QString FolderWatcher::possiblyAddUnlockedFilePath(const QString &path)
|
||||
);
|
||||
|
||||
lockFilePathWithoutPrefixSplit.push_back(QString::fromStdString(extensionSanitized));
|
||||
auto unlockedFilePath = lockFilePathWithoutPrefixSplit.join(QLatin1Char('.'));
|
||||
const auto lockFilePathWithoutPrefix = lockFilePathWithoutPrefixSplit.join(QLatin1Char('.'));
|
||||
|
||||
if (!QFile::exists(unlockedFilePath)) {
|
||||
unlockedFilePath.clear();
|
||||
qCDebug(lcFolderWatcher) << "Assumed unlocked file path" << unlockedFilePath << "does not exist. Going to try to find matching file";
|
||||
auto splitFilePath = unlockedFilePath.split(QLatin1Char('/'));
|
||||
if (splitFilePath.size() > 1) {
|
||||
const auto lockFileName = splitFilePath.takeLast();
|
||||
// some software will modify lock file name such that it does not correspond to original file (removing some symbols from the name, so we will search for a matching file
|
||||
unlockedFilePath = findMatchingUnlockedFileInDir(splitFilePath.join(QLatin1Char('/')), lockFileName);
|
||||
}
|
||||
qCDebug(lcFolderWatcher) << "Assumed locked/unlocked file path" << lockFilePathWithoutPrefix << "Going to try to find matching file";
|
||||
auto splitFilePath = lockFilePathWithoutPrefix.split(QLatin1Char('/'));
|
||||
if (splitFilePath.size() > 1) {
|
||||
const auto lockFileNameWithoutPrefix = splitFilePath.takeLast();
|
||||
// some software will modify lock file name such that it does not correspond to original file (removing some symbols from the name, so we will search
|
||||
// for a matching file
|
||||
result.path = findMatchingUnlockedFileInDir(splitFilePath.join(QLatin1Char('/')), lockFileNameWithoutPrefix);
|
||||
}
|
||||
|
||||
if (unlockedFilePath.isEmpty() || !QFile::exists(unlockedFilePath)) {
|
||||
return {};
|
||||
if (result.path.isEmpty() || !QFile::exists(result.path)) {
|
||||
result.path.clear();
|
||||
return result;
|
||||
}
|
||||
return unlockedFilePath;
|
||||
result.type = QFile::exists(path) ? FileLockingInfo::Type::Locked : FileLockingInfo::Type::Unlocked;
|
||||
return result;
|
||||
}
|
||||
|
||||
QString FolderWatcher::findMatchingUnlockedFileInDir(const QString &dirPath, const QString &lockFileName)
|
||||
QString FolderWatcher::findMatchingUnlockedFileInDir(const QString &dirPath, const QString &lockFileName) const
|
||||
{
|
||||
QString foundFilePath;
|
||||
const QDir dir(dirPath);
|
||||
|
||||
@ -50,6 +50,13 @@ class Folder;
|
||||
class FolderWatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
struct FileLockingInfo {
|
||||
enum class Type { Unset = -1, Locked, Unlocked };
|
||||
QString path;
|
||||
Type type = Type::Unset;
|
||||
};
|
||||
|
||||
public:
|
||||
// Construct, connect signals, call init()
|
||||
explicit FolderWatcher(Folder *folder = nullptr);
|
||||
@ -90,6 +97,11 @@ signals:
|
||||
*/
|
||||
void filesLockReleased(const QSet<QString> &files);
|
||||
|
||||
/*
|
||||
* Emitted when lock files were added
|
||||
*/
|
||||
void filesLockImposed(const QSet<QString> &files);
|
||||
|
||||
/**
|
||||
* Emitted if some notifications were lost.
|
||||
*
|
||||
@ -129,8 +141,8 @@ private:
|
||||
|
||||
void appendSubPaths(QDir dir, QStringList& subPaths);
|
||||
|
||||
QString possiblyAddUnlockedFilePath(const QString &path);
|
||||
QString findMatchingUnlockedFileInDir(const QString &dirPath, const QString &lockFileName);
|
||||
[[nodiscard]] FileLockingInfo checkIfFileIsLockOrUnlock(const QString &path) const;
|
||||
[[nodiscard]] QString findMatchingUnlockedFileInDir(const QString &dirPath, const QString &lockFileName) const;
|
||||
|
||||
/* Check if the path should be igored by the FolderWatcher. */
|
||||
[[nodiscard]] bool pathIsIgnored(const QString &path) const;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user