Commit d7d0774f authored by Waqar Ahmed's avatar Waqar Ahmed Committed by Christoph Cullmann
Browse files

Separate num stat for staged / modified

parent 3a394f9d
......@@ -16,7 +16,7 @@ GitUtils::GitParsedStatus GitUtils::parseStatus(const QByteArray &raw)
QVector<GitUtils::StatusItem> staged;
QVector<GitUtils::StatusItem> changed;
QList<QByteArray> rawList = raw.split(0x00);
const QList<QByteArray> rawList = raw.split(0x00);
for (const auto &r : rawList) {
if (r.isEmpty() || r.length() < 3) {
continue;
......@@ -27,67 +27,64 @@ GitUtils::GitParsedStatus GitUtils::parseStatus(const QByteArray &raw)
uint16_t xy = (((uint16_t)x) << 8) | y;
using namespace GitUtils;
const char *file = r.data() + 3;
const int size = r.size() - 3;
switch (xy) {
case StatusXY::QQ:
untracked.append({QString::fromUtf8(file, size), GitStatus::Untracked, 'U', 0, 0});
untracked.append({r.mid(3), GitStatus::Untracked, 'U', 0, 0});
break;
case StatusXY::II:
untracked.append({QString::fromUtf8(file, size), GitStatus::Ignored, 'I', 0, 0});
untracked.append({r.mid(3), GitStatus::Ignored, 'I', 0, 0});
break;
case StatusXY::DD:
unmerge.append({QString::fromUtf8(file, size), GitStatus::Unmerge_BothDeleted, x, 0, 0});
unmerge.append({r.mid(3), GitStatus::Unmerge_BothDeleted, x, 0, 0});
break;
case StatusXY::AU:
unmerge.append({QString::fromUtf8(file, size), GitStatus::Unmerge_AddedByUs, x, 0, 0});
unmerge.append({r.mid(3), GitStatus::Unmerge_AddedByUs, x, 0, 0});
break;
case StatusXY::UD:
unmerge.append({QString::fromUtf8(file, size), GitStatus::Unmerge_DeletedByThem, x, 0, 0});
unmerge.append({r.mid(3), GitStatus::Unmerge_DeletedByThem, x, 0, 0});
break;
case StatusXY::UA:
unmerge.append({QString::fromUtf8(file, size), GitStatus::Unmerge_AddedByThem, x, 0, 0});
unmerge.append({r.mid(3), GitStatus::Unmerge_AddedByThem, x, 0, 0});
break;
case StatusXY::DU:
unmerge.append({QString::fromUtf8(file, size), GitStatus::Unmerge_DeletedByUs, x, 0, 0});
unmerge.append({r.mid(3), GitStatus::Unmerge_DeletedByUs, x, 0, 0});
break;
case StatusXY::AA:
unmerge.append({QString::fromUtf8(file, size), GitStatus::Unmerge_BothAdded, x, 0, 0});
unmerge.append({r.mid(3), GitStatus::Unmerge_BothAdded, x, 0, 0});
break;
case StatusXY::UU:
unmerge.append({QString::fromUtf8(file, size), GitStatus::Unmerge_BothModified, x, 0, 0});
unmerge.append({r.mid(3), GitStatus::Unmerge_BothModified, x, 0, 0});
break;
}
switch (x) {
case 'M':
staged.append({QString::fromUtf8(file, size), GitStatus::Index_Modified, x, 0, 0});
staged.append({r.mid(3), GitStatus::Index_Modified, x, 0, 0});
break;
case 'A':
staged.append({QString::fromUtf8(file, size), GitStatus::Index_Added, x, 0, 0});
staged.append({r.mid(3), GitStatus::Index_Added, x, 0, 0});
break;
case 'D':
staged.append({QString::fromUtf8(file, size), GitStatus::Index_Deleted, x, 0, 0});
staged.append({r.mid(3), GitStatus::Index_Deleted, x, 0, 0});
break;
case 'R':
staged.append({QString::fromUtf8(file, size), GitStatus::Index_Renamed, x, 0, 0});
staged.append({r.mid(3), GitStatus::Index_Renamed, x, 0, 0});
break;
case 'C':
staged.append({QString::fromUtf8(file, size), GitStatus::Index_Copied, x, 0, 0});
staged.append({r.mid(3), GitStatus::Index_Copied, x, 0, 0});
break;
}
switch (y) {
case 'M':
changed.append({QString::fromUtf8(file, size), GitStatus::WorkingTree_Modified, y, 0, 0});
changed.append({r.mid(3), GitStatus::WorkingTree_Modified, y, 0, 0});
break;
case 'D':
changed.append({QString::fromUtf8(file, size), GitStatus::WorkingTree_Deleted, y, 0, 0});
changed.append({r.mid(3), GitStatus::WorkingTree_Deleted, y, 0, 0});
break;
case 'A':
changed.append({QString::fromUtf8(file, size), GitStatus::WorkingTree_IntentToAdd, y, 0, 0});
changed.append({r.mid(3), GitStatus::WorkingTree_IntentToAdd, y, 0, 0});
break;
}
}
......@@ -134,11 +131,25 @@ static bool getNum(const QByteArray &numBytes, int *num)
return res;
}
GitUtils::GitParsedStatus GitUtils::parseDiffNumStat(GitUtils::GitParsedStatus s, const QByteArray &raw)
static void addNumStat(QVector<GitUtils::StatusItem> &items, int add, int sub, const QByteArray &file)
{
auto list = raw.split(0x00);
for (const auto &l : list) {
auto cols = l.split('\t');
// look in modified first, then staged
auto item = std::find_if(items.begin(), items.end(), [&file](const GitUtils::StatusItem &si) {
return si.file == file;
});
if (item != items.end()) {
item->linesAdded = add;
item->linesRemoved = sub;
return;
}
}
void GitUtils::parseDiffNumStat(QVector<GitUtils::StatusItem> &items, const QByteArray &raw)
{
const auto lines = raw.split(0x00);
for (const auto &line : lines) {
// format: 12(adds)\t10(subs)\tFileName
const auto cols = line.split('\t');
if (cols.length() < 3) {
continue;
}
......@@ -152,31 +163,7 @@ GitUtils::GitParsedStatus GitUtils::parseDiffNumStat(GitUtils::GitParsedStatus s
continue;
}
auto file = cols.at(2);
s.addNumStat(add, sub, QString::fromUtf8(file));
// we are only concerned with staged + modified
}
return s;
}
void GitUtils::GitParsedStatus::addNumStat(int add, int sub, const QString &file)
{
// look in modified first, then staged
auto i = std::find_if(changed.begin(), changed.end(), [&file](const StatusItem &si) {
return si.file == file;
});
if (i != changed.end()) {
i->add = add;
i->sub = sub;
return;
}
i = std::find_if(staged.begin(), staged.end(), [&file](const StatusItem &si) {
return si.file == file;
});
if (i != staged.end()) {
i->add = add;
i->sub = sub;
return;
const auto file = cols.at(2);
addNumStat(items, add, sub, file);
}
}
......@@ -50,11 +50,11 @@ enum StatusXY {
};
struct StatusItem {
QString file;
QByteArray file;
GitStatus status;
char statusChar;
int add;
int sub;
int linesAdded;
int linesRemoved;
};
struct GitParsedStatus {
......@@ -62,13 +62,11 @@ struct GitParsedStatus {
QVector<StatusItem> unmerge;
QVector<StatusItem> staged;
QVector<StatusItem> changed;
void addNumStat(int add, int sub, const QString &file);
};
GitParsedStatus parseStatus(const QByteArray &raw);
GitParsedStatus parseDiffNumStat(GitParsedStatus s, const QByteArray &raw);
void parseDiffNumStat(QVector<GitUtils::StatusItem> &items, const QByteArray &raw);
QString statusString(GitStatus s);
}
......
......@@ -114,7 +114,7 @@ QVariant GitStatusModel::data(const QModelIndex &index, int role) const
if (role == Qt::DisplayRole) {
if (index.column() == 0) {
const auto filename = QFileInfo(m_nodes[rootIndex].at(row).file).fileName();
const auto filename = QFileInfo(QString::fromUtf8(m_nodes[rootIndex].at(row).file)).fileName();
if (filename.isEmpty()) {
return m_nodes[rootIndex].at(row).file;
}
......@@ -123,10 +123,10 @@ QVariant GitStatusModel::data(const QModelIndex &index, int role) const
if (!m_showNumStat) {
return QString(QLatin1Char(m_nodes[rootIndex].at(row).statusChar));
}
int a = m_nodes[rootIndex].at(row).add;
int s = m_nodes[rootIndex].at(row).sub;
int a = m_nodes[rootIndex].at(row).linesAdded;
int r = m_nodes[rootIndex].at(row).linesRemoved;
auto add = QString::number(a);
auto sub = QString::number(s);
auto sub = QString::number(r);
add.append(QStringLiteral("+ ") + sub + QStringLiteral("- "));
add.append(QString(QLatin1Char(m_nodes[rootIndex].at(row).statusChar)));
return add;
......@@ -134,12 +134,14 @@ QVariant GitStatusModel::data(const QModelIndex &index, int role) const
} else if (role == FileNameRole) {
return m_nodes[rootIndex].at(row).file;
} else if (role == Qt::DecorationRole) {
if (index.column() == 0)
return QIcon::fromTheme(QMimeDatabase().mimeTypeForFile(m_nodes[rootIndex].at(row).file, QMimeDatabase::MatchExtension).iconName());
if (index.column() == 0) {
const QString file = QString::fromUtf8(m_nodes[rootIndex].at(row).file);
return QIcon::fromTheme(QMimeDatabase().mimeTypeForFile(file, QMimeDatabase::MatchExtension).iconName());
}
} else if (role == Role::TreeItemType) {
return ItemType::NodeFile;
} else if (role == Qt::ToolTipRole) {
return QString(m_nodes[rootIndex].at(row).file + GitUtils::statusString(m_nodes[rootIndex].at(row).status));
return QString(QString::fromUtf8(m_nodes[rootIndex].at(row).file) + GitUtils::statusString(m_nodes[rootIndex].at(row).status));
} else if (role == Qt::TextAlignmentRole) {
if (index.column() == 0) {
return Qt::AlignLeft;
......
......@@ -558,35 +558,31 @@ void GitWidget::parseStatusReady()
GitUtils::GitParsedStatus s = m_gitStatusWatcher.result();
if (m_pluginView->plugin()->showGitStatusWithNumStat()) {
numStatForStatus(std::move(s));
return;
numStatForStatus(s.changed, true);
numStatForStatus(s.staged, false);
}
m_model->addItems(std::move(s), false);
m_model->addItems(std::move(s), m_pluginView->plugin()->showGitStatusWithNumStat());
hideEmptyTreeNodes();
}
void GitWidget::numStatForStatus(GitUtils::GitParsedStatus status)
void GitWidget::numStatForStatus(QVector<GitUtils::StatusItem> &list, bool modified)
{
disconnect(&git, &QProcess::finished, nullptr, nullptr);
const auto args = QStringList{QStringLiteral("diff"), QStringLiteral("HEAD"), QStringLiteral("--numstat"), QStringLiteral("-z")};
connect(&git, &QProcess::finished, this, [this, status{std::move(status)}](int exitCode, QProcess::ExitStatus es) mutable {
disconnect(&git, &QProcess::finished, nullptr, nullptr);
if (es != QProcess::NormalExit || exitCode != 0) {
sendMessage(i18n("Failed to get diff --numstat: %1", QString::fromUtf8(git.readAllStandardError())), true);
// just use the simple status data in model
m_model->addItems(std::move(status), false);
} else {
status = GitUtils::parseDiffNumStat(std::move(status), git.readAllStandardOutput());
m_model->addItems(status, true);
}
hideEmptyTreeNodes();
});
const auto args = modified ? QStringList{QStringLiteral("diff"), QStringLiteral("--numstat"), QStringLiteral("-z")}
: QStringList{QStringLiteral("diff"), QStringLiteral("--numstat"), QStringLiteral("--staged"), QStringLiteral("-z")};
git.setArguments(args);
git.start();
if (git.waitForStarted() && git.waitForFinished(-1)) {
if (git.exitStatus() != QProcess::NormalExit || git.exitCode() != 0) {
return;
}
}
GitUtils::parseDiffNumStat(list, git.readAllStandardOutput());
}
bool GitWidget::eventFilter(QObject *o, QEvent *e)
......@@ -741,8 +737,8 @@ void GitWidget::treeViewContextMenuEvent(QContextMenuEvent *e)
const QVector<GitUtils::StatusItem> &files = untracked ? m_model->untrackedFiles() : m_model->changedFiles();
QStringList filesList;
filesList.reserve(files.size());
for (const auto &file : files) {
filesList.append(file.file);
for (const GitUtils::StatusItem &item : files) {
filesList.append(QString::fromUtf8(item.file));
}
// execute action
......@@ -819,11 +815,11 @@ void GitWidget::treeViewContextMenuEvent(QContextMenuEvent *e)
// git reset -q HEAD --
if (act == stage) {
const QVector<GitUtils::StatusItem> &files = m_model->stagedFiles();
const QVector<GitUtils::StatusItem> &items = m_model->stagedFiles();
QStringList filesList;
filesList.reserve(filesList.size() + files.size());
for (const auto &file : files) {
filesList.append(file.file);
filesList.reserve(filesList.size() + items.size());
for (const GitUtils::StatusItem &item : items) {
filesList.append(QString::fromUtf8(item.file));
}
unstage(filesList);
} else if (act == diff) {
......
......@@ -80,7 +80,7 @@ private:
void launchExternalDiffTool(const QString &file, bool staged);
void commitChanges(const QString &msg, const QString &desc, bool signOff);
void applyDiff(const QString &fileName, bool staged, bool hunk, KTextEditor::View *v);
void numStatForStatus(GitUtils::GitParsedStatus status);
void numStatForStatus(QVector<GitUtils::StatusItem> &list, bool modified);
QMenu *stashMenu();
void hideEmptyTreeNodes();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment