forked from qt-creator/qt-creator
VCS[git]: Implement add using '--intent-to-add' depending on version.
Implement IVersionControl::vcsAdd() using --intent-to-add with a cached version check. On this occasion, implement vcsDelete() as well using 'git rm -f'.
This commit is contained in:
@@ -131,7 +131,8 @@ GitClient::GitClient(GitPlugin* plugin)
|
|||||||
: m_msgWait(tr("Waiting for data...")),
|
: m_msgWait(tr("Waiting for data...")),
|
||||||
m_plugin(plugin),
|
m_plugin(plugin),
|
||||||
m_core(Core::ICore::instance()),
|
m_core(Core::ICore::instance()),
|
||||||
m_repositoryChangedSignalMapper(0)
|
m_repositoryChangedSignalMapper(0),
|
||||||
|
m_cachedGitVersion(0)
|
||||||
{
|
{
|
||||||
if (QSettings *s = m_core->settings()) {
|
if (QSettings *s = m_core->settings()) {
|
||||||
m_settings.fromSettings(s);
|
m_settings.fromSettings(s);
|
||||||
@@ -463,14 +464,20 @@ void GitClient::addFile(const QString &workingDirectory, const QString &fileName
|
|||||||
executeGit(workingDirectory, arguments, 0, true);
|
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)
|
if (Git::Constants::debug)
|
||||||
qDebug() << Q_FUNC_INFO << workingDirectory << files;
|
qDebug() << Q_FUNC_INFO << workingDirectory << files;
|
||||||
QByteArray outputText;
|
QByteArray outputText;
|
||||||
QByteArray errorText;
|
QByteArray errorText;
|
||||||
QStringList arguments;
|
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);
|
const bool rc = synchronousGit(workingDirectory, arguments, &outputText, &errorText);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
const QString errorMessage = tr("Unable to add %n file(s) to %1: %2", 0, files.size()).
|
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;
|
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,
|
bool GitClient::synchronousReset(const QString &workingDirectory,
|
||||||
const QStringList &files,
|
const QStringList &files,
|
||||||
QString *errorMessage)
|
QString *errorMessage)
|
||||||
@@ -1233,7 +1262,7 @@ bool GitClient::addAndCommit(const QString &repositoryDirectory,
|
|||||||
// for deletion
|
// for deletion
|
||||||
QStringList addFiles = checkedFiles.toSet().subtract(origDeletedFiles.toSet()).toList();
|
QStringList addFiles = checkedFiles.toSet().subtract(origDeletedFiles.toSet()).toList();
|
||||||
if (!addFiles.isEmpty())
|
if (!addFiles.isEmpty())
|
||||||
if (!synchronousAdd(repositoryDirectory, addFiles))
|
if (!synchronousAdd(repositoryDirectory, false, addFiles))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Do the final commit
|
// Do the final commit
|
||||||
@@ -1526,6 +1555,7 @@ void GitClient::setSettings(const GitSettings &s)
|
|||||||
if (QSettings *s = m_core->settings())
|
if (QSettings *s = m_core->settings())
|
||||||
m_settings.toSettings(s);
|
m_settings.toSettings(s);
|
||||||
m_binaryPath = m_settings.gitBinaryPath();
|
m_binaryPath = m_settings.gitBinaryPath();
|
||||||
|
m_cachedGitVersion = 0u;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1542,5 +1572,52 @@ void GitClient::connectRepositoryChanged(const QString & repository, GitCommand
|
|||||||
Qt::QueuedConnection);
|
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
|
||||||
|
|||||||
@@ -95,7 +95,13 @@ public:
|
|||||||
void checkoutBranch(const QString &workingDirectory, const QString &branch);
|
void checkoutBranch(const QString &workingDirectory, const QString &branch);
|
||||||
void hardReset(const QString &workingDirectory, const QString &commit = QString());
|
void hardReset(const QString &workingDirectory, const QString &commit = QString());
|
||||||
void addFile(const QString &workingDirectory, const QString &fileName);
|
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,
|
bool synchronousReset(const QString &workingDirectory,
|
||||||
const QStringList &files = QStringList(),
|
const QStringList &files = QStringList(),
|
||||||
QString *errorMessage = 0);
|
QString *errorMessage = 0);
|
||||||
@@ -139,6 +145,10 @@ public:
|
|||||||
QStringList *descriptions, QString *errorMessage);
|
QStringList *descriptions, QString *errorMessage);
|
||||||
bool synchronousTopRevision(const QString &workingDirectory, QString *revision = 0,
|
bool synchronousTopRevision(const QString &workingDirectory, QString *revision = 0,
|
||||||
QString *branch = 0, QString *errorMessage = 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 pull(const QString &workingDirectory);
|
||||||
void push(const QString &workingDirectory);
|
void push(const QString &workingDirectory);
|
||||||
@@ -223,6 +233,8 @@ private:
|
|||||||
QByteArray* outputText = 0,
|
QByteArray* outputText = 0,
|
||||||
QByteArray* errorText = 0,
|
QByteArray* errorText = 0,
|
||||||
bool logCommandToWindow = true);
|
bool logCommandToWindow = true);
|
||||||
|
// determine version as '(major << 16) + (minor << 8) + patch' or 0.
|
||||||
|
unsigned synchronousGitVersion(QString *errorMessage = 0);
|
||||||
|
|
||||||
enum RevertResult { RevertOk, RevertUnchanged, RevertCanceled, RevertFailed };
|
enum RevertResult { RevertOk, RevertUnchanged, RevertCanceled, RevertFailed };
|
||||||
RevertResult revertI(QStringList files, bool *isDirectory, QString *errorMessage);
|
RevertResult revertI(QStringList files, bool *isDirectory, QString *errorMessage);
|
||||||
@@ -234,6 +246,7 @@ private:
|
|||||||
GitSettings m_settings;
|
GitSettings m_settings;
|
||||||
QString m_binaryPath;
|
QString m_binaryPath;
|
||||||
QSignalMapper *m_repositoryChangedSignalMapper;
|
QSignalMapper *m_repositoryChangedSignalMapper;
|
||||||
|
unsigned m_cachedGitVersion;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,12 @@ QDebug operator<<(QDebug d, const Stash &);
|
|||||||
// Make QInputDialog play nicely
|
// Make QInputDialog play nicely
|
||||||
bool inputText(QWidget *parent, const QString &title, const QString &prompt, QString *s);
|
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 Internal
|
||||||
} // namespace Git
|
} // namespace Git
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,11 @@
|
|||||||
#include "gitplugin.h"
|
#include "gitplugin.h"
|
||||||
#include "gitutils.h"
|
#include "gitutils.h"
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtCore/QFileInfo>
|
||||||
|
|
||||||
static const char stashMessageKeywordC[] = "IVersionControl@";
|
static const char stashMessageKeywordC[] = "IVersionControl@";
|
||||||
static const char stashRevisionIdC[] = "revision";
|
static const char stashRevisionIdC[] = "revision";
|
||||||
|
|
||||||
@@ -54,12 +59,22 @@ QString GitVersionControl::displayName() const
|
|||||||
return QLatin1String("git");
|
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 GitVersionControl::supportsOperation(Operation operation) const
|
||||||
{
|
{
|
||||||
bool rc = false;
|
bool rc = false;
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case AddOperation:
|
case AddOperation:
|
||||||
|
rc = addOperationSupported();
|
||||||
|
break;
|
||||||
case DeleteOperation:
|
case DeleteOperation:
|
||||||
|
rc = true;
|
||||||
|
break;
|
||||||
case OpenOperation:
|
case OpenOperation:
|
||||||
break;
|
break;
|
||||||
case CreateRepositoryOperation:
|
case CreateRepositoryOperation:
|
||||||
@@ -75,15 +90,18 @@ bool GitVersionControl::vcsOpen(const QString & /*fileName*/)
|
|||||||
return false;
|
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'.
|
const QFileInfo fi(fileName);
|
||||||
return false;
|
return gitClient()->synchronousDelete(fi.absolutePath(), true, QStringList(fi.fileName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GitVersionControl::vcsCreateRepository(const QString &directory)
|
bool GitVersionControl::vcsCreateRepository(const QString &directory)
|
||||||
|
|||||||
Reference in New Issue
Block a user