summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/plugins/git/gitclient.cpp85
-rw-r--r--src/plugins/git/gitclient.h15
-rw-r--r--src/plugins/git/gitutils.h6
-rw-r--r--src/plugins/git/gitversioncontrol.cpp28
4 files changed, 124 insertions, 10 deletions
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index b98462562a..f2020b3a5f 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -131,7 +131,8 @@ GitClient::GitClient(GitPlugin* plugin)
: m_msgWait(tr("Waiting for data...")),
m_plugin(plugin),
m_core(Core::ICore::instance()),
- m_repositoryChangedSignalMapper(0)
+ m_repositoryChangedSignalMapper(0),
+ m_cachedGitVersion(0)
{
if (QSettings *s = m_core->settings()) {
m_settings.fromSettings(s);
@@ -463,14 +464,20 @@ void GitClient::addFile(const QString &workingDirectory, const QString &fileName
executeGit(workingDirectory, arguments, 0, true);
}
-bool GitClient::synchronousAdd(const QString &workingDirectory, const QStringList &files)
+// Warning: 'intendToAdd' works only from 1.6.1 onwards
+bool GitClient::synchronousAdd(const QString &workingDirectory,
+ bool intendToAdd,
+ const QStringList &files)
{
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << workingDirectory << files;
QByteArray outputText;
QByteArray errorText;
QStringList arguments;
- arguments << QLatin1String("add") << files;
+ arguments << QLatin1String("add");
+ if (intendToAdd)
+ arguments << QLatin1String("--intent-to-add");
+ arguments.append(files);
const bool rc = synchronousGit(workingDirectory, arguments, &outputText, &errorText);
if (!rc) {
const QString errorMessage = tr("Unable to add %n file(s) to %1: %2", 0, files.size()).
@@ -480,6 +487,28 @@ bool GitClient::synchronousAdd(const QString &workingDirectory, const QStringLis
return rc;
}
+bool GitClient::synchronousDelete(const QString &workingDirectory,
+ bool force,
+ const QStringList &files)
+{
+ if (Git::Constants::debug)
+ qDebug() << Q_FUNC_INFO << workingDirectory << files;
+ QByteArray outputText;
+ QByteArray errorText;
+ QStringList arguments;
+ arguments << QLatin1String("rm");
+ if (force)
+ arguments << QLatin1String("--force");
+ arguments.append(files);
+ const bool rc = synchronousGit(workingDirectory, arguments, &outputText, &errorText);
+ if (!rc) {
+ const QString errorMessage = tr("Unable to remove %n file(s) from %1: %2", 0, files.size()).
+ arg(workingDirectory, commandOutputFromLocal8Bit(errorText));
+ VCSBase::VCSBaseOutputWindow::instance()->appendError(errorMessage);
+ }
+ return rc;
+}
+
bool GitClient::synchronousReset(const QString &workingDirectory,
const QStringList &files,
QString *errorMessage)
@@ -1233,7 +1262,7 @@ bool GitClient::addAndCommit(const QString &repositoryDirectory,
// for deletion
QStringList addFiles = checkedFiles.toSet().subtract(origDeletedFiles.toSet()).toList();
if (!addFiles.isEmpty())
- if (!synchronousAdd(repositoryDirectory, addFiles))
+ if (!synchronousAdd(repositoryDirectory, false, addFiles))
return false;
// Do the final commit
@@ -1526,6 +1555,7 @@ void GitClient::setSettings(const GitSettings &s)
if (QSettings *s = m_core->settings())
m_settings.toSettings(s);
m_binaryPath = m_settings.gitBinaryPath();
+ m_cachedGitVersion = 0u;
}
}
@@ -1542,5 +1572,52 @@ void GitClient::connectRepositoryChanged(const QString & repository, GitCommand
Qt::QueuedConnection);
}
+// determine version as '(major << 16) + (minor << 8) + patch' or 0.
+unsigned GitClient::gitVersion(QString *errorMessage /* = 0 */)
+{
+ if (!m_cachedGitVersion)
+ m_cachedGitVersion = synchronousGitVersion(errorMessage);
+ return m_cachedGitVersion;
}
+
+QString GitClient::gitVersionString(QString *errorMessage)
+{
+ if (const unsigned version = gitVersion(errorMessage)) {
+ QString rc;
+ QTextStream(&rc) << (version >> 16) << '.'
+ << (0xFF & (version >> 8)) << '.'
+ << (version & 0xFF);
+ return rc;
+ }
+ return QString();
+}
+
+// determine version as '(major << 16) + (minor << 8) + patch' or 0.
+unsigned GitClient::synchronousGitVersion(QString *errorMessage /* = 0 */)
+{
+ // run git --version
+ QByteArray outputText;
+ QByteArray errorText;
+ const bool rc = synchronousGit(QString(), QStringList("--version"), &outputText, &errorText);
+ if (!rc) {
+ const QString msg = tr("Unable to determine git version: %1").arg(commandOutputFromLocal8Bit(errorText));
+ if (errorMessage) {
+ *errorMessage = msg;
+ } else {
+ VCSBase::VCSBaseOutputWindow::instance()->appendError(msg);
+ }
+ return 0;
+ }
+ // cut 'git version 1.6.5.1.sha'
+ const QString output = commandOutputFromLocal8Bit(outputText);
+ const QRegExp versionPattern(QLatin1String("^[^\\d]+([\\d])\\.([\\d])\\.([\\d]).*$"));
+ QTC_ASSERT(versionPattern.isValid(), return 0);
+ QTC_ASSERT(versionPattern.exactMatch(output), return 0);
+ const unsigned major = versionPattern.cap(1).toUInt();
+ const unsigned minor = versionPattern.cap(2).toUInt();
+ const unsigned patch = versionPattern.cap(3).toUInt();
+ return version(major, minor, patch);
}
+
+} // namespace Internal
+} // namespace Git
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 55f6800d40..6b6ca1a655 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -95,7 +95,13 @@ public:
void checkoutBranch(const QString &workingDirectory, const QString &branch);
void hardReset(const QString &workingDirectory, const QString &commit = QString());
void addFile(const QString &workingDirectory, const QString &fileName);
- bool synchronousAdd(const QString &workingDirectory, const QStringList &files);
+ bool synchronousAdd(const QString &workingDirectory,
+ // Warning: Works only from 1.6.1 onwards
+ bool intendToAdd,
+ const QStringList &files);
+ bool synchronousDelete(const QString &workingDirectory,
+ bool force,
+ const QStringList &files);
bool synchronousReset(const QString &workingDirectory,
const QStringList &files = QStringList(),
QString *errorMessage = 0);
@@ -139,6 +145,10 @@ public:
QStringList *descriptions, QString *errorMessage);
bool synchronousTopRevision(const QString &workingDirectory, QString *revision = 0,
QString *branch = 0, QString *errorMessage = 0);
+ // determine version as '(major << 16) + (minor << 8) + patch' or 0
+ // with some smart caching.
+ unsigned gitVersion(QString *errorMessage = 0);
+ QString gitVersionString(QString *errorMessage = 0);
void pull(const QString &workingDirectory);
void push(const QString &workingDirectory);
@@ -223,6 +233,8 @@ private:
QByteArray* outputText = 0,
QByteArray* errorText = 0,
bool logCommandToWindow = true);
+ // determine version as '(major << 16) + (minor << 8) + patch' or 0.
+ unsigned synchronousGitVersion(QString *errorMessage = 0);
enum RevertResult { RevertOk, RevertUnchanged, RevertCanceled, RevertFailed };
RevertResult revertI(QStringList files, bool *isDirectory, QString *errorMessage);
@@ -234,6 +246,7 @@ private:
GitSettings m_settings;
QString m_binaryPath;
QSignalMapper *m_repositoryChangedSignalMapper;
+ unsigned m_cachedGitVersion;
};
diff --git a/src/plugins/git/gitutils.h b/src/plugins/git/gitutils.h
index 16d80ca656..7dbefc9158 100644
--- a/src/plugins/git/gitutils.h
+++ b/src/plugins/git/gitutils.h
@@ -54,6 +54,12 @@ QDebug operator<<(QDebug d, const Stash &);
// Make QInputDialog play nicely
bool inputText(QWidget *parent, const QString &title, const QString &prompt, QString *s);
+// Version information following Qt convention
+inline unsigned version(unsigned major, unsigned minor, unsigned patch)
+{
+ return (major << 16) + (minor << 8) + patch;
+}
+
} // namespace Internal
} // namespace Git
diff --git a/src/plugins/git/gitversioncontrol.cpp b/src/plugins/git/gitversioncontrol.cpp
index c98f068892..49955873ab 100644
--- a/src/plugins/git/gitversioncontrol.cpp
+++ b/src/plugins/git/gitversioncontrol.cpp
@@ -32,6 +32,11 @@
#include "gitplugin.h"
#include "gitutils.h"
+#include <utils/qtcassert.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QFileInfo>
+
static const char stashMessageKeywordC[] = "IVersionControl@";
static const char stashRevisionIdC[] = "revision";
@@ -54,12 +59,22 @@ QString GitVersionControl::displayName() const
return QLatin1String("git");
}
+// Add: Implement using "git add --intent-to-add" starting from 1.6.1
+static inline bool addOperationSupported()
+{
+ return gitClient()->gitVersion() >= version(1, 6, 1);
+}
+
bool GitVersionControl::supportsOperation(Operation operation) const
{
bool rc = false;
switch (operation) {
case AddOperation:
+ rc = addOperationSupported();
+ break;
case DeleteOperation:
+ rc = true;
+ break;
case OpenOperation:
break;
case CreateRepositoryOperation:
@@ -75,15 +90,18 @@ bool GitVersionControl::vcsOpen(const QString & /*fileName*/)
return false;
}
-bool GitVersionControl::vcsAdd(const QString & /*fileName*/)
+bool GitVersionControl::vcsAdd(const QString & fileName)
{
- return false;
+ // Implement in terms of using "--intent-to-add"
+ QTC_ASSERT(addOperationSupported(), return false);
+ const QFileInfo fi(fileName);
+ return gitClient()->synchronousAdd(fi.absolutePath(), true, QStringList(fi.fileName()));
}
-bool GitVersionControl::vcsDelete(const QString & /*fileName*/)
+bool GitVersionControl::vcsDelete(const QString & fileName)
{
- // TODO: implement using 'git rm'.
- return false;
+ const QFileInfo fi(fileName);
+ return gitClient()->synchronousDelete(fi.absolutePath(), true, QStringList(fi.fileName()));
}
bool GitVersionControl::vcsCreateRepository(const QString &directory)