Commit 90b094e8 authored by Friedemann Kleint's avatar Friedemann Kleint Committed by unknown
Browse files

Make the git plugin look for the binary in the path specified in the settings....

Make the git plugin look for the binary in the path specified in the settings. Previously, the environment was passed to the process, but that did not affect the location of the binary.
parent 890220d5
......@@ -37,6 +37,8 @@
#include <QtCore/QTimer>
#include <QtCore/QEventLoop>
#include <QtCore/QTextCodec>
#include <QtCore/QFileInfo>
#include <QtCore/QDir>
#include <QtGui/QApplication>
......@@ -366,5 +368,108 @@ void SynchronousProcess::processStdErr(bool emitSignals)
}
}
// Path utilities
enum OS_Type { OS_Mac, OS_Windows, OS_Unix };
#ifdef Q_OS_WIN
static const OS_Type pathOS = OS_Windows;
#else
# ifdef Q_OS_MAC
static const OS_Type pathOS = OS_Mac;
# else
static const OS_Type pathOS = OS_Unix;
# endif
#endif
// Locate a binary in a directory, applying all kinds of
// extensions the operating system supports.
static QString checkBinary(const QDir &dir, const QString &binary)
{
// naive UNIX approach
const QFileInfo info(dir.filePath(binary));
if (info.isFile() && info.isExecutable())
return info.absoluteFilePath();
// Does the OS have some weird extension concept or does the
// binary have a 3 letter extension?
if (pathOS == OS_Unix)
return QString();
const int dotIndex = binary.lastIndexOf(QLatin1Char('.'));
if (dotIndex != -1 && dotIndex == binary.size() - 4)
return QString();
switch (pathOS) {
case OS_Unix:
break;
case OS_Windows: {
static const char *windowsExtensions[] = {".cmd", ".bat", ".exe", ".com" };
// Check the Windows extensions using the order
const int windowsExtensionCount = sizeof(windowsExtensions)/sizeof(const char*);
for (int e = 0; e < windowsExtensionCount; e ++) {
const QFileInfo windowsBinary(dir.filePath(binary + QLatin1String(windowsExtensions[e])));
if (windowsBinary.isFile() && windowsBinary.isExecutable())
return windowsBinary.absoluteFilePath();
}
}
break;
case OS_Mac: {
// Check for Mac app folders
const QFileInfo appFolder(dir.filePath(binary + QLatin1String(".app")));
if (appFolder.isDir()) {
QString macBinaryPath = appFolder.absoluteFilePath();
macBinaryPath += QLatin1String("/Contents/MacOS/");
macBinaryPath += binary;
const QFileInfo macBinary(macBinaryPath);
if (macBinary.isFile() && macBinary.isExecutable())
return macBinary.absoluteFilePath();
}
}
break;
}
return QString();
}
QString SynchronousProcess::locateBinary(const QString &path, const QString &binary)
{
// Absolute file?
const QFileInfo absInfo(binary);
if (absInfo.isAbsolute())
return checkBinary(absInfo.dir(), absInfo.fileName());
// Windows finds binaries in the current directory
if (pathOS == OS_Windows) {
const QString currentDirBinary = checkBinary(QDir::current(), binary);
if (!currentDirBinary.isEmpty())
return currentDirBinary;
}
const QStringList paths = path.split(pathSeparator());
if (paths.empty())
return QString();
const QStringList::const_iterator cend = paths.constEnd();
for (QStringList::const_iterator it = paths.constBegin(); it != cend; ++it) {
const QDir dir(*it);
const QString rc = checkBinary(dir, binary);
if (!rc.isEmpty())
return rc;
}
return QString();
}
QString SynchronousProcess::locateBinary(const QString &binary)
{
const QByteArray path = qgetenv("PATH");
return locateBinary(QString::fromLocal8Bit(path), binary);
}
QChar SynchronousProcess::pathSeparator()
{
if (pathOS == OS_Windows)
return QLatin1Char(';');
return QLatin1Char(':');
}
} // namespace Utils
} // namespace Core
......@@ -114,6 +114,12 @@ public:
SynchronousProcessResponse run(const QString &binary, const QStringList &args);
// Helpers to find binaries. Do not use it for other path variables
// and file types.
static QString locateBinary(const QString &binary);
static QString locateBinary(const QString &path, const QString &binary);
static QChar pathSeparator();
signals:
void stdOut(const QByteArray &data, bool firstTime);
void stdErr(const QByteArray &data, bool firstTime);
......
......@@ -102,8 +102,10 @@ GitClient::GitClient(GitPlugin* plugin)
m_plugin(plugin),
m_core(Core::ICore::instance())
{
if (QSettings *s = m_core->settings())
if (QSettings *s = m_core->settings()) {
m_settings.fromSettings(s);
m_binaryPath = m_settings.gitBinaryPath();
}
}
GitClient::~GitClient()
......@@ -478,7 +480,7 @@ GitCommand *GitClient::createCommand(const QString &workingDirectory,
if (m_settings.adoptPath)
environment.set(QLatin1String("PATH"), m_settings.path);
GitCommand* command = new GitCommand(workingDirectory, environment);
GitCommand* command = new GitCommand(m_binaryPath, workingDirectory, environment);
if (outputToWindow) {
if (!editor) { // assume that the commands output is the important thing
connect(command, SIGNAL(outputData(QByteArray)), this, SLOT(appendDataAndPopup(QByteArray)));
......@@ -527,10 +529,9 @@ bool GitClient::synchronousGit(const QString &workingDirectory,
{
if (Git::Constants::debug)
qDebug() << "synchronousGit" << workingDirectory << arguments;
const QString binary = QLatin1String(Constants::GIT_BINARY);
if (logCommandToWindow)
m_plugin->outputWindow()->append(formatCommand(binary, arguments));
m_plugin->outputWindow()->append(formatCommand(m_binaryPath, arguments));
QProcess process;
process.setWorkingDirectory(workingDirectory);
......@@ -540,7 +541,7 @@ bool GitClient::synchronousGit(const QString &workingDirectory,
environment.set(QLatin1String("PATH"), m_settings.path);
process.setEnvironment(environment.toStringList());
process.start(binary, arguments);
process.start(m_binaryPath, arguments);
if (!process.waitForFinished()) {
if (errorText)
*errorText = "Error: Git timed out";
......@@ -1000,6 +1001,6 @@ void GitClient::setSettings(const GitSettings &s)
m_settings = s;
if (QSettings *s = m_core->settings())
m_settings.toSettings(s);
m_binaryPath = m_settings.gitBinaryPath();
}
}
......@@ -176,6 +176,7 @@ private:
GitPlugin *m_plugin;
Core::ICore *m_core;
GitSettings m_settings;
QString m_binaryPath;
};
......
......@@ -61,8 +61,10 @@ GitCommand::Job::Job(const QStringList &a, int t) :
{
}
GitCommand::GitCommand(const QString &workingDirectory,
GitCommand::GitCommand(const QString &binaryPath,
const QString &workingDirectory,
ProjectExplorer::Environment &environment) :
m_binaryPath(binaryPath),
m_workingDirectory(workingDirectory),
m_environment(environmentToList(environment))
{
......@@ -109,7 +111,7 @@ void GitCommand::run()
if (Git::Constants::debug)
qDebug() << "GitCommand::run" << j << '/' << count << m_jobs.at(j).arguments;
process.start(QLatin1String(Constants::GIT_BINARY), m_jobs.at(j).arguments);
process.start(m_binaryPath, m_jobs.at(j).arguments);
if (!process.waitForFinished(m_jobs.at(j).timeout * 1000)) {
ok = false;
error += QLatin1String("Error: Git timed out");
......
......@@ -43,9 +43,11 @@ namespace Internal {
class GitCommand : public QObject
{
Q_DISABLE_COPY(GitCommand)
Q_OBJECT
public:
explicit GitCommand(const QString &workingDirectory,
explicit GitCommand(const QString &binaryPath,
const QString &workingDirectory,
ProjectExplorer::Environment &environment);
......@@ -67,8 +69,7 @@ private:
int timeout;
};
QStringList environment() const;
const QString m_binaryPath;
const QString m_workingDirectory;
const QStringList m_environment;
......
......@@ -32,9 +32,13 @@
***************************************************************************/
#include "gitsettings.h"
#include "gitconstants.h"
#include <utils/synchronousprocess.h>
#include <QtCore/QSettings>
#include <QtCore/QTextStream>
#include <QtCore/QCoreApplication>
static const char *groupC = "Git";
static const char *sysEnvKeyC = "SysEnv";
......@@ -79,5 +83,30 @@ bool GitSettings::equals(const GitSettings &s) const
return adoptPath == s.adoptPath && path == s.path && logCount == s.logCount && timeout == s.timeout;
}
QString GitSettings::gitBinaryPath(bool *ok, QString *errorMessage) const
{
// Locate binary in path if one is specified, otherwise default
// to pathless binary
if (ok)
*ok = true;
if (errorMessage)
errorMessage->clear();
const QString binary = QLatin1String(Constants::GIT_BINARY);
// Easy, git is assumed to be elsewhere accessible
if (!adoptPath)
return binary;
// Search in path?
const QString pathBinary = Core::Utils::SynchronousProcess::locateBinary(path, binary);
if (pathBinary.isEmpty()) {
if (ok)
*ok = false;
if (errorMessage)
*errorMessage = QCoreApplication::translate("GitSettings",
"The binary '%1' could not be located in the path '%2'").arg(binary, path);
return binary;
}
return pathBinary;
}
}
}
......@@ -51,6 +51,8 @@ struct GitSettings
void fromSettings(QSettings *);
void toSettings(QSettings *) const;
QString gitBinaryPath(bool *ok = 0, QString *errorMessage = 0) const;
bool equals(const GitSettings &s) const;
bool adoptPath;
......
......@@ -36,8 +36,10 @@
#include "gitplugin.h"
#include <QtCore/QDebug>
#include <QtGui/QMessageBox>
using namespace Git::Internal;
namespace Git {
namespace Internal {
SettingsPageWidget::SettingsPageWidget(QWidget *parent) :
QWidget(parent)
......@@ -101,6 +103,17 @@ void SettingsPage::apply()
{
if (!m_widget)
return;
const GitSettings newSettings = m_widget->settings();
// Warn if git cannot be found in path if the widget is on top
if (m_widget->isVisible()) {
bool gitFoundOk;
QString errorMessage;
newSettings.gitBinaryPath(&gitFoundOk, &errorMessage);
if (!gitFoundOk)
QMessageBox::warning(m_widget, tr("Git Settings"), errorMessage);
}
GitPlugin::instance()->setSettings(m_widget->settings());
GitPlugin::instance()->setSettings(newSettings);
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment