forked from qt-creator/qt-creator
Fixes: Ability to uncheck files in git.
This commit is contained in:
@@ -22,10 +22,9 @@
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPlainTextEdit" name="description">
|
||||
</widget>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="description"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@@ -38,8 +37,8 @@
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QListWidget" name="fileList">
|
||||
<property name="font">
|
||||
<font/>
|
||||
|
@@ -59,6 +59,8 @@ const char* const kGitCommand = "git";
|
||||
const char* const kGitDirectoryC = ".git";
|
||||
const char* const kBranchIndicatorC = "# On branch";
|
||||
|
||||
enum { untrackedFilesInCommit = 0 };
|
||||
|
||||
static inline QString msgServerFailure()
|
||||
{
|
||||
return GitClient::tr(
|
||||
@@ -197,7 +199,9 @@ void GitClient::diff(const QString &workingDirectory, const QString &fileName)
|
||||
|
||||
void GitClient::status(const QString &workingDirectory)
|
||||
{
|
||||
executeGit(workingDirectory, QStringList(QLatin1String("status")), m_plugin->m_outputWindow, 0,true);
|
||||
QStringList statusArgs(QLatin1String("status"));
|
||||
statusArgs << QLatin1String("-u");
|
||||
executeGit(workingDirectory, statusArgs, m_plugin->m_outputWindow, 0,true);
|
||||
}
|
||||
|
||||
void GitClient::log(const QString &workingDirectory, const QString &fileName)
|
||||
@@ -286,10 +290,12 @@ void GitClient::addFile(const QString &workingDirectory, const QString &fileName
|
||||
|
||||
bool GitClient::synchronousAdd(const QString &workingDirectory, const QStringList &files)
|
||||
{
|
||||
if (Git::Constants::debug)
|
||||
qDebug() << Q_FUNC_INFO << workingDirectory << files;
|
||||
QByteArray outputText;
|
||||
QByteArray errorText;
|
||||
QStringList arguments;
|
||||
arguments << "add" << files;
|
||||
arguments << QLatin1String("add") << 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()).
|
||||
@@ -300,6 +306,30 @@ bool GitClient::synchronousAdd(const QString &workingDirectory, const QStringLis
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool GitClient::synchronousReset(const QString &workingDirectory,
|
||||
const QStringList &files)
|
||||
{
|
||||
if (Git::Constants::debug)
|
||||
qDebug() << Q_FUNC_INFO << workingDirectory << files;
|
||||
QByteArray outputText;
|
||||
QByteArray errorText;
|
||||
QStringList arguments;
|
||||
arguments << QLatin1String("reset") << QLatin1String("HEAD") << files;
|
||||
const bool rc = synchronousGit(workingDirectory, arguments, &outputText, &errorText);
|
||||
const QString output = QString::fromLocal8Bit(outputText);
|
||||
m_plugin->m_outputWindow->popup(false);
|
||||
m_plugin->m_outputWindow->append(output);
|
||||
// Note that git exits with 1 even if the operation is successful
|
||||
// Assume real failure if the output does not contain "foo.cpp modified"
|
||||
if (!rc && !output.contains(QLatin1String("modified"))) {
|
||||
const QString errorMessage = tr("Unable to reset %n file(s) in %1: %2", 0, files.size()).
|
||||
arg(workingDirectory, QString::fromLocal8Bit(errorText));
|
||||
m_plugin->m_outputWindow->append(errorMessage);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GitClient::executeGit(const QString &workingDirectory, const QStringList &arguments,
|
||||
GitOutputWindow *outputWindow, VCSBase::VCSBaseEditor* editor,
|
||||
bool outputToWindow)
|
||||
@@ -365,6 +395,22 @@ bool GitClient::synchronousGit(const QString &workingDirectory
|
||||
return process.exitCode() == 0;
|
||||
}
|
||||
|
||||
|
||||
// Trim a git status file spec: "modified: foo .cpp" -> "modified: foo .cpp"
|
||||
static inline QString trimFileSpecification(QString fileSpec)
|
||||
{
|
||||
const int colonIndex = fileSpec.indexOf(QLatin1Char(':'));
|
||||
if (colonIndex != -1) {
|
||||
// Collapse the sequence of spaces
|
||||
const int filePos = colonIndex + 2;
|
||||
int nonBlankPos = filePos;
|
||||
for ( ; fileSpec.at(nonBlankPos).isSpace(); nonBlankPos++);
|
||||
if (nonBlankPos > filePos)
|
||||
fileSpec.remove(filePos, nonBlankPos - filePos);
|
||||
}
|
||||
return fileSpec;
|
||||
}
|
||||
|
||||
/* Parse a git status file list:
|
||||
* \code
|
||||
# Changes to be committed:
|
||||
@@ -385,8 +431,8 @@ static bool parseFiles(const QStringList &lines, CommitData *d)
|
||||
const QString untrackedIndicator = QLatin1String("# Untracked files:");
|
||||
|
||||
State s = None;
|
||||
|
||||
const QRegExp filesPattern(QLatin1String("#\\t[^:]+:\\s+[^ ]+"));
|
||||
// Match added/changed-not-updated files: "#<tab>modified: foo.cpp"
|
||||
QRegExp filesPattern(QLatin1String("#\\t[^:]+:\\s+.+"));
|
||||
Q_ASSERT(filesPattern.isValid());
|
||||
|
||||
const QStringList::const_iterator cend = lines.constEnd();
|
||||
@@ -402,19 +448,22 @@ static bool parseFiles(const QStringList &lines, CommitData *d)
|
||||
s = NotUpdatedFiles;
|
||||
} else {
|
||||
if (line.startsWith(untrackedIndicator)) {
|
||||
// Now match untracked: "#<tab>foo.cpp"
|
||||
s = UntrackedFiles;
|
||||
filesPattern = QRegExp(QLatin1String("#\\t.+"));
|
||||
Q_ASSERT(filesPattern.isValid());
|
||||
} else {
|
||||
if (filesPattern.exactMatch(line)) {
|
||||
const QString fileSpec = line.mid(2).simplified();
|
||||
const QString fileSpec = line.mid(2).trimmed();
|
||||
switch (s) {
|
||||
case CommitFiles:
|
||||
d->commitFiles.push_back(fileSpec);
|
||||
d->commitFiles.push_back(trimFileSpecification(fileSpec));
|
||||
break;
|
||||
case NotUpdatedFiles:
|
||||
d->notUpdatedFiles.push_back(fileSpec);
|
||||
d->notUpdatedFiles.push_back(trimFileSpecification(fileSpec));
|
||||
break;
|
||||
case UntrackedFiles:
|
||||
d->untrackedFiles.push_back(fileSpec);
|
||||
d->untrackedFiles.push_back(QLatin1String("untracked: ") + fileSpec);
|
||||
break;
|
||||
case None:
|
||||
break;
|
||||
@@ -461,7 +510,10 @@ bool GitClient::getCommitData(const QString &workingDirectory,
|
||||
// Run status. Note that it has exitcode 1 if there are no added files.
|
||||
QByteArray outputText;
|
||||
QByteArray errorText;
|
||||
const bool statusRc = synchronousGit(workingDirectory, QStringList(QLatin1String("status")), &outputText, &errorText);
|
||||
QStringList statusArgs(QLatin1String("status"));
|
||||
if (untrackedFilesInCommit)
|
||||
statusArgs << QLatin1String("-u");
|
||||
const bool statusRc = synchronousGit(workingDirectory, statusArgs, &outputText, &errorText);
|
||||
if (!statusRc) {
|
||||
// Something fatal
|
||||
if (!outputText.contains(kBranchIndicatorC)) {
|
||||
@@ -517,13 +569,25 @@ bool GitClient::getCommitData(const QString &workingDirectory,
|
||||
return true;
|
||||
}
|
||||
|
||||
// addAndCommit:
|
||||
bool GitClient::addAndCommit(const QString &workingDirectory,
|
||||
const GitSubmitEditorPanelData &data,
|
||||
const QString &messageFile,
|
||||
const QStringList &files)
|
||||
const QStringList &checkedFiles,
|
||||
const QStringList &origCommitFiles)
|
||||
{
|
||||
if (Git::Constants::debug)
|
||||
qDebug() << "GitClient::addAndCommit:" << workingDirectory << checkedFiles << origCommitFiles;
|
||||
|
||||
// Do we need to reset any files that had been added before
|
||||
// (did the user uncheck any previously added files)
|
||||
const QSet<QString> resetFiles = origCommitFiles.toSet().subtract(checkedFiles.toSet());
|
||||
if (!resetFiles.empty())
|
||||
if (!synchronousReset(workingDirectory, resetFiles.toList()))
|
||||
return false;
|
||||
|
||||
// Re-add all to make sure we have the latest changes
|
||||
if (!synchronousAdd(workingDirectory, files))
|
||||
if (!synchronousAdd(workingDirectory, checkedFiles))
|
||||
return false;
|
||||
|
||||
// Do the final commit
|
||||
@@ -536,8 +600,8 @@ bool GitClient::addAndCommit(const QString &workingDirectory,
|
||||
QByteArray errorText;
|
||||
const bool rc = synchronousGit(workingDirectory, args, &outputText, &errorText);
|
||||
const QString message = rc ?
|
||||
tr("Committed %n file(s).", 0, files.size()) :
|
||||
tr("Unable to commit %n file(s): %1", 0, files.size()).arg(QString::fromLocal8Bit(errorText));
|
||||
tr("Committed %n file(s).", 0, checkedFiles.size()) :
|
||||
tr("Unable to commit %n file(s): %1", 0, checkedFiles.size()).arg(QString::fromLocal8Bit(errorText));
|
||||
|
||||
m_plugin->m_outputWindow->append(message);
|
||||
m_plugin->m_outputWindow->popup(false);
|
||||
|
@@ -90,6 +90,7 @@ public:
|
||||
void hardReset(const QString &workingDirectory, const QString &commit);
|
||||
void addFile(const QString &workingDirectory, const QString &fileName);
|
||||
bool synchronousAdd(const QString &workingDirectory, const QStringList &files);
|
||||
bool synchronousReset(const QString &workingDirectory, const QStringList &files);
|
||||
void pull(const QString &workingDirectory);
|
||||
void push(const QString &workingDirectory);
|
||||
|
||||
@@ -105,7 +106,8 @@ public:
|
||||
bool addAndCommit(const QString &workingDirectory,
|
||||
const GitSubmitEditorPanelData &data,
|
||||
const QString &messageFile,
|
||||
const QStringList &files);
|
||||
const QStringList &checkedFiles,
|
||||
const QStringList &origCommitFiles);
|
||||
|
||||
public slots:
|
||||
void show(const QString &source, const QString &id);
|
||||
|
@@ -524,7 +524,10 @@ void GitPlugin::startCommit()
|
||||
return;
|
||||
}
|
||||
|
||||
// Store repository for diff and the original list of
|
||||
// files to be able to unstage files the user unchecks
|
||||
m_submitRepository = data.panelInfo.repository;
|
||||
m_submitOrigCommitFiles = GitSubmitEditor::statusListToFileList(data.commitFiles);
|
||||
|
||||
if (Git::Constants::debug)
|
||||
qDebug() << Q_FUNC_INFO << data << commitTemplate;
|
||||
@@ -614,7 +617,8 @@ bool GitPlugin::editorAboutToClose(Core::IEditor *iEditor)
|
||||
m_gitClient->addAndCommit(m_submitRepository,
|
||||
editor->panelData(),
|
||||
m_changeTmpFile->fileName(),
|
||||
fileList);
|
||||
fileList,
|
||||
m_submitOrigCommitFiles);
|
||||
}
|
||||
cleanChangeTmpFile();
|
||||
return true;
|
||||
|
@@ -44,7 +44,7 @@
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QFile;
|
||||
@@ -155,6 +155,7 @@ private:
|
||||
CoreListener *m_coreListener;
|
||||
Core::IEditorFactory *m_submitEditorFactory;
|
||||
QString m_submitRepository;
|
||||
QStringList m_submitOrigCommitFiles;
|
||||
QTemporaryFile *m_changeTmpFile;
|
||||
};
|
||||
|
||||
|
@@ -52,11 +52,13 @@ GitSubmitEditorWidget *GitSubmitEditor::submitEditorWidget()
|
||||
return static_cast<GitSubmitEditorWidget *>(widget());
|
||||
}
|
||||
|
||||
QStringList GitSubmitEditor::vcsFileListToFileList(const QStringList &rawList) const
|
||||
QStringList GitSubmitEditor::statusListToFileList(const QStringList &rawList)
|
||||
{
|
||||
if (rawList.empty())
|
||||
return rawList;
|
||||
QStringList rc;
|
||||
foreach (const QString &rf, rawList)
|
||||
rc.push_back(fileFromChangeLine(rf));
|
||||
rc.push_back(fileFromStatusLine(rf));
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -65,9 +67,8 @@ void GitSubmitEditor::setCommitData(const CommitData &d)
|
||||
submitEditorWidget()->setPanelData(d.panelData);
|
||||
submitEditorWidget()->setPanelInfo(d.panelInfo);
|
||||
|
||||
// Commited: Checked, user cannot uncheck
|
||||
addFiles(d.commitFiles, true, false);
|
||||
// Not Updated: User can check
|
||||
addFiles(d.commitFiles, true, true);
|
||||
// Not Updated: Initially unchecked
|
||||
addFiles(d.notUpdatedFiles, false, true);
|
||||
addFiles(d.untrackedFiles, false, true);
|
||||
}
|
||||
@@ -77,7 +78,7 @@ GitSubmitEditorPanelData GitSubmitEditor::panelData() const
|
||||
return const_cast<GitSubmitEditor*>(this)->submitEditorWidget()->panelData();
|
||||
}
|
||||
|
||||
QString GitSubmitEditor::fileFromChangeLine(const QString &line)
|
||||
QString GitSubmitEditor::fileFromStatusLine(const QString &line)
|
||||
{
|
||||
QString rc = line;
|
||||
// "modified: mainwindow.cpp"
|
||||
|
@@ -36,6 +36,8 @@
|
||||
|
||||
#include <vcsbase/vcsbasesubmiteditor.h>
|
||||
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
namespace Git {
|
||||
namespace Internal {
|
||||
|
||||
@@ -43,7 +45,6 @@ class GitSubmitEditorWidget;
|
||||
struct CommitData;
|
||||
struct GitSubmitEditorPanelData;
|
||||
|
||||
/* */
|
||||
class GitSubmitEditor : public VCSBase::VCSBaseSubmitEditor
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -53,10 +54,12 @@ public:
|
||||
void setCommitData(const CommitData &);
|
||||
GitSubmitEditorPanelData panelData() const;
|
||||
|
||||
static QString fileFromChangeLine(const QString &line);
|
||||
static QString fileFromStatusLine(const QString &line);
|
||||
static QStringList statusListToFileList(const QStringList &);
|
||||
|
||||
protected:
|
||||
virtual QStringList vcsFileListToFileList(const QStringList &) const;
|
||||
virtual QStringList vcsFileListToFileList(const QStringList &l) const
|
||||
{ return statusListToFileList(l); }
|
||||
|
||||
private:
|
||||
inline GitSubmitEditorWidget *submitEditorWidget();
|
||||
|
Reference in New Issue
Block a user