File indexing completed on 2024-04-28 05:49:10
0001 /* 0002 SPDX-FileCopyrightText: 2021 Waqar Ahmed <waqar.17a@gmail.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 #include "stashdialog.h" 0007 #include "gitwidget.h" 0008 #include "hostprocess.h" 0009 0010 #include <QProcess> 0011 #include <QTreeView> 0012 #include <QWidget> 0013 0014 #include <KTextEditor/View> 0015 0016 #include <KLocalizedString> 0017 0018 #include <drawing_utils.h> 0019 0020 #include <gitprocess.h> 0021 0022 StashDialog::StashDialog(QWidget *parent, QWidget *window, const QString &gitPath) 0023 : HUDDialog(parent, window) 0024 , m_gitPath(gitPath) 0025 { 0026 } 0027 0028 void StashDialog::openDialog(StashMode m) 0029 { 0030 setStringList({}); 0031 0032 switch (m) { 0033 case StashMode::Stash: 0034 case StashMode::StashKeepIndex: 0035 case StashMode::StashUntrackIncluded: 0036 m_lineEdit.setPlaceholderText(i18n("Stash message (optional). Enter to confirm, Esc to leave.")); 0037 m_currentMode = m; 0038 break; 0039 case StashMode::StashPop: 0040 case StashMode::StashDrop: 0041 case StashMode::StashApply: 0042 case StashMode::ShowStashContent: 0043 m_lineEdit.setPlaceholderText(i18n("Type to filter, Enter to pop stash, Esc to leave.")); 0044 m_currentMode = m; 0045 getStashList(); 0046 break; 0047 case StashMode::StashApplyLast: 0048 applyStash({}); 0049 return; 0050 case StashMode::StashPopLast: 0051 popStash({}); 0052 return; 0053 default: 0054 return; 0055 } 0056 0057 // trigger reselect first 0058 m_lineEdit.textChanged(QString()); 0059 exec(); 0060 } 0061 0062 static QString getStashIndex(const QModelIndex &index) 0063 { 0064 QString s = index.data().toString(); 0065 if (s.isEmpty() || !s.startsWith(QStringLiteral("stash@{"))) { 0066 return {}; 0067 } 0068 static QRegularExpression re(QStringLiteral("stash@{(.*)}")); 0069 const auto match = re.match(s); 0070 if (!match.hasMatch()) 0071 return {}; 0072 return match.captured(1); 0073 } 0074 0075 void StashDialog::slotReturnPressed(const QModelIndex &index) 0076 { 0077 switch (m_currentMode) { 0078 case StashMode::Stash: 0079 stash(false, false); 0080 break; 0081 case StashMode::StashKeepIndex: 0082 stash(true, false); 0083 break; 0084 case StashMode::StashUntrackIncluded: 0085 stash(false, true); 0086 break; 0087 default: 0088 break; 0089 } 0090 0091 auto stashIndex = getStashIndex(index); 0092 if (stashIndex.isEmpty()) 0093 return; 0094 0095 switch (m_currentMode) { 0096 case StashMode::StashApply: 0097 applyStash(stashIndex); 0098 break; 0099 case StashMode::StashPop: 0100 popStash(stashIndex); 0101 break; 0102 case StashMode::StashDrop: 0103 dropStash(stashIndex); 0104 break; 0105 case StashMode::ShowStashContent: 0106 showStash(stashIndex); 0107 break; 0108 default: 0109 break; 0110 } 0111 0112 hide(); 0113 } 0114 0115 QProcess *StashDialog::gitp(const QStringList &arguments) 0116 { 0117 auto git = new QProcess(this); 0118 setupGitProcess(*git, m_gitPath, arguments); 0119 return git; 0120 } 0121 0122 void StashDialog::stash(bool keepIndex, bool includeUntracked) 0123 { 0124 QStringList args{QStringLiteral("stash"), QStringLiteral("-q")}; 0125 0126 if (keepIndex) { 0127 args.append(QStringLiteral("--keep-index")); 0128 } 0129 if (includeUntracked) { 0130 args.append(QStringLiteral("-u")); 0131 } 0132 0133 if (!m_lineEdit.text().isEmpty()) { 0134 args.append(QStringLiteral("-m")); 0135 args.append(m_lineEdit.text()); 0136 } 0137 0138 auto git = gitp(args); 0139 connect(git, &QProcess::finished, this, [this, git](int exitCode, QProcess::ExitStatus es) { 0140 if (es != QProcess::NormalExit || exitCode != 0) { 0141 qWarning() << git->errorString(); 0142 Q_EMIT message(i18n("Failed to stash changes %1", QString::fromUtf8(git->readAllStandardError())), true); 0143 } else { 0144 Q_EMIT message(i18n("Changes stashed successfully."), false); 0145 } 0146 Q_EMIT done(); 0147 git->deleteLater(); 0148 }); 0149 startHostProcess(*git, QProcess::ReadOnly); 0150 } 0151 0152 void StashDialog::getStashList() 0153 { 0154 auto git = gitp({QStringLiteral("stash"), QStringLiteral("list")}); 0155 startHostProcess(*git, QProcess::ReadOnly); 0156 0157 QStringList stashList; 0158 if (git->waitForStarted() && git->waitForFinished(-1)) { 0159 if (git->exitStatus() == QProcess::NormalExit && git->exitCode() == 0) { 0160 stashList = QString::fromUtf8(git->readAllStandardOutput()).split(QLatin1Char('\n')); 0161 setStringList(stashList); 0162 } else { 0163 Q_EMIT message(i18n("Failed to get stash list. Error: ") + QString::fromUtf8(git->readAll()), true); 0164 } 0165 } 0166 } 0167 0168 void StashDialog::popStash(const QString &index, const QString &command) 0169 { 0170 QStringList args{QStringLiteral("stash"), command}; 0171 if (!index.isEmpty()) { 0172 args.append(index); 0173 } 0174 auto git = gitp(args); 0175 0176 connect(git, &QProcess::finished, this, [this, command, git](int exitCode, QProcess::ExitStatus es) { 0177 if (es != QProcess::NormalExit || exitCode != 0) { 0178 if (command == QLatin1String("apply")) { 0179 Q_EMIT message(i18n("Failed to apply stash. Error: ") + QString::fromUtf8(git->readAll()), true); 0180 } else if (command == QLatin1String("drop")) { 0181 Q_EMIT message(i18n("Failed to drop stash. Error: ") + QString::fromUtf8(git->readAll()), true); 0182 } else { 0183 Q_EMIT message(i18n("Failed to pop stash. Error: ") + QString::fromUtf8(git->readAll()), true); 0184 } 0185 } else { 0186 if (command == QLatin1String("apply")) { 0187 Q_EMIT message(i18n("Stash applied successfully."), false); 0188 } else if (command == QLatin1String("drop")) { 0189 Q_EMIT message(i18n("Stash dropped successfully."), false); 0190 } else { 0191 Q_EMIT message(i18n("Stash popped successfully."), false); 0192 } 0193 } 0194 Q_EMIT done(); 0195 git->deleteLater(); 0196 }); 0197 startHostProcess(*git, QProcess::ReadOnly); 0198 } 0199 0200 void StashDialog::applyStash(const QString &index) 0201 { 0202 popStash(index, QStringLiteral("apply")); 0203 } 0204 0205 void StashDialog::dropStash(const QString &index) 0206 { 0207 popStash(index, QStringLiteral("drop")); 0208 } 0209 0210 void StashDialog::showStash(const QString &index) 0211 { 0212 if (index.isEmpty()) { 0213 return; 0214 } 0215 0216 auto git = gitp({QStringLiteral("stash"), QStringLiteral("show"), QStringLiteral("-p"), index}); 0217 0218 connect(git, &QProcess::finished, this, [this, git](int exitCode, QProcess::ExitStatus es) { 0219 if (es != QProcess::NormalExit || exitCode != 0) { 0220 Q_EMIT message(i18n("Show stash failed. Error: ") + QString::fromUtf8(git->readAll()), true); 0221 } else { 0222 Q_EMIT showStashDiff(git->readAllStandardOutput()); 0223 } 0224 Q_EMIT done(); 0225 git->deleteLater(); 0226 }); 0227 0228 startHostProcess(*git, QProcess::ReadOnly); 0229 } 0230 0231 #include "moc_stashdialog.cpp"