diff --git a/src/autotests/CvsIgnorelist.cpp b/src/autotests/CvsIgnorelist.cpp index 35d2d4c..2b79f8c 100644 --- a/src/autotests/CvsIgnorelist.cpp +++ b/src/autotests/CvsIgnorelist.cpp @@ -1,54 +1,86 @@ /** * Copyright (C) 2019 Michael Reeves * * This file is part of KDiff3. * * KDiff3 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * KDiff3 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with KDiff3. If not, see . */ #include +#include #include "../cvsignorelist.h" class CvsIgnoreListTest : public QObject { + const QString defaultPatterns = QString::fromLatin1(". .. core RCSLOG tags TAGS RCS SCCS .make.state " + ".nse_depinfo #* .#* cvslog.* ,* CVS CVS.adm .del-* *.a *.olb *.o *.obj " + "*.so *.Z *~ *.old *.elc *.ln *.bak *.BAK *.orig *.rej *.exe _$* *$"); Q_OBJECT private Q_SLOTS: void init() { CvsIgnoreList test; //sanity check defaults QVERIFY(test.m_exactPatterns.isEmpty()); QVERIFY(test.m_endPatterns.isEmpty()); QVERIFY(test.m_generalPatterns.isEmpty()); QVERIFY(test.m_startPatterns.isEmpty()); } + void addEntriesFromString() { CvsIgnoreList test; - QStringList expected; + CvsIgnoreList expected; - test.addEntriesFromString(". .. core RCSLOG tags TAGS RCS SCCS .make.state"); - expected = QStringList{".", "..", "core", "RCSLOG", "tags", "TAGS", "RCS", "SCCS", ".make.state"}; + QString testString = ". .. core RCSLOG tags TAGS RCS SCCS .make.state"; + test.addEntriesFromString(testString); QVERIFY(!test.m_exactPatterns.isEmpty()); - QVERIFY(test.m_exactPatterns == expected); + QVERIFY(test.m_exactPatterns == testString.split(' ')); + + expected = test = CvsIgnoreList(); + } + + void testDefaults() + { + CvsIgnoreList test; + CvsIgnoreList expected; + MocIgnoreFile file; + t_DirectoryList dirList; + + /* + Verify default init. For this to work we must: + 1. Unset CVSIGNORE + 2. Insure no patterns are read from a .cvsignore file. + MocCvsIgnore emulates a blank cvs file by default insuring the second condition. + */ + test = CvsIgnoreList(); + // + qunsetenv("CVSIGNORE"); + + expected.addEntriesFromString(defaultPatterns); + test.init(file, &dirList); + QVERIFY(test.m_endPatterns == expected.m_endPatterns); + QVERIFY(test.m_exactPatterns == expected.m_exactPatterns); + QVERIFY(test.m_startPatterns == expected.m_startPatterns); + QVERIFY(test.m_generalPatterns == expected.m_generalPatterns); } }; QTEST_MAIN(CvsIgnoreListTest); #include "CvsIgnorelist.moc" diff --git a/src/cvsignorelist.cpp b/src/cvsignorelist.cpp index 0c3f85e..e5700a8 100644 --- a/src/cvsignorelist.cpp +++ b/src/cvsignorelist.cpp @@ -1,197 +1,191 @@ /*************************************************************************** * class CvsIgnoreList from Cervisia cvsdir.cpp * * Copyright (C) 1999-2002 Bernd Gehrmann * * with elements from class StringMatcher * * Copyright (c) 2003 Andre Woebbeking * * Modifications for KDiff3 by Joachim Eibl * * * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/ #include "cvsignorelist.h" #include "TypeUtils.h" #include #include void CvsIgnoreList::init(FileAccess& dir, const t_DirectoryList* pDirList) { - static const QStringList ignorestr = QStringList{".", ".. core", "RCSLOG", "tags", "TAGS", "RCS", "SCCS", ".make.state", - ".nse_depinfo", "#* .#* cvslog.*", ",* CVS", "CVS.adm", ".del-*", "*.a", "*.olb", "*.o", "*.obj", - "*.so", "*.Z", "*~ *.old", "*.elc *.ln", "*.bak", "*.BAK", "*.orig", "*.rej", "*.exe", "_$*", "*$"}; + static const QString ignorestr = QString::fromLatin1(". .. core RCSLOG tags TAGS RCS SCCS .make.state " + ".nse_depinfo #* .#* cvslog.* ,* CVS CVS.adm .del-* *.a *.olb *.o *.obj " + "*.so *.Z *~ *.old *.elc *.ln *.bak *.BAK *.orig *.rej *.exe _$* *$"); + constexpr char varname[] = "CVSIGNORE"; - addEntriesFromList(ignorestr); + addEntriesFromString(ignorestr); addEntriesFromFile(QDir::homePath() + "/.cvsignore"); if(qEnvironmentVariableIsSet(varname) && !qEnvironmentVariableIsEmpty(varname)) { addEntriesFromString(QString::fromLocal8Bit(qgetenv(varname))); } const bool bUseLocalCvsIgnore = cvsIgnoreExists(pDirList); if(bUseLocalCvsIgnore) { FileAccess file(dir); file.addPath(".cvsignore"); if(file.exists() && file.isLocal()) addEntriesFromFile(file.absoluteFilePath()); else { file.createLocalCopy(); addEntriesFromFile(file.getTempName()); } } } -void CvsIgnoreList::addEntriesFromList(const QStringList& patternList) -{ - for(const QString& pattern : patternList) - { - addEntry(pattern); - } -} - void CvsIgnoreList::addEntriesFromString(const QString& str) { QStringList patternList = str.split(' '); for(const QString& pattern : patternList) { addEntry(pattern); } } /* MocIgnoreFile is incapatiable with addEntriesFromFile so do nothing in AUTORUN mode */ void CvsIgnoreList::addEntriesFromFile(const QString& name) { #ifdef AUTORUN Q_UNUSED(name) #else QFile file(name); if(file.open(QIODevice::ReadOnly)) { QTextStream stream(&file); while(!stream.atEnd()) { addEntry(stream.readLine()); } } #endif } void CvsIgnoreList::addEntry(const QString& pattern) { if(pattern != QString("!")) { if(pattern.isEmpty()) return; // The general match is general but slow. // Special tests for '*' and '?' at the beginning or end of a pattern // allow fast checks. // Count number of '*' and '?' unsigned int nofMetaCharacters = 0; const QChar* pos; pos = pattern.unicode(); const QChar* posEnd; posEnd = pos + pattern.length(); while(pos < posEnd) { if(*pos == QChar('*') || *pos == QChar('?')) ++nofMetaCharacters; ++pos; } if(nofMetaCharacters == 0) { m_exactPatterns.append(pattern); } else if(nofMetaCharacters == 1) { if(pattern.at(0) == QChar('*')) { m_endPatterns.append(pattern.right(pattern.length() - 1)); } else if(pattern.at(pattern.length() - 1) == QChar('*')) { m_startPatterns.append(pattern.left(pattern.length() - 1)); } else { m_generalPatterns.append(pattern); } } else { m_generalPatterns.append(pattern); } } else { m_exactPatterns.clear(); m_startPatterns.clear(); m_endPatterns.clear(); m_generalPatterns.clear(); } } bool CvsIgnoreList::matches(const QString& text, bool bCaseSensitive) const { if(m_exactPatterns.indexOf(text) >= 0) { return true; } for(const QString& startPattern: m_startPatterns) { if(text.startsWith(startPattern)) { return true; } } for(const QString& endPattern: m_endPatterns) { if(text.mid(text.length() - endPattern.length()) == endPattern) //(text.endsWith(*it)) { + Q_ASSERT(text.endsWith(endPattern)); return true; } } /* for (QValueList::const_iterator it(m_generalPatterns.begin()), itEnd(m_generalPatterns.end()); it != itEnd; ++it) { if (::fnmatch(*it, text.local8Bit(), FNM_PATHNAME) == 0) { return true; } } */ for(const QString& globStr : m_generalPatterns) { QRegExp pattern(globStr, bCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard); if(pattern.exactMatch(text)) return true; } return false; } bool CvsIgnoreList::cvsIgnoreExists(const t_DirectoryList* pDirList) { for(const FileAccess& dir : *pDirList) { if(dir.fileName() == ".cvsignore") return true; } return false; } diff --git a/src/cvsignorelist.h b/src/cvsignorelist.h index b32308d..fe3a7e3 100644 --- a/src/cvsignorelist.h +++ b/src/cvsignorelist.h @@ -1,48 +1,47 @@ /*************************************************************************** * class CvsIgnoreList from Cervisia cvsdir.cpp * * Copyright (C) 1999-2002 Bernd Gehrmann * * with elements from class StringMatcher * * Copyright (c) 2003 Andre Woebbeking * * Modifications for KDiff3 by Joachim Eibl * * * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/ #ifndef CVSIGNORELIST_H #define CVSIGNORELIST_H #ifndef AUTOTEST #include "fileaccess.h" #else #include "MocIgnoreFile.h" #endif -#include #include +#include class CvsIgnoreList { public: CvsIgnoreList() {} void init(FileAccess& dir, const t_DirectoryList* pDirList); bool matches(const QString& text, bool bCaseSensitive) const; private: friend class CvsIgnoreListTest; bool cvsIgnoreExists(const t_DirectoryList* pDirList); - void addEntriesFromList(const QStringList& patternList); void addEntriesFromString(const QString& str); void addEntriesFromFile(const QString& name); void addEntry(const QString& pattern); QStringList m_exactPatterns; QStringList m_startPatterns; QStringList m_endPatterns; QStringList m_generalPatterns; }; #endif