mirror of
https://git.outfoxxed.me/quickshell/quickshell.git
synced 2026-04-10 06:11:54 +10:00
core: hash scanned files and don't trigger a reload if matching
Nix builds often trip QFileSystemWatcher, causing random reloads.
This commit is contained in:
parent
bd62179277
commit
9a9c605250
4 changed files with 48 additions and 11 deletions
|
|
@ -33,6 +33,7 @@ set shell id.
|
|||
- IPC operations filter available instances to the current display connection by default.
|
||||
- PwNodeLinkTracker ignores sound level monitoring programs.
|
||||
- Replaced breakpad with cpptrace.
|
||||
- Reloads are prevented if no file content has changed.
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
|
|
|
|||
|
|
@ -209,6 +209,8 @@ bool EngineGeneration::setExtraWatchedFiles(const QVector<QString>& files) {
|
|||
for (const auto& file: files) {
|
||||
if (!this->scanner.scannedFiles.contains(file)) {
|
||||
this->extraWatchedFiles.append(file);
|
||||
QByteArray data;
|
||||
this->scanner.readAndHashFile(file, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -229,6 +231,11 @@ void EngineGeneration::onFileChanged(const QString& name) {
|
|||
auto fileInfo = QFileInfo(name);
|
||||
if (fileInfo.isFile() && fileInfo.size() == 0) return;
|
||||
|
||||
if (!this->scanner.hasFileContentChanged(name)) {
|
||||
qCDebug(logQmlScanner) << "Ignoring file change with unchanged content:" << name;
|
||||
return;
|
||||
}
|
||||
|
||||
emit this->filesChanged();
|
||||
}
|
||||
}
|
||||
|
|
@ -237,6 +244,11 @@ void EngineGeneration::onDirectoryChanged() {
|
|||
// try to find any files that were just deleted from a replace operation
|
||||
for (auto& file: this->deletedWatchedFiles) {
|
||||
if (QFileInfo(file).exists()) {
|
||||
if (!this->scanner.hasFileContentChanged(file)) {
|
||||
qCDebug(logQmlScanner) << "Ignoring restored file with unchanged content:" << file;
|
||||
continue;
|
||||
}
|
||||
|
||||
emit this->filesChanged();
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <utility>
|
||||
|
||||
#include <qcontainerfwd.h>
|
||||
#include <qcryptographichash.h>
|
||||
#include <qdir.h>
|
||||
#include <qfileinfo.h>
|
||||
#include <qjsengine.h>
|
||||
|
|
@ -21,6 +22,25 @@
|
|||
|
||||
QS_LOGGING_CATEGORY(logQmlScanner, "quickshell.qmlscanner", QtWarningMsg);
|
||||
|
||||
bool QmlScanner::readAndHashFile(const QString& path, QByteArray& data) {
|
||||
auto file = QFile(path);
|
||||
if (!file.open(QFile::ReadOnly)) return false;
|
||||
data = file.readAll();
|
||||
this->fileHashes.insert(path, QCryptographicHash::hash(data, QCryptographicHash::Md5));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QmlScanner::hasFileContentChanged(const QString& path) const {
|
||||
auto it = this->fileHashes.constFind(path);
|
||||
if (it == this->fileHashes.constEnd()) return true;
|
||||
|
||||
auto file = QFile(path);
|
||||
if (!file.open(QFile::ReadOnly)) return true;
|
||||
|
||||
auto newHash = QCryptographicHash::hash(file.readAll(), QCryptographicHash::Md5);
|
||||
return newHash != it.value();
|
||||
}
|
||||
|
||||
void QmlScanner::scanDir(const QDir& dir) {
|
||||
if (this->scannedDirs.contains(dir)) return;
|
||||
this->scannedDirs.push_back(dir);
|
||||
|
|
@ -109,13 +129,13 @@ bool QmlScanner::scanQmlFile(const QString& path, bool& singleton, bool& interna
|
|||
|
||||
qCDebug(logQmlScanner) << "Scanning qml file" << path;
|
||||
|
||||
auto file = QFile(path);
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QByteArray fileData;
|
||||
if (!this->readAndHashFile(path, fileData)) {
|
||||
qCWarning(logQmlScanner) << "Failed to open file" << path;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto stream = QTextStream(&file);
|
||||
auto stream = QTextStream(&fileData);
|
||||
auto imports = QVector<QString>();
|
||||
|
||||
bool inHeader = true;
|
||||
|
|
@ -219,8 +239,6 @@ bool QmlScanner::scanQmlFile(const QString& path, bool& singleton, bool& interna
|
|||
postError("unclosed preprocessor if block");
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
if (isOverridden) {
|
||||
this->fileIntercepts.insert(path, overrideText);
|
||||
}
|
||||
|
|
@ -257,8 +275,11 @@ bool QmlScanner::scanQmlFile(const QString& path, bool& singleton, bool& interna
|
|||
continue;
|
||||
}
|
||||
|
||||
if (import.endsWith(".js")) this->scannedFiles.push_back(cpath);
|
||||
else this->scanDir(cpath);
|
||||
if (import.endsWith(".js")) {
|
||||
this->scannedFiles.push_back(cpath);
|
||||
QByteArray jsData;
|
||||
this->readAndHashFile(cpath, jsData);
|
||||
} else this->scanDir(cpath);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -273,14 +294,12 @@ void QmlScanner::scanQmlRoot(const QString& path) {
|
|||
bool QmlScanner::scanQmlJson(const QString& path) {
|
||||
qCDebug(logQmlScanner) << "Scanning qml.json file" << path;
|
||||
|
||||
auto file = QFile(path);
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QByteArray data;
|
||||
if (!this->readAndHashFile(path, data)) {
|
||||
qCWarning(logQmlScanner) << "Failed to open file" << path;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto data = file.readAll();
|
||||
|
||||
// Importing this makes CI builds fail for some reason.
|
||||
QJsonParseError error; // NOLINT (misc-include-cleaner)
|
||||
auto json = QJsonDocument::fromJson(data, &error);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <qbytearray.h>
|
||||
#include <qcontainerfwd.h>
|
||||
#include <qdir.h>
|
||||
#include <qhash.h>
|
||||
|
|
@ -21,6 +22,7 @@ public:
|
|||
|
||||
QVector<QDir> scannedDirs;
|
||||
QVector<QString> scannedFiles;
|
||||
QHash<QString, QByteArray> fileHashes;
|
||||
QHash<QString, QString> fileIntercepts;
|
||||
|
||||
struct ScanError {
|
||||
|
|
@ -31,6 +33,9 @@ public:
|
|||
|
||||
QVector<ScanError> scanErrors;
|
||||
|
||||
bool readAndHashFile(const QString& path, QByteArray& data);
|
||||
[[nodiscard]] bool hasFileContentChanged(const QString& path) const;
|
||||
|
||||
private:
|
||||
QDir rootPath;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue