File indexing completed on 2024-05-12 04:40:01

0001 /*
0002     This file was partly taken from KDevelop's cvs plugin
0003     SPDX-FileCopyrightText: 2007 Robert Gruber <rgruber@users.sourceforge.net>
0004 
0005     Adapted for Git
0006     SPDX-FileCopyrightText: 2008 Evgeniy Ivanov <powerfox@kde.ru>
0007 
0008     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0009 */
0010 
0011 #include "test_git.h"
0012 
0013 #include <QTest>
0014 #include <tests/testcore.h>
0015 #include <tests/autotestshell.h>
0016 #include <QUrl>
0017 #include <QDebug>
0018 
0019 #include <vcs/dvcs/dvcsjob.h>
0020 #include <vcs/vcsannotation.h>
0021 #include "../gitplugin.h"
0022 
0023 #define VERIFYJOB(j) \
0024 do { QVERIFY(j); QVERIFY(j->exec()); QVERIFY((j)->status() == KDevelop::VcsJob::JobSucceeded); } while(0)
0025 
0026 #define VERIFYJOBFAILURE(j) \
0027 do { QVERIFY(j); QVERIFY(((!j->exec()) || ((j)->status() != KDevelop::VcsJob::JobSucceeded))); } while(0)
0028 
0029 inline QString tempDir() { return QDir::tempPath(); }
0030 inline QString gitTest_BaseDir() { return tempDir() + "/kdevGit_testdir/"; }
0031 inline QString gitRepo() { return gitTest_BaseDir() + ".git"; }
0032 inline QString gitSrcDir() { return gitTest_BaseDir() + "src/"; }
0033 inline QString gitTest_FileName() { return QStringLiteral("testfile"); }
0034 inline QString gitTest_FileName2() { return QStringLiteral("foo"); }
0035 inline QString gitTest_FileName3() { return QStringLiteral("bar"); }
0036 
0037 using namespace KDevelop;
0038 
0039 bool writeFile(const QString &path, const QString& content, QIODevice::OpenModeFlag mode = QIODevice::WriteOnly)
0040 {
0041     QFile f(path);
0042 
0043     if (!f.open(mode)) {
0044         return false;
0045     }
0046 
0047     QTextStream input(&f);
0048     input << content;
0049 
0050     return true;
0051 }
0052 
0053 void GitInitTest::initTestCase()
0054 {
0055     AutoTestShell::init({QStringLiteral("kdevgit")});
0056     TestCore::initialize();
0057 
0058     m_plugin = new GitPlugin(TestCore::self());
0059 }
0060 
0061 void GitInitTest::cleanupTestCase()
0062 {
0063     delete m_plugin;
0064 
0065     TestCore::shutdown();
0066 }
0067 
0068 void GitInitTest::init()
0069 {
0070     // Now create the basic directory structure
0071     QDir tmpdir(tempDir());
0072     tmpdir.mkdir(gitTest_BaseDir());
0073     tmpdir.mkdir(gitSrcDir());
0074 }
0075 
0076 void GitInitTest::cleanup()
0077 {
0078     removeTempDirs();
0079 }
0080 
0081 
0082 void GitInitTest::repoInit()
0083 {
0084     qDebug() << "Trying to init repo";
0085     // make job that creates the local repository
0086     VcsJob* j = m_plugin->init(QUrl::fromLocalFile(gitTest_BaseDir()));
0087     VERIFYJOB(j);
0088 
0089     //check if the CVSROOT directory in the new local repository exists now
0090     QVERIFY(QFileInfo::exists(gitRepo()));
0091 
0092     //check if isValidDirectory works
0093     QVERIFY(m_plugin->isValidDirectory(QUrl::fromLocalFile(gitTest_BaseDir())));
0094     //and for non-git dir, I hope nobody has /tmp under git
0095     QVERIFY(!m_plugin->isValidDirectory(QUrl::fromLocalFile(tempDir())));
0096 
0097     //we have nothing, so output should be empty
0098     DVcsJob * j2 = m_plugin->gitRevParse(gitRepo(), QStringList(QStringLiteral("--branches")));
0099     QVERIFY(j2);
0100     QVERIFY(j2->exec());
0101     QVERIFY(j2->output().isEmpty());
0102 
0103     // Make sure to set the Git identity so unit tests don't depend on that
0104     auto j3 = m_plugin->setConfigOption(QUrl::fromLocalFile(gitTest_BaseDir()),
0105               QStringLiteral("user.email"), QStringLiteral("me@example.com"));
0106     VERIFYJOB(j3);
0107     auto j4 = m_plugin->setConfigOption(QUrl::fromLocalFile(gitTest_BaseDir()),
0108               QStringLiteral("user.name"), QStringLiteral("My Name"));
0109     VERIFYJOB(j4);
0110 }
0111 
0112 void GitInitTest::addFiles()
0113 {
0114     qDebug() << "Adding files to the repo";
0115 
0116     //we start it after repoInit, so we still have empty git repo
0117     QVERIFY(writeFile(gitTest_BaseDir() + gitTest_FileName(), QStringLiteral("HELLO WORLD")));
0118     QVERIFY(writeFile(gitTest_BaseDir() + gitTest_FileName2(), QStringLiteral("No, bar()!")));
0119 
0120     //test git-status exitCode (see DVcsJob::setExitCode).
0121     VcsJob* j = m_plugin->status(QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir()));
0122     VERIFYJOB(j);
0123 
0124     // /tmp/kdevGit_testdir/ and testfile
0125     j = m_plugin->add(QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir() + gitTest_FileName()));
0126     VERIFYJOB(j);
0127 
0128     QVERIFY(writeFile(gitSrcDir() + gitTest_FileName3(), QStringLiteral("No, foo()! It's bar()!")));
0129 
0130     //test git-status exitCode again
0131     j = m_plugin->status(QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir()));
0132     VERIFYJOB(j);
0133 
0134     //repository path without trailing slash and a file in a parent directory
0135     // /tmp/repo  and /tmp/repo/src/bar
0136     j = m_plugin->add(QList<QUrl>() << QUrl::fromLocalFile(gitSrcDir() + gitTest_FileName3()));
0137     VERIFYJOB(j);
0138 
0139     //let's use absolute path, because it's used in ContextMenus
0140     j = m_plugin->add(QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir() + gitTest_FileName2()));
0141     VERIFYJOB(j);
0142 
0143     //Now let's create several files and try "git add file1 file2 file3"
0144     const QStringList files{QStringLiteral("file1"), QStringLiteral("file2"), QStringLiteral("la la")};
0145     QList<QUrl> multipleFiles;
0146     for (const QString& file : files) {
0147         QVERIFY(writeFile(gitTest_BaseDir() + file, file));
0148         multipleFiles << QUrl::fromLocalFile(gitTest_BaseDir() + file);
0149     }
0150     j = m_plugin->add(multipleFiles);
0151     VERIFYJOB(j);
0152 }
0153 
0154 void GitInitTest::commitFiles()
0155 {
0156     qDebug() << "Committing...";
0157     //we start it after addFiles, so we just have to commit
0158     VcsJob* j = m_plugin->commit(QStringLiteral("Test commit"), QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir()));
0159     VERIFYJOB(j);
0160 
0161     //test git-status exitCode one more time.
0162     j = m_plugin->status(QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir()));
0163     VERIFYJOB(j);
0164 
0165     //since we committed the file to the "pure" repository, .git/refs/heads/master should exist
0166     //TODO: maybe other method should be used
0167     QString headRefName(gitRepo() + "/refs/heads/master");
0168     QVERIFY(QFileInfo::exists(headRefName));
0169 
0170     //Test the results of the "git add"
0171     auto* jobLs = new DVcsJob(gitTest_BaseDir(), m_plugin);
0172     *jobLs << "git" << "ls-tree" << "--name-only" << "-r" << "HEAD";
0173 
0174     if (jobLs->exec() && jobLs->status() == KDevelop::VcsJob::JobSucceeded) {
0175         QStringList files = jobLs->output().split('\n');
0176         QVERIFY(files.contains(gitTest_FileName()));
0177         QVERIFY(files.contains(gitTest_FileName2()));
0178         QVERIFY(files.contains("src/" + gitTest_FileName3()));
0179     }
0180 
0181     QString firstCommit;
0182 
0183     QFile headRef(headRefName);
0184 
0185     if (headRef.open(QIODevice::ReadOnly)) {
0186         QTextStream output(&headRef);
0187         output >> firstCommit;
0188     }
0189     headRef.close();
0190 
0191     QVERIFY(!firstCommit.isEmpty());
0192 
0193     qDebug() << "Committing one more time";
0194     //let's try to change the file and test "git commit -a"
0195     QVERIFY(writeFile(gitTest_BaseDir() + gitTest_FileName(), QStringLiteral("Just another HELLO WORLD\n")));
0196 
0197     //add changes
0198     j = m_plugin->add(QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir() + gitTest_FileName()));
0199     VERIFYJOB(j);
0200 
0201     j = m_plugin->commit(QStringLiteral("KDevelop's Test commit2"), QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir()));
0202     VERIFYJOB(j);
0203 
0204     QString secondCommit;
0205 
0206     if (headRef.open(QIODevice::ReadOnly)) {
0207         QTextStream output(&headRef);
0208         output >> secondCommit;
0209     }
0210     headRef.close();
0211 
0212     QVERIFY(!secondCommit.isEmpty());
0213     QVERIFY(firstCommit != secondCommit);
0214 
0215 }
0216 
0217 void GitInitTest::testInit()
0218 {
0219     repoInit();
0220 }
0221 
0222 static QString runCommand(const QString& cmd, const QStringList& args)
0223 {
0224     QProcess proc;
0225     proc.setWorkingDirectory(gitTest_BaseDir());
0226     proc.start(cmd, args);
0227     proc.waitForFinished();
0228     return proc.readAllStandardOutput().trimmed();
0229 }
0230 
0231 void GitInitTest::testReadAndSetConfigOption()
0232 {
0233     repoInit();
0234 
0235     {
0236         qDebug() << "read non-existing config option";
0237         QString nameFromPlugin = m_plugin->readConfigOption(QUrl::fromLocalFile(gitTest_BaseDir()),
0238                                                             QStringLiteral("notexisting.asdads"));
0239         QVERIFY(nameFromPlugin.isEmpty());
0240     }
0241 
0242     {
0243         qDebug() << "write user.name = \"John Tester\"";
0244         auto job = m_plugin->setConfigOption(QUrl::fromLocalFile(gitTest_BaseDir()),
0245                                              QStringLiteral("user.name"), QStringLiteral("John Tester"));
0246         VERIFYJOB(job);
0247         const auto name = runCommand(QStringLiteral("git"), {"config", "--get", QStringLiteral("user.name")});
0248         QCOMPARE(name, QStringLiteral("John Tester"));
0249     }
0250 
0251     {
0252         qDebug() << "read user.name";
0253         const QString nameFromPlugin = m_plugin->readConfigOption(QUrl::fromLocalFile(gitTest_BaseDir()),
0254                                                                QStringLiteral("user.name"));
0255         QCOMPARE(nameFromPlugin, QStringLiteral("John Tester"));
0256         const auto name = runCommand(QStringLiteral("git"), {"config", "--get", QStringLiteral("user.name")});
0257         QCOMPARE(name, QStringLiteral("John Tester"));
0258     }
0259 }
0260 
0261 void GitInitTest::testAdd()
0262 {
0263     repoInit();
0264     addFiles();
0265 }
0266 
0267 void GitInitTest::testCommit()
0268 {
0269     repoInit();
0270     addFiles();
0271     commitFiles();
0272 }
0273 
0274 void GitInitTest::testBranch(const QString& newBranch)
0275 {
0276     //Already tested, so I assume that it works
0277     const QUrl baseUrl = QUrl::fromLocalFile(gitTest_BaseDir());
0278     QString oldBranch = runSynchronously(m_plugin->currentBranch(baseUrl)).toString();
0279 
0280     VcsRevision rev;
0281     rev.setRevisionValue(oldBranch, KDevelop::VcsRevision::GlobalNumber);
0282     VcsJob* j = m_plugin->branch(baseUrl, rev, newBranch);
0283     VERIFYJOB(j);
0284     QVERIFY(runSynchronously(m_plugin->branches(baseUrl)).toStringList().contains(newBranch));
0285 
0286     // switch branch
0287     j = m_plugin->switchBranch(baseUrl, newBranch);
0288     VERIFYJOB(j);
0289     QCOMPARE(runSynchronously(m_plugin->currentBranch(baseUrl)).toString(), newBranch);
0290 
0291     // get into detached head state
0292     j = m_plugin->switchBranch(baseUrl, QStringLiteral("HEAD~1"));
0293     VERIFYJOB(j);
0294     QCOMPARE(runSynchronously(m_plugin->currentBranch(baseUrl)).toString(), QString());
0295 
0296     // switch back
0297     j = m_plugin->switchBranch(baseUrl, newBranch);
0298     VERIFYJOB(j);
0299     QCOMPARE(runSynchronously(m_plugin->currentBranch(baseUrl)).toString(), newBranch);
0300 
0301     j = m_plugin->deleteBranch(baseUrl, oldBranch);
0302     VERIFYJOB(j);
0303     QVERIFY(!runSynchronously(m_plugin->branches(baseUrl)).toStringList().contains(oldBranch));
0304 
0305     // Test that we can't delete branch on which we currently are
0306     j = m_plugin->deleteBranch(baseUrl, newBranch);
0307     VERIFYJOBFAILURE(j);
0308     QVERIFY(runSynchronously(m_plugin->branches(baseUrl)).toStringList().contains(newBranch));
0309 
0310     // Test branching off HEAD
0311     rev = KDevelop::VcsRevision::createSpecialRevision(KDevelop::VcsRevision::Head);
0312     j = m_plugin->branch(baseUrl, rev, newBranch+QStringLiteral("-new"));
0313     VERIFYJOB(j);
0314     QVERIFY(runSynchronously(m_plugin->branches(baseUrl)).toStringList().contains(newBranch+QStringLiteral("-new")));
0315 }
0316 
0317 void GitInitTest::testMerge()
0318 {
0319     const QString branchNames[] = {QStringLiteral("aBranchToBeMergedIntoMaster"), QStringLiteral("AnotherBranch")};
0320 
0321     const QString files[]={QStringLiteral("First File to Appear after merging"),QStringLiteral("Second File to Appear after merging"), QStringLiteral("Another_File.txt")};
0322 
0323     const QString content=QStringLiteral("Testing merge.");
0324 
0325     repoInit();
0326     addFiles();
0327     commitFiles();
0328 
0329     const QUrl baseUrl = QUrl::fromLocalFile(gitTest_BaseDir());
0330     VcsJob* j = m_plugin->branches(baseUrl);
0331     VERIFYJOB(j);
0332     QString curBranch = runSynchronously(m_plugin->currentBranch(baseUrl)).toString();
0333     QCOMPARE(curBranch, QStringLiteral("master"));
0334 
0335     VcsRevision rev;
0336     rev.setRevisionValue("master", KDevelop::VcsRevision::GlobalNumber);
0337 
0338     j = m_plugin->branch(baseUrl, rev, branchNames[0]);
0339     VERIFYJOB(j);
0340 
0341     qDebug() << "Adding files to the new branch";
0342 
0343     //we start it after repoInit, so we still have empty git repo
0344     QVERIFY(writeFile(gitTest_BaseDir() + files[0], content));
0345     QVERIFY(writeFile(gitTest_BaseDir() + files[1], content));
0346 
0347     QList<QUrl> listOfAddedFiles{QUrl::fromLocalFile(gitTest_BaseDir() + files[0]),
0348         QUrl::fromLocalFile(gitTest_BaseDir() + files[1])};
0349 
0350     j = m_plugin->add(listOfAddedFiles);
0351     VERIFYJOB(j);
0352 
0353     j = m_plugin->commit(QStringLiteral("Committing to the new branch"), QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir()));
0354     VERIFYJOB(j);
0355 
0356     j = m_plugin->switchBranch(baseUrl, QStringLiteral("master"));
0357     VERIFYJOB(j);
0358 
0359     j = m_plugin->mergeBranch(baseUrl, branchNames[0]);
0360     VERIFYJOB(j);
0361 
0362     auto jobLs = new DVcsJob(gitTest_BaseDir(), m_plugin);
0363     *jobLs << "git" << "ls-tree" << "--name-only" << "-r" << "HEAD" ;
0364 
0365     if (jobLs->exec() && jobLs->status() == KDevelop::VcsJob::JobSucceeded) {
0366         QStringList files = jobLs->output().split('\n');
0367         qDebug() << "Files in this Branch: " << files;
0368         QVERIFY(files.contains(files[0]));
0369         QVERIFY(files.contains(files[1]));
0370     }
0371 
0372     //Testing one more time.
0373     j = m_plugin->switchBranch(baseUrl, branchNames[0]);
0374     VERIFYJOB(j);
0375     rev.setRevisionValue(branchNames[0], KDevelop::VcsRevision::GlobalNumber);
0376     j = m_plugin->branch(baseUrl, rev, branchNames[1]);
0377     VERIFYJOB(j);
0378     QVERIFY(writeFile(gitTest_BaseDir() + files[2], content));
0379     j = m_plugin->add(QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir() + files[2]));
0380     VERIFYJOB(j);
0381     j = m_plugin->commit(QStringLiteral("Committing to AnotherBranch"), QList<QUrl>() << baseUrl);
0382     VERIFYJOB(j);
0383     j = m_plugin->switchBranch(baseUrl, branchNames[0]);
0384     VERIFYJOB(j);
0385     j = m_plugin->mergeBranch(baseUrl, branchNames[1]);
0386     VERIFYJOB(j);
0387     qDebug() << j->errorString() ;
0388 
0389     jobLs = new DVcsJob(gitTest_BaseDir(), m_plugin);
0390     *jobLs << "git" << "ls-tree" << "--name-only" << "-r" << "HEAD" ;
0391 
0392     if (jobLs->exec() && jobLs->status() == KDevelop::VcsJob::JobSucceeded) {
0393         QStringList files = jobLs->output().split('\n');
0394         QVERIFY(files.contains(files[2]));
0395         qDebug() << "Files in this Branch: " << files;
0396     }
0397 
0398     j = m_plugin->switchBranch(baseUrl, QStringLiteral("master"));
0399     VERIFYJOB(j);
0400     j = m_plugin->mergeBranch(baseUrl, branchNames[1]);
0401     VERIFYJOB(j);
0402     qDebug() << j->errorString() ;
0403 
0404     jobLs = new DVcsJob(gitTest_BaseDir(), m_plugin);
0405     *jobLs << "git" << "ls-tree" << "--name-only" << "-r" << "HEAD" ;
0406 
0407     if (jobLs->exec() && jobLs->status() == KDevelop::VcsJob::JobSucceeded) {
0408         QStringList files = jobLs->output().split('\n');
0409         QVERIFY(files.contains(files[2]));
0410         qDebug() << "Files in this Branch: " << files;
0411     }
0412 
0413 }
0414 
0415 void GitInitTest::testBranching()
0416 {
0417     repoInit();
0418     addFiles();
0419     commitFiles();
0420 
0421     const QUrl baseUrl = QUrl::fromLocalFile(gitTest_BaseDir());
0422     VcsJob* j = m_plugin->branches(baseUrl);
0423     VERIFYJOB(j);
0424 
0425     QString curBranch = runSynchronously(m_plugin->currentBranch(baseUrl)).toString();
0426     QCOMPARE(curBranch, QStringLiteral("master"));
0427 
0428     testBranch(QStringLiteral("new"));
0429     testBranch(QStringLiteral("averylongbranchnamejusttotestlongnames"));
0430     testBranch(QStringLiteral("KDE/4.10"));
0431 }
0432 
0433 void GitInitTest::revHistory()
0434 {
0435     repoInit();
0436     addFiles();
0437     commitFiles();
0438 
0439     const QVector<KDevelop::DVcsEvent> commits = m_plugin->allCommits(gitTest_BaseDir());
0440     QVERIFY(!commits.isEmpty());
0441     QStringList logMessages;
0442 
0443     for (auto& commit : commits)
0444         logMessages << commit.log();
0445 
0446     QCOMPARE(commits.count(), 2);
0447 
0448     QCOMPARE(logMessages[0], QStringLiteral("KDevelop's Test commit2"));  //0 is later than 1!
0449 
0450     QCOMPARE(logMessages[1], QStringLiteral("Test commit"));
0451 
0452     QVERIFY(commits[1].parents().isEmpty());  //0 is later than 1!
0453 
0454     QVERIFY(!commits[0].parents().isEmpty()); //initial commit is on the top
0455 
0456     QVERIFY(commits[1].commit().contains(QRegExp("^\\w{,40}$")));
0457 
0458     QVERIFY(commits[0].commit().contains(QRegExp("^\\w{,40}$")));
0459 
0460     QVERIFY(commits[0].parents()[0].contains(QRegExp("^\\w{,40}$")));
0461 }
0462 
0463 void GitInitTest::testAnnotation()
0464 {
0465     repoInit();
0466     addFiles();
0467     commitFiles();
0468 
0469     // called after commitFiles
0470     QVERIFY(writeFile(gitTest_BaseDir() + gitTest_FileName(), QStringLiteral("An appended line"), QIODevice::Append));
0471 
0472     VcsJob* j = m_plugin->commit(QStringLiteral("KDevelop's Test commit3"), QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir()));
0473     VERIFYJOB(j);
0474 
0475     j = m_plugin->annotate(QUrl::fromLocalFile(gitTest_BaseDir() + gitTest_FileName()), VcsRevision::createSpecialRevision(VcsRevision::Head));
0476     VERIFYJOB(j);
0477 
0478     QList<QVariant> results = j->fetchResults().toList();
0479     QCOMPARE(results.size(), 2);
0480     QVERIFY(results.at(0).canConvert<VcsAnnotationLine>());
0481     VcsAnnotationLine annotation = results.at(0).value<VcsAnnotationLine>();
0482     QCOMPARE(annotation.lineNumber(), 0);
0483     QCOMPARE(annotation.commitMessage(), QStringLiteral("KDevelop's Test commit2"));
0484 
0485     QVERIFY(results.at(1).canConvert<VcsAnnotationLine>());
0486     annotation = results.at(1).value<VcsAnnotationLine>();
0487     QCOMPARE(annotation.lineNumber(), 1);
0488     QCOMPARE(annotation.commitMessage(), QStringLiteral("KDevelop's Test commit3"));
0489 }
0490 
0491 void GitInitTest::testRemoveEmptyFolder()
0492 {
0493     repoInit();
0494 
0495     QDir d(gitTest_BaseDir());
0496     d.mkdir(QStringLiteral("emptydir"));
0497 
0498     VcsJob* j = m_plugin->remove(QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir()+"emptydir/"));
0499     if (j) VERIFYJOB(j);
0500 
0501     QVERIFY(!d.exists(QStringLiteral("emptydir")));
0502 }
0503 
0504 void GitInitTest::testRemoveEmptyFolderInFolder()
0505 {
0506     repoInit();
0507 
0508     QDir d(gitTest_BaseDir());
0509     d.mkdir(QStringLiteral("dir"));
0510 
0511     QDir d2(gitTest_BaseDir()+"dir");
0512     d2.mkdir(QStringLiteral("emptydir"));
0513 
0514     VcsJob* j = m_plugin->remove(QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir()+"dir/"));
0515     if (j) VERIFYJOB(j);
0516 
0517     QVERIFY(!d.exists(QStringLiteral("dir")));
0518 }
0519 
0520 void GitInitTest::testRemoveUnindexedFile()
0521 {
0522     repoInit();
0523 
0524     QVERIFY(writeFile(gitTest_BaseDir() + gitTest_FileName(), QStringLiteral("An appended line"), QIODevice::Append));
0525 
0526     VcsJob* j = m_plugin->remove(QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir() + gitTest_FileName()));
0527     if (j) VERIFYJOB(j);
0528 
0529     QVERIFY(!QFile::exists(gitTest_BaseDir() + gitTest_FileName()));
0530 }
0531 
0532 void GitInitTest::testRemoveFolderContainingUnversionedFiles()
0533 {
0534     repoInit();
0535 
0536     QDir d(gitTest_BaseDir());
0537     d.mkdir(QStringLiteral("dir"));
0538 
0539     QVERIFY(writeFile(gitTest_BaseDir() + "dir/foo", QStringLiteral("An appended line"), QIODevice::Append));
0540     VcsJob* j = m_plugin->add(QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir()+"dir"));
0541     VERIFYJOB(j);
0542     j = m_plugin->commit(QStringLiteral("initial commit"), QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir()));
0543     VERIFYJOB(j);
0544 
0545     QVERIFY(writeFile(gitTest_BaseDir() + "dir/bar", QStringLiteral("An appended line"), QIODevice::Append));
0546 
0547     j = m_plugin->remove(QList<QUrl>() << QUrl::fromLocalFile(gitTest_BaseDir() + "dir"));
0548     if (j) VERIFYJOB(j);
0549 
0550     QVERIFY(!QFile::exists(gitTest_BaseDir() + "dir"));
0551 
0552 }
0553 
0554 
0555 void GitInitTest::removeTempDirs()
0556 {
0557     const auto dirPath = gitTest_BaseDir();
0558     QDir dir(dirPath);
0559     if (dir.exists() && !dir.removeRecursively()) {
0560         qDebug() << "QDir::removeRecursively(" << dirPath << ") returned false";
0561     }
0562 }
0563 
0564 void GitInitTest::testDiff()
0565 {
0566     repoInit();
0567     addFiles();
0568     commitFiles();
0569 
0570     QVERIFY(writeFile(gitTest_BaseDir() + gitTest_FileName(), QStringLiteral("something else")));
0571 
0572     VcsRevision srcrev = VcsRevision::createSpecialRevision(VcsRevision::Base);
0573     VcsRevision dstrev = VcsRevision::createSpecialRevision(VcsRevision::Working);
0574     VcsJob* j = m_plugin->diff(QUrl::fromLocalFile(gitTest_BaseDir()), srcrev, dstrev, IBasicVersionControl::Recursive);
0575     VERIFYJOB(j);
0576 
0577     KDevelop::VcsDiff d = j->fetchResults().value<KDevelop::VcsDiff>();
0578     QVERIFY(d.baseDiff().isLocalFile());
0579     QString path = d.baseDiff().toLocalFile();
0580     QVERIFY(QDir().exists(path+"/.git"));
0581 }
0582 
0583 void GitInitTest::testStash()
0584 {
0585     repoInit();
0586     addFiles();
0587     commitFiles();
0588     const QVector<KDevelop::DVcsEvent> commits = m_plugin->allCommits(gitTest_BaseDir());
0589     QVERIFY(!commits.isEmpty());
0590     QStringList logMessages;
0591 
0592     for (auto& commit : commits)
0593         logMessages << commit.log();
0594 
0595     auto repo_url = QUrl::fromLocalFile(gitTest_BaseDir());
0596 
0597     // No stash
0598     QVERIFY(!m_plugin->hasStashes(gitTest_BaseDir()));
0599     VcsJob* j = m_plugin->stashList(gitTest_BaseDir());
0600     VERIFYJOB(j);
0601     QVERIFY(j->fetchResults().value<QList<GitPlugin::StashItem>>().isEmpty());
0602 
0603     // Do some changes
0604     QVERIFY(writeFile(gitTest_BaseDir() + gitTest_FileName(), QStringLiteral("NEW CONTENT TO STASH")));
0605     QVERIFY(writeFile(gitTest_BaseDir() + gitTest_FileName2(), QStringLiteral("No, REALLY NEW FOOO()!")));
0606 
0607     // Verify stashing works
0608     j = m_plugin->gitStash(gitTest_BaseDir(), {}, OutputJob::Silent);
0609     VERIFYJOB(j);
0610     QVERIFY(m_plugin->hasStashes(gitTest_BaseDir()));
0611 
0612     // Verify stash list gives us the single stash
0613     j = m_plugin->stashList(gitTest_BaseDir());
0614     VERIFYJOB(j);
0615     auto items = j->fetchResults().value<QList<GitPlugin::StashItem>>();
0616     QVERIFY(items.length() == 1);
0617     QVERIFY(items[0].stackDepth == 0);
0618     QVERIFY(items[0].branch == runSynchronously(m_plugin->currentBranch(repo_url)).toString());
0619     QVERIFY(commits[0].commit() == items[0].parentSHA);
0620 
0621     // Verify stash on new branch gives us correct parent branch
0622     //
0623     // 1. switch to a new branch
0624     auto rev = KDevelop::VcsRevision::createSpecialRevision(KDevelop::VcsRevision::Head);
0625     j = m_plugin->branch(repo_url, rev, QStringLiteral("my-new-branch"));
0626     VERIFYJOB(j);
0627     j = m_plugin->switchBranch(repo_url, QStringLiteral("my-new-branch"));
0628     VERIFYJOB(j);
0629 
0630     // 2. Do more changes & stash them
0631     QString testFileContent = QStringLiteral("2. NEW CONTENT TO STASH");
0632     QVERIFY(writeFile(gitTest_BaseDir() + gitTest_FileName(), testFileContent));
0633     QVERIFY(writeFile(gitTest_BaseDir() + gitTest_FileName2(), QStringLiteral("2. No, REALLY NEW FOOO()!")));
0634     j = m_plugin->gitStash(gitTest_BaseDir(), {}, OutputJob::Silent);
0635     VERIFYJOB(j);
0636     QFile testFile(gitTest_BaseDir() + gitTest_FileName());
0637     testFile.open(QIODevice::ReadOnly);
0638     auto testFileContentAfterStash = QString::fromUtf8(testFile.readAll());
0639     testFile.close();
0640     QVERIFY(testFileContent != testFileContentAfterStash);
0641 
0642 
0643     // 3. Verify stash list gives us a new stash
0644     j = m_plugin->stashList(gitTest_BaseDir());
0645     VERIFYJOB(j);
0646     items = j->fetchResults().value<QList<GitPlugin::StashItem>>();
0647     QVERIFY(items.length() == 2);
0648 
0649     // 4. Find the newest stash
0650     bool found = false;
0651     for(const auto& item : items) {
0652         if (item.stackDepth != 0) continue;
0653         // 5. Verify that the new branch is parent of the new stash
0654         QVERIFY(item.branch == QStringLiteral("my-new-branch"));
0655         found = true;
0656     }
0657     QVERIFY(found);
0658 
0659     // Verify that stash pop recreates the contents and drops the stash item
0660     j = m_plugin->gitStash(gitTest_BaseDir(), {QStringLiteral("pop")}, OutputJob::Silent);
0661     VERIFYJOB(j);
0662     testFile.open(QIODevice::ReadOnly);
0663     auto testFileContentAfterPop = QString::fromUtf8(testFile.readAll());
0664     QVERIFY(testFileContentAfterPop == testFileContent);
0665     j = m_plugin->stashList(gitTest_BaseDir());
0666     VERIFYJOB(j);
0667     items = j->fetchResults().value<QList<GitPlugin::StashItem>>();
0668     QVERIFY(items.length() == 1);
0669 
0670 }
0671 
0672 QTEST_MAIN(GitInitTest)
0673 
0674 // #include "gittest.moc"
0675 #include "moc_test_git.cpp"