1#include "CommitInfo.h"
2
3#include <QStringList>
4
5const QString CommitInfo::ZERO_SHA = QString("0000000000000000000000000000000000000000");
6const QString CommitInfo::INIT_SHA = QString("4b825dc642cb6eb9a060e54bf8d69288fbee4904");
7
8CommitInfo::CommitInfo(QByteArray commitData, const QString &gpg, bool goodSignature)
9 : gpgKey(gpg)
10 , mGoodSignature(goodSignature)
11{
12 parseDiff(commitData, 0);
13}
14
15CommitInfo::CommitInfo(QByteArray data)
16{
17 parseDiff(data, 1);
18}
19
20void CommitInfo::parseDiff(QByteArray &data, int startingField)
21{
22 if (const auto fields = QString::fromUtf8(data).split('\n'); fields.count() > 0)
23 {
24 const auto firstField = fields.constFirst();
25 auto combinedShas = fields.at(startingField++);
26 auto shas = combinedShas.split('X');
27 sha = shas.takeFirst().remove(0, 1);
28
29 if (!shas.isEmpty())
30 {
31 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
32 mParentsSha = shas.takeFirst().split(' ', Qt::SkipEmptyParts);
33 #else
34 mParentsSha = shas.takeFirst().split(' ', QString::SkipEmptyParts);
35 #endif
36 }
37 committer = fields.at(startingField++);
38 author = fields.at(startingField++);
39 dateSinceEpoch = std::chrono::seconds(fields.at(startingField++).toInt());
40 shortLog = fields.at(startingField);
41
42 for (auto i = 6; i < fields.count(); ++i)
43 longLog += fields.at(i) + '\n';
44
45 longLog = longLog.trimmed();
46 }
47}
48
49CommitInfo::CommitInfo(const QString &sha, const QStringList &parents, std::chrono::seconds commitDate,
50 const QString &log)
51 : sha(sha)
52 , dateSinceEpoch(commitDate)
53 , shortLog(log)
54 , mParentsSha(parents)
55{
56}
57
58bool CommitInfo::operator==(const CommitInfo &commit) const
59{
60 return sha.startsWith(commit.sha) && mParentsSha == commit.mParentsSha && committer == commit.committer
61 && author == commit.author && dateSinceEpoch == commit.dateSinceEpoch && shortLog == commit.shortLog
62 && longLog == commit.longLog && mLanes == commit.mLanes;
63}
64
65bool CommitInfo::operator!=(const CommitInfo &commit) const
66{
67 return !(*this == commit);
68}
69
70bool CommitInfo::contains(const QString &value)
71{
72 return sha.startsWith(value, Qt::CaseInsensitive) || shortLog.contains(value, Qt::CaseInsensitive)
73 || committer.contains(value, Qt::CaseInsensitive) || author.contains(value, Qt::CaseInsensitive);
74}
75
76int CommitInfo::parentsCount() const
77{
78 auto count = mParentsSha.count();
79
80 if (count > 0 && mParentsSha.contains(CommitInfo::INIT_SHA))
81 --count;
82
83 return count;
84}
85
86QString CommitInfo::firstParent() const
87{
88 return !mParentsSha.isEmpty() ? mParentsSha.at(0) : QString();
89}
90
91QStringList CommitInfo::parents() const
92{
93 return mParentsSha;
94}
95
96bool CommitInfo::isInWorkingBranch() const
97{
98 for (const auto &child : mChilds)
99 {
100 if (child->sha == CommitInfo::ZERO_SHA)
101 {
102 return true;
103 break;
104 }
105 }
106
107 return false;
108}
109
110void CommitInfo::setLanes(QVector<Lane> lanes)
111{
112 this->mLanes.clear();
113 this->mLanes.squeeze();
114 this->mLanes = std::move(lanes);
115}
116
117bool CommitInfo::isValid() const
118{
119 static QRegExp hexMatcher("^[0-9A-F]{40}$", Qt::CaseInsensitive);
120
121 return !sha.isEmpty() && hexMatcher.exactMatch(sha);
122}
123
124int CommitInfo::getActiveLane() const
125{
126 auto i = 0;
127
128 for (auto lane : mLanes)
129 {
130 if (lane.isActive())
131 return i;
132 else
133 ++i;
134 }
135
136 return -1;
137}
138
139void CommitInfo::removeChild(CommitInfo *commit)
140{
141 if (mChilds.contains(commit))
142 mChilds.removeAll(commit);
143}
144
145QString CommitInfo::getFirstChildSha() const
146{
147 if (!mChilds.isEmpty())
148 mChilds.constFirst();
149 return QString();
150}
151