Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/app/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@ Application::Application(int &argc, char **argv, bool haltOnParseError)
setOrganizationDomain(GITTYUP_ORGANIZATION_DOMAIN);
setDesktopFileName(GITTYUP_IDENTIFIER);

// When in test mode, redirect QSettings to a private, per-process location.
// This prevents test cases from accidentially cluttering up the user
// environment and allows for test cases to run in parallel
if (isInTest()) {
mTempSettingsDir.reset(new QTemporaryDir);
QSettings::setDefaultFormat(QSettings::IniFormat);
QSettings::setPath(QSettings::IniFormat, QSettings::UserScope,
mTempSettingsDir->path());
}

// Register types that are queued at runtime.
qRegisterMetaType<git::Id>();

Expand Down
2 changes: 2 additions & 0 deletions src/app/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "Theme.h"
#include <QApplication>
#include <QTemporaryDir>

class QNetworkAccessManager;
class QNetworkReply;
Expand Down Expand Up @@ -42,6 +43,7 @@ class Application : public QApplication {

QString mPathspec = QString();
QScopedPointer<Theme> mTheme;
QScopedPointer<QTemporaryDir> mTempSettingsDir;
QStringList mPositionalArguments;

static bool mIsInTest;
Expand Down
38 changes: 17 additions & 21 deletions src/app/Theme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,31 +40,27 @@ Theme::Theme() {
mDir = Settings::themesDir();
mName = QString("System");

// Create Qt theme.
// Create Qt theme. Build the script in memory rather than through a
// shared temp file: the theme template is combined with a generated
// style.default line reflecting the live QPalette, then executed
// directly, so concurrent processes never contend over a fixed path.
QFile themeFile(mDir.filePath(QString("%1.lua").arg(mName)).toUtf8());
if (themeFile.open(QIODevice::ReadOnly)) {
QDir tempDir = QDir::temp();
QFile tempFile(tempDir.filePath(QString("%1.lua").arg(mName)).toUtf8());
if (tempFile.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
mDir = tempDir;

// Copy template.
tempFile.write(themeFile.readAll());

// Add theme colors for scintilla editor.
tempFile.write(
QString("theme.property['style.default'] = 'fore:%1,back:%2'\n")
.arg(QPalette().color(QPalette::Text).name(QColor::HexRgb),
QPalette().color(QPalette::Base).name(QColor::HexRgb))
.toUtf8());
tempFile.close();
}
QByteArray source = themeFile.readAll();
themeFile.close();
}

// Load Qt theme.
QByteArray file = mDir.filePath(QString("%1.lua").arg(mName)).toUtf8();
mMap = ConfFile(file).parse("theme");
// Add theme colors for scintilla editor.
source +=
QString("theme.property['style.default'] = 'fore:%1,back:%2'\n")
.arg(QPalette().color(QPalette::Text).name(QColor::HexRgb),
QPalette().color(QPalette::Base).name(QColor::HexRgb))
.toUtf8();

mMap = ConfFile(source, mDir).parse("theme");
} else {
QByteArray file = mDir.filePath(QString("%1.lua").arg(mName)).toUtf8();
mMap = ConfFile(file).parse("theme");
}

QPalette palette;
QColor base = palette.color(QPalette::Base);
Expand Down
31 changes: 26 additions & 5 deletions src/conf/ConfFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,22 @@ QVariantMap table(lua_State *L) {

ConfFile::ConfFile(const QString &filename) : mFilename(filename) {}

ConfFile::ConfFile(const QByteArray &source, const QDir &baseDir)
: mSource(source), mBaseDir(baseDir) {}

ConfFile::~ConfFile() {}

QVariantMap ConfFile::parse(const QString &name) {
// Verify the existence of the file.
QFileInfo info(mFilename);
QString canPath = info.canonicalPath();
// Determine the directory used to extend package.path so require()
// keeps working relative to the script's logical location, whether
// the script itself comes from disk or from an in-memory buffer.
QString canPath;
if (mFilename.isEmpty()) {
canPath = mBaseDir.canonicalPath();
} else {
canPath = QFileInfo(mFilename).canonicalPath();
}

if (canPath.isEmpty())
return QVariantMap();

Expand Down Expand Up @@ -104,8 +114,19 @@ QVariantMap ConfFile::parse(const QString &name) {
lua_setglobal(L, tableName);
}

// Execute the configuration script.
if (luaL_dofile(L, localName))
// Execute the configuration script, either from disk or from the
// in-memory buffer supplied via the QByteArray/QDir constructor.
bool failed;
if (mFilename.isEmpty()) {
QByteArray chunkName = "@" + localPath + "/(generated)";
failed = luaL_loadbuffer(L, mSource.constData(), mSource.size(),
chunkName.constData()) ||
lua_pcall(L, 0, LUA_MULTRET, 0);
} else {
failed = luaL_dofile(L, localName);
}

if (failed)
lua_error(L);

// Push global table.
Expand Down
9 changes: 9 additions & 0 deletions src/conf/ConfFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,19 @@
#ifndef CONFFILE_H
#define CONFFILE_H

#include <QDir>
#include <QString>
#include <QVariant>

class ConfFile {
public:
ConfFile(const QString &filename);

// Parse Lua source held in memory rather than on disk. baseDir is used
// to set up package.path so the script can still require() files
// relative to the theme/config directory it logically belongs to.
ConfFile(const QByteArray &source, const QDir &baseDir);

virtual ~ConfFile();

// Table is the name of a new global table that the script
Expand All @@ -25,6 +32,8 @@ class ConfFile {

private:
QString mFilename;
QByteArray mSource;
QDir mBaseDir;
};

#endif
6 changes: 6 additions & 0 deletions src/ui/CommitList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ class CommitModel : public QAbstractListModel {
resetSettings();
}

~CommitModel() {
// Ensure that mStatus is stopped since it captures `this` and potentially
// might crash after the destructor is finished
cancelStatus();
}

git::Reference reference() const { return mRef; }

git::Diff status() const {
Expand Down
8 changes: 4 additions & 4 deletions test/CommitAuthorCommitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
#include "git/Reference.h"
#include "git/Signature.h"

#define INIT_REPO(repoPath, /* bool */ useTempDir) \
QString path = Test::extractRepository(repoPath, useTempDir); \
#define INIT_REPO(repoPath) \
QString path = Test::extractRepository(repoPath); \
QVERIFY(!path.isEmpty()); \
git::Repository repo = git::Repository::open(path); \
QVERIFY(repo.isValid()); \
Expand Down Expand Up @@ -46,7 +46,7 @@ void TestCommitAuthorCommitter::cleanupTestCase() {
* Check that author and email address are preserved during cherry pick
*/
void TestCommitAuthorCommitter::testCherryPickAuthorEmailPreservance() {
INIT_REPO("CherryPickAuthorEmail.zip", true);
INIT_REPO("CherryPickAuthorEmail.zip");

git::Commit commit =
repo.lookupCommit("710846db7a1fbd583975da0a6c10f9c2964ebd08");
Expand Down Expand Up @@ -78,7 +78,7 @@ void TestCommitAuthorCommitter::testCherryPickAuthorEmailPreservance() {
* is the current user
*/
void TestCommitAuthorCommitter::testRevertAuthorEmailPreservance() {
INIT_REPO("CherryPickAuthorEmail.zip", true);
INIT_REPO("CherryPickAuthorEmail.zip");

git::Commit commit =
repo.lookupCommit("710846db7a1fbd583975da0a6c10f9c2964ebd08");
Expand Down
Loading
Loading