Finish up the matcher for basic .gitignore matching
[vng.git] / ExcludeMatcher.cpp
blob0ab768e437aa5a6c92f8bc77ed7d0921fdbdee78
1 /*
2 * This file is part of the vng project
3 * Copyright (C) 2008 Thomas Zander <tzander@trolltech.com>
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "ExcludeMatcher.h"
20 #include "GitRunner.h"
21 #include "Logger.h"
23 #include <QDebug>
25 ExcludeMatcher::ExcludeMatcher()
29 bool ExcludeMatcher::isExcluded(const QString &entry)
31 // TODO
32 // current dir should have a .git dir. [assert]
33 // entry is a relative path from our current dir. [assert]
34 if (m_baseMatches.isEmpty()) {
35 // TODO
36 // call git config --get core.excludesfile
37 // $GIT_DIR/info/exclude
40 // split entry into separate dirs.
41 QStringList pathSegments = entry.split(QDir::separator(), QString::SkipEmptyParts);
42 QString fileName = "/"+ pathSegments.takeLast(); // remove last entry (the actual filename);
44 if (isExcluded(m_baseMatches, entry, fileName))
45 return true;
48 pathSegments.insert(0, ".");
49 QString path;
50 foreach(QString segment, pathSegments) {
51 path = path + segment + QDir::separator();
52 if (! m_cachedMatches.contains(path)) {
53 QList<IgnoreLine> items;
54 QFile ignoreFile(path +".gitignore");
55 if (ignoreFile.exists()) {
56 if (ignoreFile.open(QFile::ReadOnly)) {
57 QTextStream file(&ignoreFile);
58 int line=0;
59 while(true) {
60 ++line;
61 QString line = file.readLine();
62 if (line.isNull())
63 break;
64 if (line.isEmpty() || line[0] == '#')
65 continue;
66 IgnoreLine ignoreLine;
67 ignoreLine.inverted = line[0] == '!';
68 if (ignoreLine.inverted)
69 line = line.mid(1);
70 ignoreLine.matchOnFileOnly = line.contains('/');
71 QRegExp re(line, Qt::CaseInsensitive, QRegExp::Wildcard);
72 ignoreLine.regExp = re;
73 if (re.isValid())
74 items << ignoreLine;
75 else
76 Logger::debug() << "invalid entry in " << ignoreFile.fileName() << " line " << line;
78 ignoreFile.close();
81 m_cachedMatches.insert(path, items);
83 if (isExcluded(m_cachedMatches[path], entry, fileName))
84 return true;
86 return false;
90 bool ExcludeMatcher::isExcluded(const QList<IgnoreLine> &ignores, const QString &path, const QString &fileName)
92 foreach (IgnoreLine il, ignores) {
93 bool matches;
94 // qDebug() << "trying on " << il.regExp.pattern() << il.matchOnFileOnly << il.inverted;
95 if (il.matchOnFileOnly)
96 matches = il.regExp.exactMatch(fileName);
97 else
98 matches = il.regExp.exactMatch(path);
99 if (matches != il.inverted)
100 return true;
102 return false;