Git: Extract FileState from CommitData

* Add a QFlags type for it and use it
* Clean up GitClient::addAndCommit
* Rename Updated -> Unmerged

Change-Id: Id96f71fb78af923605f5773f65a5625244a49499
Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
Orgad Shaneh
2012-10-28 21:54:24 +02:00
committed by Orgad Shaneh
parent 0f2f2a59d2
commit ab85e7342e
5 changed files with 90 additions and 103 deletions

View File

@@ -88,25 +88,25 @@ void CommitData::clear()
files.clear(); files.clear();
} }
static CommitData::FileState stateFor(const QChar &c) static FileStates stateFor(const QChar &c)
{ {
switch (c.unicode()) { switch (c.unicode()) {
case ' ': case ' ':
return CommitData::UntrackedFile; return UntrackedFile;
case 'M': case 'M':
return CommitData::ModifiedFile; return ModifiedFile;
case 'A': case 'A':
return CommitData::AddedFile; return AddedFile;
case 'D': case 'D':
return CommitData::DeletedFile; return DeletedFile;
case 'R': case 'R':
return CommitData::RenamedFile; return RenamedFile;
case 'C': case 'C':
return CommitData::CopiedFile; return CopiedFile;
case 'U': case 'U':
return CommitData::UpdatedFile; return UnmergedFile;
default: default:
return CommitData::UnknownFileState; return UnknownFileState;
} }
} }
@@ -115,25 +115,25 @@ bool CommitData::checkLine(const QString &stateInfo, const QString &file)
QTC_ASSERT(stateInfo.count() == 2, return false); QTC_ASSERT(stateInfo.count() == 2, return false);
if (stateInfo == QLatin1String("??")) { if (stateInfo == QLatin1String("??")) {
files.append(qMakePair(UntrackedFile, file)); files.append(qMakePair(FileStates(UntrackedFile), file));
return true; return true;
} }
FileState stagedState = stateFor(stateInfo.at(0)); FileStates stagedState = stateFor(stateInfo.at(0));
if (stagedState == UnknownFileState) if (stagedState == UnknownFileState)
return false; return false;
stagedState = static_cast<FileState>(stagedState | StagedFile); stagedState |= StagedFile;
if (stagedState != StagedFile) if (stagedState != StagedFile)
files.append(qMakePair(stagedState, file)); files.append(qMakePair(stagedState, file));
FileState state = stateFor(stateInfo.at(1)); FileStates state = stateFor(stateInfo.at(1));
if (state == UnknownFileState) if (state == UnknownFileState)
return false; return false;
if (state != UntrackedFile) { if (state != UntrackedFile) {
QString newFile = file; QString newFile = file;
if (stagedState == RenamedStagedFile || stagedState == CopiedStagedFile) if (stagedState & (RenamedFile | CopiedFile))
newFile = file.mid(file.indexOf(QLatin1String(" -> ")) + 4); newFile = file.mid(file.indexOf(QLatin1String(" -> ")) + 4);
files.append(qMakePair(state, newFile)); files.append(qMakePair(state, newFile));
@@ -171,7 +171,7 @@ bool CommitData::parseFilesFromStatus(const QString &output)
return true; return true;
} }
QStringList CommitData::filterFiles(const CommitData::FileState &state) const QStringList CommitData::filterFiles(const FileStates &state) const
{ {
QStringList result; QStringList result;
foreach (const StateFilePair &p, files) { foreach (const StateFilePair &p, files) {
@@ -181,7 +181,7 @@ QStringList CommitData::filterFiles(const CommitData::FileState &state) const
return result; return result;
} }
QString CommitData::stateDisplayName(const FileState &state) QString CommitData::stateDisplayName(const FileStates &state)
{ {
QString resultState; QString resultState;
if (state == UntrackedFile) if (state == UntrackedFile)
@@ -199,8 +199,8 @@ QString CommitData::stateDisplayName(const FileState &state)
resultState.append(QCoreApplication::translate("Git::Internal::CommitData", "renamed")); resultState.append(QCoreApplication::translate("Git::Internal::CommitData", "renamed"));
else if (state & CopiedFile) else if (state & CopiedFile)
resultState.append(QCoreApplication::translate("Git::Internal::CommitData", "copied")); resultState.append(QCoreApplication::translate("Git::Internal::CommitData", "copied"));
else if (state & UpdatedFile) else if (state & UnmergedFile)
resultState.append(QCoreApplication::translate("Git::Internal::CommitData", "updated")); resultState.append(QCoreApplication::translate("Git::Internal::CommitData", "unmerged"));
return resultState; return resultState;
} }

View File

@@ -64,9 +64,6 @@ struct GitSubmitEditorPanelData
QDebug operator<<(QDebug d, const GitSubmitEditorPanelData &); QDebug operator<<(QDebug d, const GitSubmitEditorPanelData &);
class CommitData
{
public:
enum FileState { enum FileState {
UntrackedFile = 0, UntrackedFile = 0,
@@ -76,21 +73,17 @@ public:
DeletedFile = 0x08, DeletedFile = 0x08,
RenamedFile = 0x10, RenamedFile = 0x10,
CopiedFile = 0x20, CopiedFile = 0x20,
UpdatedFile = 0x40, UnmergedFile = 0x40,
ModifiedStagedFile = StagedFile | ModifiedFile, UnknownFileState = 0x800
AddedStagedFile = StagedFile | AddedFile,
DeletedStagedFile = StagedFile | DeletedFile,
RenamedStagedFile = StagedFile | RenamedFile,
CopiedStagedFile = StagedFile | CopiedFile,
UpdatedStagedFile = StagedFile | UpdatedFile,
AllStates = UpdatedFile | CopiedFile | RenamedFile | DeletedFile | AddedFile | ModifiedFile | StagedFile,
UnknownFileState
}; };
Q_DECLARE_FLAGS(FileStates, FileState)
class CommitData
{
public:
// A pair of state string/file name ('modified', 'file.cpp'). // A pair of state string/file name ('modified', 'file.cpp').
typedef QPair<FileState, QString> StateFilePair; typedef QPair<FileStates, QString> StateFilePair;
void clear(); void clear();
// Parse the files and the branch of panelInfo // Parse the files and the branch of panelInfo
@@ -99,9 +92,9 @@ public:
// Convenience to retrieve the file names from // Convenience to retrieve the file names from
// the specification list. Optionally filter for a certain state // the specification list. Optionally filter for a certain state
QStringList filterFiles(const FileState &state) const; QStringList filterFiles(const FileStates &state) const;
static QString stateDisplayName(const FileState &state); static QString stateDisplayName(const FileStates &state);
QString amendSHA1; QString amendSHA1;
QString commitEncoding; QString commitEncoding;
@@ -117,4 +110,6 @@ private:
} // namespace Internal } // namespace Internal
} // namespace Git } // namespace Git
Q_DECLARE_OPERATORS_FOR_FLAGS(Git::Internal::FileStates)
#endif // COMMITDATA_H #endif // COMMITDATA_H

View File

@@ -1750,13 +1750,13 @@ bool GitClient::getCommitData(const QString &workingDirectory,
} }
// Filter out untracked files that are not part of the project // Filter out untracked files that are not part of the project
QStringList untrackedFiles = commitData->filterFiles(CommitData::UntrackedFile); QStringList untrackedFiles = commitData->filterFiles(UntrackedFile);
VcsBase::VcsBaseSubmitEditor::filterUntrackedFilesOfProject(repoDirectory, &untrackedFiles); VcsBase::VcsBaseSubmitEditor::filterUntrackedFilesOfProject(repoDirectory, &untrackedFiles);
QList<CommitData::StateFilePair> filteredFiles; QList<CommitData::StateFilePair> filteredFiles;
QList<CommitData::StateFilePair>::const_iterator it = commitData->files.constBegin(); QList<CommitData::StateFilePair>::const_iterator it = commitData->files.constBegin();
for ( ; it != commitData->files.constEnd(); ++it) { for ( ; it != commitData->files.constEnd(); ++it) {
if (it->first == CommitData::UntrackedFile && !untrackedFiles.contains(it->second)) if (it->first == UntrackedFile && !untrackedFiles.contains(it->second))
continue; continue;
filteredFiles.append(*it); filteredFiles.append(*it);
} }
@@ -1836,47 +1836,41 @@ bool GitClient::addAndCommit(const QString &repositoryDirectory,
int commitCount = 0; int commitCount = 0;
for (int i = 0; i < model->rowCount(); ++i) { for (int i = 0; i < model->rowCount(); ++i) {
const CommitData::FileState state = static_cast<CommitData::FileState>(model->extraData(i).toInt()); const FileStates state = static_cast<FileStates>(model->extraData(i).toInt());
QString file = model->file(i); QString file = model->file(i);
const bool checked = model->checked(i); const bool checked = model->checked(i);
if (checked) if (checked)
++commitCount; ++commitCount;
if (state == CommitData::UntrackedFile && checked) if (state == UntrackedFile && checked)
filesToAdd.append(file); filesToAdd.append(file);
if (state == CommitData::ModifiedStagedFile && !checked) { if ((state & StagedFile) && !checked) {
if (state & (AddedFile | DeletedFile)) {
filesToReset.append(file); filesToReset.append(file);
} else if (state == CommitData::AddedStagedFile && !checked) { } else if (state & (RenamedFile | CopiedFile)) {
filesToReset.append(file);
} else if (state == CommitData::DeletedStagedFile && !checked) {
filesToReset.append(file);
} else if (state == CommitData::RenamedStagedFile && !checked) {
const int pos = file.indexOf(QLatin1String(" -> "));
const QString newFile = file.mid(pos + 4);
filesToReset.append(newFile);
} else if (state == CommitData::CopiedStagedFile && !checked) {
const QString newFile = file.mid(file.indexOf(renameSeparator) + renameSeparator.count()); const QString newFile = file.mid(file.indexOf(renameSeparator) + renameSeparator.count());
filesToReset.append(newFile); filesToReset.append(newFile);
} else if (state == CommitData::UpdatedStagedFile && !checked) { }
QTC_ASSERT(false, continue); // There should not be updated files when commiting! } else if (state & UnmergedFile && checked) {
QTC_ASSERT(false, continue); // There should not be unmerged files when commiting!
} }
if (state == CommitData::ModifiedFile && checked) { if (state == ModifiedFile && checked) {
filesToReset.removeAll(file); filesToReset.removeAll(file);
filesToAdd.append(file); filesToAdd.append(file);
} else if (state == CommitData::AddedFile && checked) { } else if (state == AddedFile && checked) {
QTC_ASSERT(false, continue); // these should be untracked! QTC_ASSERT(false, continue); // these should be untracked!
} else if (state == CommitData::DeletedFile && checked) { } else if (state == DeletedFile && checked) {
filesToReset.removeAll(file); filesToReset.removeAll(file);
filesToRemove.append(file); filesToRemove.append(file);
} else if (state == CommitData::RenamedFile && checked) { } else if (state == RenamedFile && checked) {
QTC_ASSERT(false, continue); // git mv directly stages. QTC_ASSERT(false, continue); // git mv directly stages.
} else if (state == CommitData::CopiedFile && checked) { } else if (state == CopiedFile && checked) {
QTC_ASSERT(false, continue); // only is noticed after adding a new file to the index QTC_ASSERT(false, continue); // only is noticed after adding a new file to the index
} else if (state == CommitData::UpdatedFile && checked) { } else if (state == UnmergedFile && checked) {
QTC_ASSERT(false, continue); // There should not be updated files when commiting! QTC_ASSERT(false, continue); // There should not be unmerged files when commiting!
} }
} }
@@ -1965,8 +1959,8 @@ GitClient::RevertResult GitClient::revertI(QStringList files,
} }
// From the status output, determine all modified [un]staged files. // From the status output, determine all modified [un]staged files.
const QStringList allStagedFiles = data.filterFiles(CommitData::ModifiedStagedFile); const QStringList allStagedFiles = data.filterFiles(StagedFile | ModifiedFile);
const QStringList allUnstagedFiles = data.filterFiles(CommitData::ModifiedFile); const QStringList allUnstagedFiles = data.filterFiles(ModifiedFile);
// Unless a directory was passed, filter all modified files for the // Unless a directory was passed, filter all modified files for the
// argument file list. // argument file list.
QStringList stagedFiles = allStagedFiles; QStringList stagedFiles = allStagedFiles;

View File

@@ -1069,44 +1069,42 @@ GitClient *GitPlugin::gitClient() const
#ifdef WITH_TESTS #ifdef WITH_TESTS
#include <QTest> #include <QTest>
Q_DECLARE_METATYPE(CommitData::FileState) Q_DECLARE_METATYPE(FileStates)
void GitPlugin::testStatusParsing_data() void GitPlugin::testStatusParsing_data()
{ {
QTest::addColumn<QString>("line"); QTest::addColumn<FileStates>("first");
QTest::addColumn<CommitData::FileState>("first"); QTest::addColumn<FileStates>("second");
QTest::addColumn<CommitData::FileState>("second");
#define STATUS_TEST(status, first, second) \ QTest::newRow(" M") << FileStates(ModifiedFile) << FileStates(UnknownFileState);
QTest::newRow(status) << QString::fromLatin1(status) << CommitData::first << CommitData::second; QTest::newRow(" D") << FileStates(DeletedFile) << FileStates(UnknownFileState);
STATUS_TEST(" M", ModifiedFile, UnknownFileState); QTest::newRow("M ") << (ModifiedFile | StagedFile) << FileStates(UnknownFileState);
STATUS_TEST(" D", DeletedFile, UnknownFileState); QTest::newRow("MM") << (ModifiedFile | StagedFile) << FileStates(ModifiedFile);
STATUS_TEST("M ", ModifiedStagedFile, UnknownFileState); QTest::newRow("MD") << (ModifiedFile | StagedFile) << FileStates(DeletedFile);
STATUS_TEST("MM", ModifiedStagedFile, ModifiedFile); QTest::newRow("A ") << (AddedFile | StagedFile) << FileStates(UnknownFileState);
STATUS_TEST("MD", ModifiedStagedFile, DeletedFile); QTest::newRow("AM") << (AddedFile | StagedFile) << FileStates(ModifiedFile);
STATUS_TEST("A ", AddedStagedFile, UnknownFileState); QTest::newRow("AD") << (AddedFile | StagedFile) << FileStates(DeletedFile);
STATUS_TEST("AM", AddedStagedFile, ModifiedFile); QTest::newRow("D ") << (DeletedFile | StagedFile) << FileStates(UnknownFileState);
STATUS_TEST("AD", AddedStagedFile, DeletedFile); QTest::newRow("DM") << (DeletedFile | StagedFile) << FileStates(ModifiedFile);
STATUS_TEST("D ", DeletedStagedFile, UnknownFileState); QTest::newRow("R ") << (RenamedFile | StagedFile) << FileStates(UnknownFileState);
STATUS_TEST("DM", DeletedStagedFile, ModifiedFile); QTest::newRow("RM") << (RenamedFile | StagedFile) << FileStates(ModifiedFile);
STATUS_TEST("R ", RenamedStagedFile, UnknownFileState); QTest::newRow("RD") << (RenamedFile | StagedFile) << FileStates(DeletedFile);
STATUS_TEST("RM", RenamedStagedFile, ModifiedFile); QTest::newRow("C ") << (CopiedFile | StagedFile) << FileStates(UnknownFileState);
STATUS_TEST("RD", RenamedStagedFile, DeletedFile); QTest::newRow("CM") << (CopiedFile | StagedFile) << FileStates(ModifiedFile);
STATUS_TEST("C ", CopiedStagedFile, UnknownFileState); QTest::newRow("CD") << (CopiedFile | StagedFile) << FileStates(DeletedFile);
STATUS_TEST("CM", CopiedStagedFile, ModifiedFile);
STATUS_TEST("CD", CopiedStagedFile, DeletedFile);
} }
void GitPlugin::testStatusParsing() void GitPlugin::testStatusParsing()
{ {
CommitData data; CommitData data;
QFETCH(QString, line); QFETCH(FileStates, first);
QFETCH(CommitData::FileState, first); QFETCH(FileStates, second);
QFETCH(CommitData::FileState, second);
QString output = QLatin1String("## master...origin/master [ahead 1]\n"); QString output = QLatin1String("## master...origin/master [ahead 1]\n");
output += line + QLatin1String(" main.cpp\n"); output += QString::fromLatin1(QTest::currentDataTag()) + QLatin1String(" main.cpp\n");
data.parseFilesFromStatus(output); data.parseFilesFromStatus(output);
QCOMPARE(data.files.at(0).first, first); QCOMPARE(data.files.at(0).first, first);
if (second != CommitData::UnknownFileState) if (second == UnknownFileState)
QCOMPARE(data.files.size(), 1);
else
QCOMPARE(data.files.at(1).first, second); QCOMPARE(data.files.at(1).first, second);
} }
#endif #endif

View File

@@ -70,9 +70,9 @@ void GitSubmitEditor::setCommitData(const CommitData &d)
if (!d.files.isEmpty()) { if (!d.files.isEmpty()) {
for (QList<CommitData::StateFilePair>::const_iterator it = d.files.constBegin(); for (QList<CommitData::StateFilePair>::const_iterator it = d.files.constBegin();
it != d.files.constEnd(); ++it) { it != d.files.constEnd(); ++it) {
const CommitData::FileState state = it->first; const FileStates state = it->first;
const QString file = it->second; const QString file = it->second;
m_model->addFile(file, CommitData::stateDisplayName(state), state & CommitData::StagedFile, m_model->addFile(file, CommitData::stateDisplayName(state), state & StagedFile,
QVariant(static_cast<int>(state))); QVariant(static_cast<int>(state)));
} }
} }
@@ -89,10 +89,10 @@ void GitSubmitEditor::slotDiffSelected(const QStringList &files)
for (int r = 0; r < rowCount; r++) { for (int r = 0; r < rowCount; r++) {
const QString fileName = m_model->item(r, fileColumn)->text(); const QString fileName = m_model->item(r, fileColumn)->text();
if (files.contains(fileName)) { if (files.contains(fileName)) {
const CommitData::FileState state = static_cast<CommitData::FileState>(m_model->extraData(r).toInt()); const FileStates state = static_cast<FileStates>(m_model->extraData(r).toInt());
if (state & CommitData::StagedFile) if (state & StagedFile)
stagedFiles.push_back(fileName); stagedFiles.push_back(fileName);
else if (state != CommitData::UntrackedFile) else if (state != UntrackedFile)
unstagedFiles.push_back(fileName); unstagedFiles.push_back(fileName);
} }
} }