forked from quickshell/quickshell
		
	core!: refactor launch sequence
Also includes slight changes to the command syntax. See --help for details.
This commit is contained in:
		
							parent
							
								
									da043e092a
								
							
						
					
					
						commit
						94e881e6b0
					
				
					 12 changed files with 729 additions and 651 deletions
				
			
		| 
						 | 
				
			
			@ -13,12 +13,16 @@ QDataStream& operator>>(QDataStream& stream, InstanceInfo& info) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
QDataStream& operator<<(QDataStream& stream, const RelaunchInfo& info) {
 | 
			
		||||
	stream << info.instance << info.noColor << info.sparseLogsOnly;
 | 
			
		||||
	stream << info.instance << info.noColor << info.timestamp << info.sparseLogsOnly
 | 
			
		||||
	       << info.defaultLogLevel << info.logRules;
 | 
			
		||||
 | 
			
		||||
	return stream;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QDataStream& operator>>(QDataStream& stream, RelaunchInfo& info) {
 | 
			
		||||
	stream >> info.instance >> info.noColor >> info.sparseLogsOnly;
 | 
			
		||||
	stream >> info.instance >> info.noColor >> info.timestamp >> info.sparseLogsOnly
 | 
			
		||||
	    >> info.defaultLogLevel >> info.logRules;
 | 
			
		||||
 | 
			
		||||
	return stream;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,13 +1,13 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <qdatetime.h>
 | 
			
		||||
#include <qlogging.h>
 | 
			
		||||
#include <qstring.h>
 | 
			
		||||
 | 
			
		||||
struct InstanceInfo {
 | 
			
		||||
	QString instanceId;
 | 
			
		||||
	QString configPath;
 | 
			
		||||
	QString shellId;
 | 
			
		||||
	QString initialWorkdir;
 | 
			
		||||
	QDateTime launchTime;
 | 
			
		||||
 | 
			
		||||
	static InstanceInfo CURRENT; // NOLINT
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +16,10 @@ struct InstanceInfo {
 | 
			
		|||
struct RelaunchInfo {
 | 
			
		||||
	InstanceInfo instance;
 | 
			
		||||
	bool noColor = false;
 | 
			
		||||
	bool timestamp = false;
 | 
			
		||||
	bool sparseLogsOnly = false;
 | 
			
		||||
	QtMsgType defaultLogLevel = QtWarningMsg;
 | 
			
		||||
	QString logRules;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
QDataStream& operator<<(QDataStream& stream, const InstanceInfo& info);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,16 +104,16 @@ void IpcClient::onError(QLocalSocket::LocalSocketError error) {
 | 
			
		|||
	qCCritical(logIpc) << "Socket Error" << error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool IpcClient::connect(const QString& id, const std::function<void(IpcClient& client)>& callback) {
 | 
			
		||||
int IpcClient::connect(const QString& id, const std::function<void(IpcClient& client)>& callback) {
 | 
			
		||||
	auto path = QsPaths::ipcPath(id);
 | 
			
		||||
	auto client = IpcClient(path);
 | 
			
		||||
	qCDebug(logIpc) << "Connecting to instance" << id << "at" << path;
 | 
			
		||||
 | 
			
		||||
	client.waitForConnected();
 | 
			
		||||
	if (!client.isConnected()) return false;
 | 
			
		||||
	if (!client.isConnected()) return -1;
 | 
			
		||||
	qCDebug(logIpc) << "Connected.";
 | 
			
		||||
 | 
			
		||||
	callback(client);
 | 
			
		||||
	return true;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
} // namespace qs::ipc
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ public:
 | 
			
		|||
 | 
			
		||||
	void kill();
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] static bool
 | 
			
		||||
	[[nodiscard]] static int
 | 
			
		||||
	connect(const QString& id, const std::function<void(IpcClient& client)>& callback);
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,6 +32,7 @@
 | 
			
		|||
Q_LOGGING_CATEGORY(logBare, "quickshell.bare");
 | 
			
		||||
 | 
			
		||||
namespace qs::log {
 | 
			
		||||
using namespace qt_logging_registry;
 | 
			
		||||
 | 
			
		||||
Q_LOGGING_CATEGORY(logLogging, "quickshell.logging", QtWarningMsg);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -48,8 +49,16 @@ void LogMessage::formatMessage(
 | 
			
		|||
    QTextStream& stream,
 | 
			
		||||
    const LogMessage& msg,
 | 
			
		||||
    bool color,
 | 
			
		||||
    bool timestamp
 | 
			
		||||
    bool timestamp,
 | 
			
		||||
    const QString& prefix
 | 
			
		||||
) {
 | 
			
		||||
	if (!prefix.isEmpty()) {
 | 
			
		||||
		if (color) stream << "\033[90m";
 | 
			
		||||
		stream << '[' << prefix << ']';
 | 
			
		||||
		if (timestamp) stream << ' ';
 | 
			
		||||
		if (color) stream << "\033[0m";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (timestamp) {
 | 
			
		||||
		if (color) stream << "\033[90m";
 | 
			
		||||
		stream << msg.time.toString("yyyy-MM-dd hh:mm:ss.zzz");
 | 
			
		||||
| 
						 | 
				
			
			@ -102,6 +111,30 @@ bool CategoryFilter::shouldDisplay(QtMsgType type) const {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CategoryFilter::apply(QLoggingCategory* category) const {
 | 
			
		||||
	category->setEnabled(QtDebugMsg, this->debug);
 | 
			
		||||
	category->setEnabled(QtInfoMsg, this->info);
 | 
			
		||||
	category->setEnabled(QtWarningMsg, this->warn);
 | 
			
		||||
	category->setEnabled(QtCriticalMsg, this->critical);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CategoryFilter::applyRule(
 | 
			
		||||
    QLatin1StringView category,
 | 
			
		||||
    const qt_logging_registry::QLoggingRule& rule
 | 
			
		||||
) {
 | 
			
		||||
	auto filterpass = rule.pass(category, QtDebugMsg);
 | 
			
		||||
	if (filterpass != 0) this->debug = filterpass > 0;
 | 
			
		||||
 | 
			
		||||
	filterpass = rule.pass(category, QtInfoMsg);
 | 
			
		||||
	if (filterpass != 0) this->info = filterpass > 0;
 | 
			
		||||
 | 
			
		||||
	filterpass = rule.pass(category, QtWarningMsg);
 | 
			
		||||
	if (filterpass != 0) this->warn = filterpass > 0;
 | 
			
		||||
 | 
			
		||||
	filterpass = rule.pass(category, QtCriticalMsg);
 | 
			
		||||
	if (filterpass != 0) this->critical = filterpass > 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LogManager::LogManager(): stdoutStream(stdout) {}
 | 
			
		||||
 | 
			
		||||
void LogManager::messageHandler(
 | 
			
		||||
| 
						 | 
				
			
			@ -122,7 +155,14 @@ void LogManager::messageHandler(
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	if (display) {
 | 
			
		||||
		LogMessage::formatMessage(self->stdoutStream, message, self->colorLogs, false);
 | 
			
		||||
		LogMessage::formatMessage(
 | 
			
		||||
		    self->stdoutStream,
 | 
			
		||||
		    message,
 | 
			
		||||
		    self->colorLogs,
 | 
			
		||||
		    self->timestampLogs,
 | 
			
		||||
		    self->prefix
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		self->stdoutStream << Qt::endl;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -132,21 +172,37 @@ void LogManager::messageHandler(
 | 
			
		|||
void LogManager::filterCategory(QLoggingCategory* category) {
 | 
			
		||||
	auto* instance = LogManager::instance();
 | 
			
		||||
 | 
			
		||||
	auto categoryName = QLatin1StringView(category->categoryName());
 | 
			
		||||
	auto isQs = categoryName.startsWith(QLatin1StringView("quickshell."));
 | 
			
		||||
 | 
			
		||||
	if (instance->lastCategoryFilter) {
 | 
			
		||||
		instance->lastCategoryFilter(category);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (QLatin1StringView(category->categoryName()).startsWith(QLatin1StringView("quickshell"))) {
 | 
			
		||||
	auto filter = CategoryFilter(category);
 | 
			
		||||
 | 
			
		||||
	if (isQs) {
 | 
			
		||||
		filter.debug = filter.debug || instance->mDefaultLevel == QtDebugMsg;
 | 
			
		||||
		filter.info = filter.debug || instance->mDefaultLevel == QtInfoMsg;
 | 
			
		||||
		filter.warn = filter.info || instance->mDefaultLevel == QtWarningMsg;
 | 
			
		||||
		filter.critical = filter.warn || instance->mDefaultLevel == QtCriticalMsg;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (const auto& rule: *instance->rules) {
 | 
			
		||||
		filter.applyRule(categoryName, rule);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (isQs && instance->sparse) {
 | 
			
		||||
		// We assume the category name pointer will always be the same and be comparable in the message handler.
 | 
			
		||||
		LogManager::instance()->sparseFilters.insert(
 | 
			
		||||
		    static_cast<const void*>(category->categoryName()),
 | 
			
		||||
		    CategoryFilter(category)
 | 
			
		||||
		    filter
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		category->setEnabled(QtDebugMsg, true);
 | 
			
		||||
		category->setEnabled(QtInfoMsg, true);
 | 
			
		||||
		category->setEnabled(QtWarningMsg, true);
 | 
			
		||||
		category->setEnabled(QtCriticalMsg, true);
 | 
			
		||||
		// all enabled by default
 | 
			
		||||
		CategoryFilter().apply(category);
 | 
			
		||||
	} else {
 | 
			
		||||
		filter.apply(category);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -155,15 +211,31 @@ LogManager* LogManager::instance() {
 | 
			
		|||
	return instance;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LogManager::init(bool color, bool sparseOnly) {
 | 
			
		||||
void LogManager::init(
 | 
			
		||||
    bool color,
 | 
			
		||||
    bool timestamp,
 | 
			
		||||
    bool sparseOnly,
 | 
			
		||||
    QtMsgType defaultLevel,
 | 
			
		||||
    const QString& rules,
 | 
			
		||||
    const QString& prefix
 | 
			
		||||
) {
 | 
			
		||||
	auto* instance = LogManager::instance();
 | 
			
		||||
	instance->colorLogs = color;
 | 
			
		||||
	instance->timestampLogs = timestamp;
 | 
			
		||||
	instance->sparse = sparseOnly;
 | 
			
		||||
	instance->prefix = prefix;
 | 
			
		||||
	instance->mDefaultLevel = defaultLevel;
 | 
			
		||||
	instance->mRulesString = rules;
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		QLoggingSettingsParser parser;
 | 
			
		||||
		parser.setContent(rules);
 | 
			
		||||
		instance->rules = new QList(parser.rules());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	qInstallMessageHandler(&LogManager::messageHandler);
 | 
			
		||||
 | 
			
		||||
	if (!sparseOnly) {
 | 
			
		||||
		instance->lastCategoryFilter = QLoggingCategory::installFilter(&LogManager::filterCategory);
 | 
			
		||||
	}
 | 
			
		||||
	instance->lastCategoryFilter = QLoggingCategory::installFilter(&LogManager::filterCategory);
 | 
			
		||||
 | 
			
		||||
	qCDebug(logLogging) << "Creating offthread logger...";
 | 
			
		||||
	auto* thread = new QThread();
 | 
			
		||||
| 
						 | 
				
			
			@ -181,6 +253,10 @@ void LogManager::initFs() {
 | 
			
		|||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString LogManager::rulesString() const { return this->mRulesString; }
 | 
			
		||||
QtMsgType LogManager::defaultLevel() const { return this->mDefaultLevel; }
 | 
			
		||||
bool LogManager::isSparse() const { return this->sparse; }
 | 
			
		||||
 | 
			
		||||
void LoggingThreadProxy::initInThread() {
 | 
			
		||||
	this->logging = new ThreadLogging(this);
 | 
			
		||||
	this->logging->init();
 | 
			
		||||
| 
						 | 
				
			
			@ -654,8 +730,6 @@ bool EncodedLogReader::registerCategory() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
bool readEncodedLogs(QIODevice* device, bool timestamps, const QString& rulespec) {
 | 
			
		||||
	using namespace qt_logging_registry;
 | 
			
		||||
 | 
			
		||||
	QList<QLoggingRule> rules;
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -695,17 +769,7 @@ bool readEncodedLogs(QIODevice* device, bool timestamps, const QString& rulespec
 | 
			
		|||
			filter = filters.value(message.readCategoryId);
 | 
			
		||||
		} else {
 | 
			
		||||
			for (const auto& rule: rules) {
 | 
			
		||||
				auto filterpass = rule.pass(message.category, QtDebugMsg);
 | 
			
		||||
				if (filterpass != 0) filter.debug = filterpass > 0;
 | 
			
		||||
 | 
			
		||||
				filterpass = rule.pass(message.category, QtInfoMsg);
 | 
			
		||||
				if (filterpass != 0) filter.info = filterpass > 0;
 | 
			
		||||
 | 
			
		||||
				filterpass = rule.pass(message.category, QtWarningMsg);
 | 
			
		||||
				if (filterpass != 0) filter.warn = filterpass > 0;
 | 
			
		||||
 | 
			
		||||
				filterpass = rule.pass(message.category, QtCriticalMsg);
 | 
			
		||||
				if (filterpass != 0) filter.critical = filterpass > 0;
 | 
			
		||||
				filter.applyRule(message.category, rule);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			filters.insert(message.readCategoryId, filter);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,7 +37,13 @@ struct LogMessage {
 | 
			
		|||
	QByteArray body;
 | 
			
		||||
	quint16 readCategoryId = 0;
 | 
			
		||||
 | 
			
		||||
	static void formatMessage(QTextStream& stream, const LogMessage& msg, bool color, bool timestamp);
 | 
			
		||||
	static void formatMessage(
 | 
			
		||||
	    QTextStream& stream,
 | 
			
		||||
	    const LogMessage& msg,
 | 
			
		||||
	    bool color,
 | 
			
		||||
	    bool timestamp,
 | 
			
		||||
	    const QString& prefix = ""
 | 
			
		||||
	);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
size_t qHash(const LogMessage& message);
 | 
			
		||||
| 
						 | 
				
			
			@ -58,6 +64,10 @@ private:
 | 
			
		|||
	ThreadLogging* logging = nullptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace qt_logging_registry {
 | 
			
		||||
class QLoggingRule;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct CategoryFilter {
 | 
			
		||||
	explicit CategoryFilter() = default;
 | 
			
		||||
	explicit CategoryFilter(QLoggingCategory* category)
 | 
			
		||||
| 
						 | 
				
			
			@ -67,6 +77,8 @@ struct CategoryFilter {
 | 
			
		|||
	    , critical(category->isCriticalEnabled()) {}
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] bool shouldDisplay(QtMsgType type) const;
 | 
			
		||||
	void apply(QLoggingCategory* category) const;
 | 
			
		||||
	void applyRule(QLatin1StringView category, const qt_logging_registry::QLoggingRule& rule);
 | 
			
		||||
 | 
			
		||||
	bool debug = true;
 | 
			
		||||
	bool info = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -78,11 +90,24 @@ class LogManager: public QObject {
 | 
			
		|||
	Q_OBJECT;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	static void init(bool color, bool sparseOnly);
 | 
			
		||||
	static void init(
 | 
			
		||||
	    bool color,
 | 
			
		||||
	    bool timestamp,
 | 
			
		||||
	    bool sparseOnly,
 | 
			
		||||
	    QtMsgType defaultLevel,
 | 
			
		||||
	    const QString& rules,
 | 
			
		||||
	    const QString& prefix = ""
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	static void initFs();
 | 
			
		||||
	static LogManager* instance();
 | 
			
		||||
 | 
			
		||||
	bool colorLogs = true;
 | 
			
		||||
	bool timestampLogs = false;
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] QString rulesString() const;
 | 
			
		||||
	[[nodiscard]] QtMsgType defaultLevel() const;
 | 
			
		||||
	[[nodiscard]] bool isSparse() const;
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
	void logMessage(LogMessage msg, bool showInSparse);
 | 
			
		||||
| 
						 | 
				
			
			@ -94,6 +119,11 @@ private:
 | 
			
		|||
	static void filterCategory(QLoggingCategory* category);
 | 
			
		||||
 | 
			
		||||
	QLoggingCategory::CategoryFilter lastCategoryFilter = nullptr;
 | 
			
		||||
	bool sparse = false;
 | 
			
		||||
	QString prefix;
 | 
			
		||||
	QString mRulesString;
 | 
			
		||||
	QList<qt_logging_registry::QLoggingRule>* rules = nullptr;
 | 
			
		||||
	QtMsgType mDefaultLevel = QtWarningMsg;
 | 
			
		||||
	QHash<const void*, CategoryFilter> sparseFilters;
 | 
			
		||||
 | 
			
		||||
	QTextStream stdoutStream;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1190
									
								
								src/core/main.cpp
									
										
									
									
									
								
							
							
						
						
									
										1190
									
								
								src/core/main.cpp
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -1,3 +1,7 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
int qs_main(int argc, char** argv); // NOLINT
 | 
			
		||||
namespace qs::launch {
 | 
			
		||||
 | 
			
		||||
int main(int argc, char** argv); // NOLINT
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,7 +64,7 @@ void CrashHandler::init() {
 | 
			
		|||
	qCInfo(logCrashHandler) << "Crash handler initialized.";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CrashHandler::setInstanceInfo(const RelaunchInfo& info) {
 | 
			
		||||
void CrashHandler::setRelaunchInfo(const RelaunchInfo& info) {
 | 
			
		||||
	this->d->infoFd = memfd_create("quickshell:instance_info", MFD_CLOEXEC);
 | 
			
		||||
 | 
			
		||||
	if (this->d->infoFd == -1) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ public:
 | 
			
		|||
	Q_DISABLE_COPY_MOVE(CrashHandler);
 | 
			
		||||
 | 
			
		||||
	void init();
 | 
			
		||||
	void setInstanceInfo(const RelaunchInfo& info);
 | 
			
		||||
	void setRelaunchInfo(const RelaunchInfo& info);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	CrashHandlerPrivate* d;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,14 @@ void qsCheckCrash(int argc, char** argv) {
 | 
			
		|||
		ds >> info;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LogManager::init(!info.noColor, false);
 | 
			
		||||
	LogManager::init(
 | 
			
		||||
	    !info.noColor,
 | 
			
		||||
	    info.timestamp,
 | 
			
		||||
	    info.sparseLogsOnly,
 | 
			
		||||
	    info.defaultLogLevel,
 | 
			
		||||
	    info.logRules
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	auto crashDir = QsPaths::crashDir(info.instance.instanceId);
 | 
			
		||||
 | 
			
		||||
	qCInfo(logCrashReporter) << "Starting crash reporter...";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,3 @@
 | 
			
		|||
#include "core/main.hpp"
 | 
			
		||||
 | 
			
		||||
int main(int argc, char** argv) { return qs_main(argc, argv); }
 | 
			
		||||
int main(int argc, char** argv) { return qs::launch::main(argc, argv); }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue