1 | #pragma once |
2 | |
3 | /**************************************************************************************** |
4 | ** GitQlient is an application to manage and operate one or several Git repositories. With |
5 | ** GitQlient you will be able to add commits, branches and manage all the options Git provides. |
6 | ** Copyright (C) 2021 Francesc Martinez |
7 | ** |
8 | ** LinkedIn: www.linkedin.com/in/cescmm/ |
9 | ** Web: www.francescmm.com |
10 | ** |
11 | ** This program is free software; you can redistribute it and/or |
12 | ** modify it under the terms of the GNU Lesser General Public |
13 | ** License as published by the Free Software Foundation; either |
14 | ** version 2 of the License, or (at your option) any later version. |
15 | ** |
16 | ** This program is distributed in the hope that it will be useful, |
17 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
19 | ** Lesser General Public License for more details. |
20 | ** |
21 | ** You should have received a copy of the GNU Lesser General Public |
22 | ** License along with this library; if not, write to the Free Software |
23 | ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
24 | ***************************************************************************************/ |
25 | |
26 | #include <DiffInfo.h> |
27 | |
28 | #include <QStringList> |
29 | #include <QPair> |
30 | #include <QVector> |
31 | #include <QPlainTextEdit> |
32 | #include <QMessageBox> |
33 | |
34 | namespace DiffHelper |
35 | { |
36 | |
37 | struct DiffChange |
38 | { |
39 | QString newFileName; |
40 | int newFileStartLine; |
41 | QString oldFileName; |
42 | int oldFileStartLine; |
43 | QString ; |
44 | QString content; |
45 | QPair<QStringList, QVector<ChunkDiffInfo::ChunkInfo>> oldData; |
46 | QPair<QStringList, QVector<ChunkDiffInfo::ChunkInfo>> newData; |
47 | }; |
48 | |
49 | inline void (QString , int &startOldFile, int &startNewFile) |
50 | { |
51 | header = header.split(" @@ " ).first(); |
52 | header.remove("@" ); |
53 | header = header.trimmed(); |
54 | auto modifications = header.split(" " ); |
55 | startOldFile = std::abs(modifications.first().split("," ).first().toInt()); |
56 | startNewFile = std::abs(modifications.last().split("," ).first().toInt()); |
57 | } |
58 | |
59 | inline QVector<DiffChange> splitDiff(const QString &diff) |
60 | { |
61 | QVector<DiffHelper::DiffChange> changes; |
62 | |
63 | #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) |
64 | const auto flag = Qt::SkipEmptyParts; |
65 | #else |
66 | const auto flag = QString::SkipEmptyParts; |
67 | #endif |
68 | |
69 | const auto chunks = diff.split("diff --git" , flag); |
70 | |
71 | for (const auto &chunk : chunks) |
72 | { |
73 | auto lines = chunk.split("\n" ); |
74 | DiffHelper::DiffChange change; |
75 | |
76 | auto filesStr = lines.takeFirst(); |
77 | auto files = filesStr.trimmed().split(" " ); |
78 | change.newFileName = files.first().remove("a/" ); |
79 | change.oldFileName = files.last().remove("b/" ); |
80 | |
81 | auto isA = lines.constFirst().startsWith("copy " ) || lines.constFirst().startsWith("index " ) |
82 | || lines.constFirst().startsWith("new " ); |
83 | auto isB = lines.constFirst().startsWith("old " ) || lines.constFirst().startsWith("rename " ) |
84 | || lines.constFirst().startsWith("similarity " ); |
85 | auto isC = lines.constFirst().startsWith("+++ " ) || lines.constFirst().startsWith("--- " ); |
86 | |
87 | while (isA || isB || isC) |
88 | { |
89 | lines.takeFirst(); |
90 | |
91 | isA = lines.constFirst().startsWith("copy " ) || lines.constFirst().startsWith("index " ) |
92 | || lines.constFirst().startsWith("new " ); |
93 | isB = lines.constFirst().startsWith("old " ) || lines.constFirst().startsWith("rename " ) |
94 | || lines.constFirst().startsWith("similarity " ); |
95 | isC = lines.constFirst().startsWith("+++ " ) || lines.constFirst().startsWith("--- " ); |
96 | } |
97 | |
98 | for (auto &line : lines) |
99 | { |
100 | if (line.startsWith("@@" )) |
101 | { |
102 | if (!change.content.isEmpty()) |
103 | { |
104 | changes.append(change); |
105 | change.content.clear(); |
106 | } |
107 | |
108 | change.header = line; |
109 | extractLinesFromHeader(change.header, change.oldFileStartLine, change.newFileStartLine); |
110 | } |
111 | else |
112 | change.content.append(line + "\n" ); |
113 | } |
114 | |
115 | changes.append(change); |
116 | } |
117 | return changes; |
118 | } |
119 | |
120 | inline DiffInfo processDiff(const QString &text, QPair<QStringList, QVector<ChunkDiffInfo::ChunkInfo>> &newFileData, |
121 | QPair<QStringList, QVector<ChunkDiffInfo::ChunkInfo>> &oldFileData) |
122 | { |
123 | DiffInfo diffInfo; |
124 | ChunkDiffInfo diff; |
125 | int oldFileRow = 1; |
126 | int newFileRow = 1; |
127 | |
128 | const auto lines = text.split("\n" ); |
129 | for (auto line : lines) |
130 | { |
131 | if (line.startsWith('-')) |
132 | { |
133 | line.remove(0, 1); |
134 | |
135 | if (diff.oldFile.startLine == -1) |
136 | diff.oldFile.startLine = oldFileRow; |
137 | |
138 | oldFileData.first.append(line); |
139 | |
140 | ++oldFileRow; |
141 | } |
142 | else if (line.startsWith('+')) |
143 | { |
144 | line.remove(0, 1); |
145 | |
146 | if (diff.newFile.startLine == -1) |
147 | { |
148 | diff.newFile.startLine = newFileRow; |
149 | diff.newFile.addition = true; |
150 | } |
151 | |
152 | newFileData.first.append(line); |
153 | |
154 | ++newFileRow; |
155 | } |
156 | else |
157 | { |
158 | line.remove(0, 1); |
159 | |
160 | if (diff.oldFile.startLine != -1) |
161 | diff.oldFile.endLine = oldFileRow - 1; |
162 | |
163 | if (diff.newFile.startLine != -1) |
164 | diff.newFile.endLine = newFileRow - 1; |
165 | |
166 | if (diff.isValid()) |
167 | { |
168 | if (diff.newFile.isValid()) |
169 | newFileData.second.append(diff.newFile); |
170 | |
171 | if (diff.oldFile.isValid()) |
172 | oldFileData.second.append(diff.oldFile); |
173 | |
174 | diffInfo.chunks.append(diff); |
175 | } |
176 | |
177 | oldFileData.first.append(line); |
178 | newFileData.first.append(line); |
179 | |
180 | diff = ChunkDiffInfo(); |
181 | |
182 | ++oldFileRow; |
183 | ++newFileRow; |
184 | } |
185 | } |
186 | |
187 | diffInfo.fullDiff = lines; |
188 | diffInfo.newFileDiff = newFileData.first; |
189 | diffInfo.oldFileDiff = oldFileData.first; |
190 | |
191 | return diffInfo; |
192 | } |
193 | |
194 | inline void findString(const QString &s, QPlainTextEdit *textEdit, QWidget *managerWidget) |
195 | { |
196 | if (!s.isEmpty()) |
197 | { |
198 | QTextCursor cursor = textEdit->textCursor(); |
199 | QTextCursor cursorSaved = cursor; |
200 | |
201 | if (!textEdit->find(s)) |
202 | { |
203 | cursor.movePosition(QTextCursor::Start); |
204 | textEdit->setTextCursor(cursor); |
205 | |
206 | if (!textEdit->find(s)) |
207 | { |
208 | textEdit->setTextCursor(cursorSaved); |
209 | |
210 | QMessageBox::information(managerWidget, QObject::tr("Text not found" ), QObject::tr("Text not found." )); |
211 | } |
212 | } |
213 | } |
214 | } |
215 | |
216 | } |
217 | |