2011-04-06 13:48:02 +04:00
|
|
|
/*
|
2014-01-13 19:16:19 +04:00
|
|
|
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
|
2011-04-06 13:48:02 +04:00
|
|
|
*
|
|
|
|
* 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
|
2014-01-13 19:16:19 +04:00
|
|
|
* the Free Software Foundation; version 2 of the License.
|
2011-04-06 13:48:02 +04:00
|
|
|
*
|
|
|
|
* This program 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.
|
|
|
|
*/
|
2011-02-17 02:21:45 +03:00
|
|
|
|
2011-03-16 16:50:34 +03:00
|
|
|
// event masks
|
2014-07-11 02:31:24 +04:00
|
|
|
#include "folderwatcher.h"
|
2012-05-21 18:48:49 +04:00
|
|
|
|
2012-03-01 19:13:50 +04:00
|
|
|
#include <stdint.h>
|
2011-03-16 16:50:34 +03:00
|
|
|
|
2011-02-17 02:21:45 +03:00
|
|
|
#include <QFileInfo>
|
|
|
|
#include <QFlags>
|
|
|
|
#include <QDebug>
|
|
|
|
#include <QDir>
|
|
|
|
#include <QMutexLocker>
|
|
|
|
#include <QStringList>
|
2011-03-18 15:54:32 +03:00
|
|
|
#include <QTimer>
|
2011-02-17 02:21:45 +03:00
|
|
|
|
2014-01-27 15:31:54 +04:00
|
|
|
#if defined(Q_OS_WIN)
|
2014-07-11 02:31:24 +04:00
|
|
|
#include "folderwatcher_win.h"
|
2014-01-27 15:31:54 +04:00
|
|
|
#elif defined(Q_OS_MAC)
|
2014-07-11 02:31:24 +04:00
|
|
|
#include "folderwatcher_mac.h"
|
2014-04-29 13:02:44 +04:00
|
|
|
#elif defined(Q_OS_UNIX)
|
2014-07-11 02:31:24 +04:00
|
|
|
#include "folderwatcher_linux.h"
|
2014-01-27 15:31:54 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2011-02-17 02:21:45 +03:00
|
|
|
namespace Mirall {
|
|
|
|
|
2011-03-18 15:54:32 +03:00
|
|
|
FolderWatcher::FolderWatcher(const QString &root, QObject *parent)
|
2014-01-13 18:23:38 +04:00
|
|
|
: QObject(parent)
|
2011-02-17 02:21:45 +03:00
|
|
|
{
|
2014-01-13 18:23:38 +04:00
|
|
|
_d.reset(new FolderWatcherPrivate(this, root));
|
2012-12-05 21:23:35 +04:00
|
|
|
|
2014-01-13 18:23:38 +04:00
|
|
|
_timer.start();
|
2011-03-21 00:18:38 +03:00
|
|
|
}
|
|
|
|
|
2014-01-27 15:31:54 +04:00
|
|
|
FolderWatcher::~FolderWatcher()
|
|
|
|
{ }
|
|
|
|
|
2013-07-05 18:54:11 +04:00
|
|
|
void FolderWatcher::addIgnoreListFile( const QString& file )
|
2012-03-28 14:23:34 +04:00
|
|
|
{
|
|
|
|
if( file.isEmpty() ) return;
|
|
|
|
|
|
|
|
QFile infile( file );
|
|
|
|
if (!infile.open(QIODevice::ReadOnly | QIODevice::Text))
|
|
|
|
return;
|
|
|
|
|
|
|
|
while (!infile.atEnd()) {
|
|
|
|
QString line = QString::fromLocal8Bit( infile.readLine() ).trimmed();
|
2013-10-14 18:09:51 +04:00
|
|
|
if( !(line.startsWith( QLatin1Char('#') ) || line.isEmpty()) ) {
|
2013-07-22 23:39:13 +04:00
|
|
|
_ignores.append(line);
|
2012-03-28 14:23:34 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-05 21:23:35 +04:00
|
|
|
QStringList FolderWatcher::ignores() const
|
|
|
|
{
|
|
|
|
return _ignores;
|
|
|
|
}
|
|
|
|
|
2014-01-13 18:23:38 +04:00
|
|
|
bool FolderWatcher::pathIsIgnored( const QString& path )
|
|
|
|
{
|
|
|
|
if( path.isEmpty() ) return true;
|
|
|
|
|
2014-11-05 18:48:27 +03:00
|
|
|
QFileInfo fInfo(path);
|
|
|
|
if( fInfo.isHidden() ) {
|
|
|
|
qDebug() << "* Discarded as is hidden!" << fInfo.filePath();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-01-13 18:23:38 +04:00
|
|
|
// Remember: here only directories are checked!
|
|
|
|
// If that changes to files too at some day, remember to check
|
|
|
|
// for the database name as well as the trailing slash rule for
|
|
|
|
// dirs only. Best use csync_ignore than somehow.
|
|
|
|
foreach (QString pattern, _ignores) {
|
|
|
|
QRegExp regexp(pattern);
|
|
|
|
regexp.setPatternSyntax(QRegExp::Wildcard);
|
|
|
|
|
|
|
|
if(pattern.endsWith('/')) {
|
|
|
|
// directory only pattern. But since only dirs here, we cut off the trailing dir.
|
|
|
|
pattern.remove(pattern.length()-1, 1); // remove the last char.
|
|
|
|
}
|
|
|
|
// if the pattern contains / it needs to match the entire path
|
|
|
|
if (pattern.contains('/') && regexp.exactMatch(path)) {
|
|
|
|
qDebug() << "* Discarded by ignore pattern: " << path;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList components = path.split('/');
|
|
|
|
foreach (const QString& comp, components) {
|
|
|
|
if(regexp.exactMatch(comp)) {
|
|
|
|
qDebug() << "* Discarded by component ignore pattern " << comp;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-01-11 23:35:58 +04:00
|
|
|
void FolderWatcher::changeDetected( const QString& path )
|
2011-04-05 14:16:24 +04:00
|
|
|
{
|
2014-02-18 03:36:41 +04:00
|
|
|
QStringList paths(path);
|
|
|
|
changeDetected(paths);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FolderWatcher::changeDetected( const QStringList& paths )
|
|
|
|
{
|
2014-05-15 11:43:13 +04:00
|
|
|
// qDebug() << Q_FUNC_INFO << paths;
|
2014-02-18 03:36:41 +04:00
|
|
|
|
|
|
|
// TODO: this shortcut doesn't look very reliable:
|
|
|
|
// - why is the timeout only 1 second?
|
|
|
|
// - what if there are more than one file being updated frequently?
|
|
|
|
// - why do we skip the file alltogether instead of e.g. reducing the upload frequency?
|
|
|
|
|
2014-01-13 18:23:38 +04:00
|
|
|
// Check if the same path was reported within the last second.
|
2014-02-18 03:36:41 +04:00
|
|
|
QSet<QString> pathsSet = paths.toSet();
|
|
|
|
if( pathsSet == _lastPaths && _timer.elapsed() < 1000 ) {
|
2014-01-13 18:23:38 +04:00
|
|
|
// the same path was reported within the last second. Skip.
|
|
|
|
return;
|
|
|
|
}
|
2014-02-18 03:36:41 +04:00
|
|
|
_lastPaths = pathsSet;
|
2014-01-13 18:23:38 +04:00
|
|
|
_timer.restart();
|
|
|
|
|
2014-02-18 03:36:41 +04:00
|
|
|
QSet<QString> changedFolders;
|
|
|
|
|
2014-01-13 18:23:38 +04:00
|
|
|
// ------- handle ignores:
|
2014-02-18 03:36:41 +04:00
|
|
|
for (int i = 0; i < paths.size(); ++i) {
|
|
|
|
QString path = paths[i];
|
|
|
|
if( pathIsIgnored(path) ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
QFileInfo fi(path);
|
|
|
|
if (fi.isDir()) {
|
|
|
|
changedFolders.insert(path);
|
|
|
|
} else {
|
|
|
|
changedFolders.insert(fi.dir().path());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (changedFolders.isEmpty()) {
|
2014-01-13 18:23:38 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-02-18 03:36:41 +04:00
|
|
|
qDebug() << "detected changes in folders:" << changedFolders;
|
|
|
|
foreach (const QString &path, changedFolders) {
|
|
|
|
emit folderChanged(path);
|
|
|
|
}
|
2012-12-05 21:30:40 +04:00
|
|
|
}
|
|
|
|
|
2013-08-19 19:41:42 +04:00
|
|
|
void FolderWatcher::addPath(const QString &path )
|
|
|
|
{
|
|
|
|
_d->addPath(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FolderWatcher::removePath(const QString &path )
|
|
|
|
{
|
|
|
|
_d->removePath(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-04 20:46:44 +04:00
|
|
|
} // namespace Mirall
|
2011-02-17 02:21:45 +03:00
|
|
|
|