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.
|
- IPC operations filter available instances to the current display connection by default.
|
||||||
- PwNodeLinkTracker ignores sound level monitoring programs.
|
- PwNodeLinkTracker ignores sound level monitoring programs.
|
||||||
- Replaced breakpad with cpptrace.
|
- Replaced breakpad with cpptrace.
|
||||||
|
- Reloads are prevented if no file content has changed.
|
||||||
|
|
||||||
## Bug Fixes
|
## Bug Fixes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -209,6 +209,8 @@ bool EngineGeneration::setExtraWatchedFiles(const QVector<QString>& files) {
|
||||||
for (const auto& file: files) {
|
for (const auto& file: files) {
|
||||||
if (!this->scanner.scannedFiles.contains(file)) {
|
if (!this->scanner.scannedFiles.contains(file)) {
|
||||||
this->extraWatchedFiles.append(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);
|
auto fileInfo = QFileInfo(name);
|
||||||
if (fileInfo.isFile() && fileInfo.size() == 0) return;
|
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();
|
emit this->filesChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -237,6 +244,11 @@ void EngineGeneration::onDirectoryChanged() {
|
||||||
// try to find any files that were just deleted from a replace operation
|
// try to find any files that were just deleted from a replace operation
|
||||||
for (auto& file: this->deletedWatchedFiles) {
|
for (auto& file: this->deletedWatchedFiles) {
|
||||||
if (QFileInfo(file).exists()) {
|
if (QFileInfo(file).exists()) {
|
||||||
|
if (!this->scanner.hasFileContentChanged(file)) {
|
||||||
|
qCDebug(logQmlScanner) << "Ignoring restored file with unchanged content:" << file;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
emit this->filesChanged();
|
emit this->filesChanged();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <qcontainerfwd.h>
|
#include <qcontainerfwd.h>
|
||||||
|
#include <qcryptographichash.h>
|
||||||
#include <qdir.h>
|
#include <qdir.h>
|
||||||
#include <qfileinfo.h>
|
#include <qfileinfo.h>
|
||||||
#include <qjsengine.h>
|
#include <qjsengine.h>
|
||||||
|
|
@ -21,6 +22,25 @@
|
||||||
|
|
||||||
QS_LOGGING_CATEGORY(logQmlScanner, "quickshell.qmlscanner", QtWarningMsg);
|
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) {
|
void QmlScanner::scanDir(const QDir& dir) {
|
||||||
if (this->scannedDirs.contains(dir)) return;
|
if (this->scannedDirs.contains(dir)) return;
|
||||||
this->scannedDirs.push_back(dir);
|
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;
|
qCDebug(logQmlScanner) << "Scanning qml file" << path;
|
||||||
|
|
||||||
auto file = QFile(path);
|
QByteArray fileData;
|
||||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
if (!this->readAndHashFile(path, fileData)) {
|
||||||
qCWarning(logQmlScanner) << "Failed to open file" << path;
|
qCWarning(logQmlScanner) << "Failed to open file" << path;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto stream = QTextStream(&file);
|
auto stream = QTextStream(&fileData);
|
||||||
auto imports = QVector<QString>();
|
auto imports = QVector<QString>();
|
||||||
|
|
||||||
bool inHeader = true;
|
bool inHeader = true;
|
||||||
|
|
@ -219,8 +239,6 @@ bool QmlScanner::scanQmlFile(const QString& path, bool& singleton, bool& interna
|
||||||
postError("unclosed preprocessor if block");
|
postError("unclosed preprocessor if block");
|
||||||
}
|
}
|
||||||
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
if (isOverridden) {
|
if (isOverridden) {
|
||||||
this->fileIntercepts.insert(path, overrideText);
|
this->fileIntercepts.insert(path, overrideText);
|
||||||
}
|
}
|
||||||
|
|
@ -257,8 +275,11 @@ bool QmlScanner::scanQmlFile(const QString& path, bool& singleton, bool& interna
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (import.endsWith(".js")) this->scannedFiles.push_back(cpath);
|
if (import.endsWith(".js")) {
|
||||||
else this->scanDir(cpath);
|
this->scannedFiles.push_back(cpath);
|
||||||
|
QByteArray jsData;
|
||||||
|
this->readAndHashFile(cpath, jsData);
|
||||||
|
} else this->scanDir(cpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -273,14 +294,12 @@ void QmlScanner::scanQmlRoot(const QString& path) {
|
||||||
bool QmlScanner::scanQmlJson(const QString& path) {
|
bool QmlScanner::scanQmlJson(const QString& path) {
|
||||||
qCDebug(logQmlScanner) << "Scanning qml.json file" << path;
|
qCDebug(logQmlScanner) << "Scanning qml.json file" << path;
|
||||||
|
|
||||||
auto file = QFile(path);
|
QByteArray data;
|
||||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
if (!this->readAndHashFile(path, data)) {
|
||||||
qCWarning(logQmlScanner) << "Failed to open file" << path;
|
qCWarning(logQmlScanner) << "Failed to open file" << path;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = file.readAll();
|
|
||||||
|
|
||||||
// Importing this makes CI builds fail for some reason.
|
// Importing this makes CI builds fail for some reason.
|
||||||
QJsonParseError error; // NOLINT (misc-include-cleaner)
|
QJsonParseError error; // NOLINT (misc-include-cleaner)
|
||||||
auto json = QJsonDocument::fromJson(data, &error);
|
auto json = QJsonDocument::fromJson(data, &error);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <qbytearray.h>
|
||||||
#include <qcontainerfwd.h>
|
#include <qcontainerfwd.h>
|
||||||
#include <qdir.h>
|
#include <qdir.h>
|
||||||
#include <qhash.h>
|
#include <qhash.h>
|
||||||
|
|
@ -21,6 +22,7 @@ public:
|
||||||
|
|
||||||
QVector<QDir> scannedDirs;
|
QVector<QDir> scannedDirs;
|
||||||
QVector<QString> scannedFiles;
|
QVector<QString> scannedFiles;
|
||||||
|
QHash<QString, QByteArray> fileHashes;
|
||||||
QHash<QString, QString> fileIntercepts;
|
QHash<QString, QString> fileIntercepts;
|
||||||
|
|
||||||
struct ScanError {
|
struct ScanError {
|
||||||
|
|
@ -31,6 +33,9 @@ public:
|
||||||
|
|
||||||
QVector<ScanError> scanErrors;
|
QVector<ScanError> scanErrors;
|
||||||
|
|
||||||
|
bool readAndHashFile(const QString& path, QByteArray& data);
|
||||||
|
[[nodiscard]] bool hasFileContentChanged(const QString& path) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QDir rootPath;
|
QDir rootPath;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue