Newer
Older
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
/* Revert: This function can be called with a file list (to revert single
* files) or a single directory (revert all). Qt Creator currently has only
* 'revert single' in its VCS menus, but the code is prepared to deal with
* reverting a directory pending a sophisticated selection dialog in the
* VCSBase plugin. */
GitClient::RevertResult GitClient::revertI(QStringList files, bool *ptrToIsDirectory, QString *errorMessage)
{
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << files;
if (files.empty())
return RevertCanceled;
// Figure out the working directory
const QFileInfo firstFile(files.front());
const bool isDirectory = firstFile.isDir();
if (ptrToIsDirectory)
*ptrToIsDirectory = isDirectory;
const QString workingDirectory = isDirectory ? firstFile.absoluteFilePath() : firstFile.absolutePath();
const QString repoDirectory = GitClient::findRepositoryForDirectory(workingDirectory);
if (repoDirectory.isEmpty()) {
*errorMessage = msgRepositoryNotFound(workingDirectory);
return RevertFailed;
}
// Check for changes
QString output;
switch (gitStatus(repoDirectory, false, &output, errorMessage)) {
case StatusChanged:
break;
case StatusUnchanged:
return RevertUnchanged;
case StatusFailed:
return RevertFailed;
}

Friedemann Kleint
committed
if (!data.parseFilesFromStatus(output)) {
*errorMessage = msgParseFilesFailed();
return RevertFailed;
}
// If we are looking at files, make them relative to the repository
// directory to match them in the status output list.
if (!isDirectory) {
const QDir repoDir(repoDirectory);
const QStringList::iterator cend = files.end();
for (QStringList::iterator it = files.begin(); it != cend; ++it)
*it = repoDir.relativeFilePath(*it);
}
// From the status output, determine all modified [un]staged files.

Friedemann Kleint
committed
const QString modifiedState = QLatin1String("modified");
const QStringList allStagedFiles = data.stagedFileNames(modifiedState);
const QStringList allUnstagedFiles = data.unstagedFileNames(modifiedState);
// Unless a directory was passed, filter all modified files for the
// argument file list.
QStringList stagedFiles = allStagedFiles;
QStringList unstagedFiles = allUnstagedFiles;
if (!isDirectory) {
const QSet<QString> filesSet = files.toSet();
stagedFiles = allStagedFiles.toSet().intersect(filesSet).toList();
unstagedFiles = allUnstagedFiles.toSet().intersect(filesSet).toList();
}
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << data.stagedFiles << data.unstagedFiles << allStagedFiles << allUnstagedFiles << stagedFiles << unstagedFiles;
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
if (stagedFiles.empty() && unstagedFiles.empty())
return RevertUnchanged;
// Ask to revert (to do: Handle lists with a selection dialog)
const QMessageBox::StandardButton answer
= QMessageBox::question(m_core->mainWindow(),
tr("Revert"),
tr("The file has been changed. Do you want to revert it?"),
QMessageBox::Yes|QMessageBox::No,
QMessageBox::No);
if (answer == QMessageBox::No)
return RevertCanceled;
// Unstage the staged files
if (!stagedFiles.empty() && !synchronousReset(repoDirectory, stagedFiles, errorMessage))
return RevertFailed;
// Finally revert!
if (!synchronousCheckout(repoDirectory, stagedFiles + unstagedFiles, errorMessage))
return RevertFailed;
return RevertOk;
}
void GitClient::revert(const QStringList &files)
{
bool isDirectory;
QString errorMessage;
switch (revertI(files, &isDirectory, &errorMessage)) {
case RevertOk:
m_plugin->gitVersionControl()->emitFilesChanged(files);
case RevertCanceled:
break;
case RevertUnchanged: {
const QString msg = (isDirectory || files.size() > 1) ? msgNoChangedFiles() : tr("The file is not modified.");
VCSBase::VCSBaseOutputWindow::instance()->append(msg);
}
break;
case RevertFailed:
VCSBase::VCSBaseOutputWindow::instance()->append(errorMessage);
break;
}
}
GitCommand *cmd = executeGit(workingDirectory, QStringList(QLatin1String("pull")), 0, true, GitCommand::ReportStderr);
connectRepositoryChanged(workingDirectory, cmd);
}
void GitClient::push(const QString &workingDirectory)
{
executeGit(workingDirectory, QStringList(QLatin1String("push")), 0, true, GitCommand::ReportStderr);
}
QString GitClient::msgNoChangedFiles()
{
return tr("There are no modified files.");
}
void GitClient::stash(const QString &workingDirectory)
{
// Check for changes and stash
QString errorMessage;
switch (gitStatus(workingDirectory, false, 0, &errorMessage)) {
case StatusChanged:
executeGit(workingDirectory, QStringList(QLatin1String("stash")), 0, true);
break;
case StatusUnchanged:
VCSBase::VCSBaseOutputWindow::instance()->append(msgNoChangedFiles());
break;
case StatusFailed:
VCSBase::VCSBaseOutputWindow::instance()->append(errorMessage);
break;
}
}
void GitClient::stashPop(const QString &workingDirectory)
{
QStringList arguments(QLatin1String("stash"));
arguments << QLatin1String("pop");
GitCommand *cmd = executeGit(workingDirectory, arguments, 0, true);
connectRepositoryChanged(workingDirectory, cmd);
}
void GitClient::branchList(const QString &workingDirectory)
{
QStringList arguments(QLatin1String("branch"));

Friedemann Kleint
committed
arguments << QLatin1String("-r") << QLatin1String(noColorOption);
executeGit(workingDirectory, arguments, 0, true);
}
void GitClient::stashList(const QString &workingDirectory)
{
QStringList arguments(QLatin1String("stash"));

Friedemann Kleint
committed
arguments << QLatin1String("list") << QLatin1String(noColorOption);
executeGit(workingDirectory, arguments, 0, true);
}
QString GitClient::readConfig(const QString &workingDirectory, const QStringList &configVar)
{
QStringList arguments;
arguments << QLatin1String("config") << configVar;
QByteArray outputText;
if (synchronousGit(workingDirectory, arguments, &outputText, 0, false))
return QString::fromLocal8Bit(outputText).remove(QLatin1Char('\r'));
return QString();
}
// Read a single-line config value, return trimmed
QString GitClient::readConfigValue(const QString &workingDirectory, const QString &configVar)
{
return readConfig(workingDirectory, QStringList(configVar)).remove(QLatin1Char('\n'));
}
GitSettings GitClient::settings() const
{
return m_settings;
}
void GitClient::setSettings(const GitSettings &s)
{
if (s != m_settings) {
m_settings = s;
if (QSettings *s = m_core->settings())
m_settings.toSettings(s);

Friedemann Kleint
committed
m_binaryPath = m_settings.gitBinaryPath();
}
}
void GitClient::connectRepositoryChanged(const QString & repository, GitCommand *cmd)
{
// Bind command success termination with repository to changed signal
if (!m_repositoryChangedSignalMapper) {
m_repositoryChangedSignalMapper = new QSignalMapper(this);
connect(m_repositoryChangedSignalMapper, SIGNAL(mapped(QString)),
m_plugin->gitVersionControl(), SIGNAL(repositoryChanged(QString)));
}
m_repositoryChangedSignalMapper->setMapping(cmd, repository);
connect(cmd, SIGNAL(success()), m_repositoryChangedSignalMapper, SLOT(map()),
Qt::QueuedConnection);
}