1#include "UnstagedMenu.h"
2
3#include <GitBase.h>
4#include <GitLocal.h>
5#include <GitSyncProcess.h>
6#include <QLogger.h>
7
8#include <QDir>
9#include <QFile>
10#include <QMessageBox>
11
12using namespace QLogger;
13
14UnstagedMenu::UnstagedMenu(const QSharedPointer<GitBase> &git, const QString &fileName, QWidget *parent)
15 : QMenu(parent)
16 , mGit(git)
17 , mFileName(fileName)
18{
19 setAttribute(Qt::WA_DeleteOnClose);
20
21 connect(addAction(tr("See changes")), &QAction::triggered, this, [this]() { emit signalShowDiff(mFileName); });
22 connect(addAction(tr("Blame")), &QAction::triggered, this, [this]() { emit signalShowFileHistory(mFileName); });
23 connect(addAction(tr("Edit file")), &QAction::triggered, this,
24 [this]() { emit signalEditFile(mGit->getWorkingDir() + "/" + mFileName); });
25
26 addSeparator();
27
28 connect(addAction(tr("Stage file")), &QAction::triggered, this, &UnstagedMenu::signalStageFile);
29
30 connect(addAction(tr("Revert file changes")), &QAction::triggered, this, [this]() {
31 const auto msgBoxRet
32 = QMessageBox::question(this, tr("Ignoring file"), tr("Are you sure you want to revert the changes?"));
33
34 if (msgBoxRet == QMessageBox::Yes)
35 {
36 QScopedPointer<GitLocal> git(new GitLocal(mGit));
37 const auto ret = git->checkoutFile(mFileName);
38
39 if (ret)
40 emit changeReverted(mFileName);
41 }
42 });
43
44 addSeparator();
45
46 const auto ignoreMenu = addMenu(tr("Ignore"));
47
48 connect(ignoreMenu->addAction(tr("Ignore file")), &QAction::triggered, this, [this]() {
49 const auto ret = QMessageBox::question(this, tr("Ignoring file"),
50 tr("Are you sure you want to add the file to the black list?"));
51
52 if (ret == QMessageBox::Yes)
53 {
54 const auto gitRet = addEntryToGitIgnore(mFileName);
55
56 if (gitRet)
57 emit signalCheckedOut();
58 }
59 });
60
61 connect(addAction(tr("Delete file")), &QAction::triggered, this, &UnstagedMenu::onDeleteFile);
62
63 connect(addAction(tr("Delete ALL untracked files")), &QAction::triggered, this, &UnstagedMenu::deleteUntracked);
64
65 connect(ignoreMenu->addAction(tr("Ignore extension")), &QAction::triggered, this, [this]() {
66 const auto msgBoxRet = QMessageBox::question(
67 this, tr("Ignoring extension"), tr("Are you sure you want to add the file extension to the black list?"));
68
69 if (msgBoxRet == QMessageBox::Yes)
70 {
71 auto fileParts = mFileName.split(".");
72 fileParts.takeFirst();
73 const auto extension = QString("*.%1").arg(fileParts.join("."));
74 const auto ret = addEntryToGitIgnore(extension);
75
76 if (ret)
77 emit signalCheckedOut();
78 }
79 });
80
81 connect(ignoreMenu->addAction(tr("Ignore containing folder")), &QAction::triggered, this, [this]() {
82 const auto msgBoxRet = QMessageBox::question(
83 this, tr("Ignoring folder"), tr("Are you sure you want to add the containing folder to the black list?"));
84
85 if (msgBoxRet == QMessageBox::Yes)
86 {
87 const auto path = mFileName.lastIndexOf("/");
88 const auto folder = mFileName.left(path);
89 const auto extension = QString("%1/*").arg(folder);
90 const auto ret = addEntryToGitIgnore(extension);
91
92 if (ret)
93 emit signalCheckedOut();
94 }
95 });
96
97 addSeparator();
98
99 connect(addAction(tr("Add all files to commit")), &QAction::triggered, this, &UnstagedMenu::signalCommitAll);
100 connect(addAction(tr("Revert all changes")), &QAction::triggered, this, [this]() {
101 const auto msgBoxRet
102 = QMessageBox::question(this, tr("Ignoring file"), tr("Are you sure you want to undo all the changes?"));
103 if (msgBoxRet == QMessageBox::Yes)
104 emit signalRevertAll();
105 });
106}
107
108bool UnstagedMenu::addEntryToGitIgnore(const QString &entry)
109{
110 auto entryAdded = false;
111 QDir d(mGit->getWorkingDir());
112 QFile f(d.absolutePath() + "/.gitignore");
113
114 if (!f.exists())
115 {
116 if (f.open(QIODevice::ReadWrite))
117 f.close();
118 }
119
120 if (f.open(QIODevice::Append))
121 {
122 const auto bytesWritten = f.write(entry.toUtf8() + "\n");
123
124 if (bytesWritten != -1)
125 {
126 QMessageBox::information(this, tr("File added to .gitignore"),
127 tr("The file has been added to the ignore list in the file .gitignore."));
128
129 entryAdded = true;
130 }
131 else
132 QMessageBox::critical(this, tr("Unable to add the entry"),
133 tr("It was impossible to add the entry in the .gitignore file."));
134
135 f.close();
136 }
137
138 return entryAdded;
139}
140
141void UnstagedMenu::onDeleteFile()
142{
143 const auto path = QString("%1").arg(mFileName);
144
145 QLog_Info("UI", "Removing path: " + path);
146
147 QProcess p;
148 p.setWorkingDirectory(mGit->getWorkingDir());
149 p.start("rm", { "-rf", path });
150
151 if (p.waitForFinished())
152 emit signalCheckedOut();
153}
154