Excludes: switch all the path handling to QString

Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
This commit is contained in:
Kevin Ottens 2020-11-26 16:55:04 +01:00
parent 1c443ad021
commit cce3d6f6fc
No known key found for this signature in database
GPG key ID: 074BBBCB8DECC9E2
3 changed files with 50 additions and 55 deletions

View file

@ -223,7 +223,7 @@ static CSYNC_EXCLUDE_TYPE _csync_excluded_common(const QString &path, bool exclu
return match;
}
static QByteArray leftIncludeLast(const QByteArray & arr, char c)
static QString leftIncludeLast(const QString &arr, char c)
{
// left up to and including `c`
return arr.left(arr.lastIndexOf(c, arr.size() - 2) + 1);
@ -231,8 +231,8 @@ static QByteArray leftIncludeLast(const QByteArray & arr, char c)
using namespace OCC;
ExcludedFiles::ExcludedFiles(QString localPath)
: _localPath(std::move(localPath))
ExcludedFiles::ExcludedFiles(const QString &localPath)
: _localPath(localPath)
, _clientVersion(MIRALL_VERSION_MAJOR, MIRALL_VERSION_MINOR, MIRALL_VERSION_PATCH)
{
Q_ASSERT(_localPath.endsWith("/"));
@ -253,12 +253,12 @@ ExcludedFiles::~ExcludedFiles() = default;
void ExcludedFiles::addExcludeFilePath(const QString &path)
{
_excludeFiles[_localPath.toUtf8()].append(path);
_excludeFiles[_localPath].append(path);
}
void ExcludedFiles::addInTreeExcludeFilePath(const QString &path)
{
BasePathByteArray basePath = leftIncludeLast(path.toUtf8(), '/');
BasePathString basePath = leftIncludeLast(path, '/');
_excludeFiles[basePath].append(path);
}
@ -267,12 +267,12 @@ void ExcludedFiles::setExcludeConflictFiles(bool onoff)
_excludeConflictFiles = onoff;
}
void ExcludedFiles::addManualExclude(const QByteArray &expr)
void ExcludedFiles::addManualExclude(const QString &expr)
{
addManualExclude(expr, _localPath.toUtf8());
addManualExclude(expr, _localPath);
}
void ExcludedFiles::addManualExclude(const QByteArray &expr, const QByteArray &basePath)
void ExcludedFiles::addManualExclude(const QString &expr, const QString &basePath)
{
#if defined(Q_OS_WIN)
Q_ASSERT(basePath.size() >= 2 && basePath.at(1) == ':');
@ -304,13 +304,13 @@ void ExcludedFiles::setClientVersion(ExcludedFiles::Version version)
_clientVersion = version;
}
bool ExcludedFiles::loadExcludeFile(const QByteArray & basePath, const QString & file)
bool ExcludedFiles::loadExcludeFile(const QString &basePath, const QString & file)
{
QFile f(file);
if (!f.open(QIODevice::ReadOnly))
return false;
QList<QByteArray> patterns;
QStringList patterns;
while (!f.atEnd()) {
QByteArray line = f.readLine().trimmed();
if (line.startsWith("#!version")) {
@ -320,7 +320,7 @@ bool ExcludedFiles::loadExcludeFile(const QByteArray & basePath, const QString &
if (line.isEmpty() || line.startsWith('#'))
continue;
csync_exclude_expand_escapes(line);
patterns.append(line);
patterns.append(QString::fromUtf8(line));
}
_allExcludes.insert(basePath, patterns);
@ -437,7 +437,7 @@ CSYNC_EXCLUDE_TYPE ExcludedFiles::traversalPatternMatch(const QString &path, Ite
// Directories are guaranteed to be visited before their files
if (filetype == ItemTypeDirectory) {
const auto basePath = QString(_localPath + path + QLatin1Char('/')).toUtf8();
const auto basePath = QString(_localPath + path + QLatin1Char('/'));
const auto fi = QFileInfo(basePath + QStringLiteral(".sync-exclude.lst"));
if (fi.isReadable()) {
@ -454,7 +454,7 @@ CSYNC_EXCLUDE_TYPE ExcludedFiles::traversalPatternMatch(const QString &path, Ite
bnameStr = path.midRef(lastSlash + 1);
}
QByteArray basePath(_localPath.toUtf8() + path.toUtf8());
QString basePath(_localPath + path);
while (basePath.size() > _localPath.size()) {
basePath = leftIncludeLast(basePath, '/');
QRegularExpressionMatch m;
@ -478,7 +478,7 @@ CSYNC_EXCLUDE_TYPE ExcludedFiles::traversalPatternMatch(const QString &path, Ite
}
// third capture: full path matching is triggered
basePath = _localPath.toUtf8() + path.toUtf8();
basePath = _localPath + path;
while (basePath.size() > _localPath.size()) {
basePath = leftIncludeLast(basePath, '/');
QRegularExpressionMatch m;
@ -517,7 +517,7 @@ CSYNC_EXCLUDE_TYPE ExcludedFiles::fullPatternMatch(const QString &p, ItemType fi
if (path[0] == '/')
path = path.mid(1);
QByteArray basePath(_localPath.toUtf8() + path.toUtf8());
QString basePath(_localPath + path);
while (basePath.size() > _localPath.size()) {
basePath = leftIncludeLast(basePath, '/');
QRegularExpressionMatch m;
@ -689,7 +689,7 @@ void ExcludedFiles::prepare()
prepare(basePath);
}
void ExcludedFiles::prepare(const BasePathByteArray & basePath)
void ExcludedFiles::prepare(const BasePathString & basePath)
{
Q_ASSERT(_allExcludes.contains(basePath));
@ -765,7 +765,7 @@ void ExcludedFiles::prepare(const BasePathByteArray & basePath)
// Make exclude relative to _localPath
exclude.prepend(relPath);
}
auto regexExclude = convertToRegexpSyntax(QString::fromUtf8(exclude), _wildcardsMatchSlash);
auto regexExclude = convertToRegexpSyntax(exclude, _wildcardsMatchSlash);
if (!fullPath) {
regexAppend(bnameFileDir, bnameDir, regexExclude, matchDirOnly);
} else {

View file

@ -67,7 +67,7 @@ class OCSYNC_EXPORT ExcludedFiles : public QObject
public:
typedef std::tuple<int, int, int> Version;
ExcludedFiles(QString localPath = "/");
explicit ExcludedFiles(const QString &localPath = QStringLiteral("/"));
~ExcludedFiles();
/**
@ -102,8 +102,8 @@ public:
* Primarily used in tests. Patterns added this way are preserved when
* reloadExcludeFiles() is called.
*/
void addManualExclude(const QByteArray &expr);
void addManualExclude(const QByteArray &expr, const QByteArray &basePath);
void addManualExclude(const QString &expr);
void addManualExclude(const QString &expr, const QString &basePath);
/**
* Removes all manually added exclude patterns.
@ -147,7 +147,7 @@ public slots:
/**
* Loads the exclude patterns from file the registered base paths.
*/
bool loadExcludeFile(const QByteArray & basePath, const QString & file);
bool loadExcludeFile(const QString &basePath, const QString &file);
private:
/**
@ -178,24 +178,19 @@ private:
CSYNC_EXCLUDE_TYPE fullPatternMatch(const QString &path, ItemType filetype) const;
// Our BasePath need to end with '/'
class BasePathByteArray : public QByteArray
class BasePathString : public QString
{
public:
BasePathByteArray(QByteArray && other)
: QByteArray(std::move(other))
BasePathString(QString &&other)
: QString(std::move(other))
{
Q_ASSERT(this->endsWith('/'));
Q_ASSERT(endsWith('/'));
}
BasePathByteArray(const QByteArray & other)
: QByteArray(other)
{
Q_ASSERT(this->endsWith('/'));
}
BasePathByteArray(const char * data, int size = -1)
: BasePathByteArray(QByteArray(data, size))
BasePathString(const QString &other)
: QString(other)
{
Q_ASSERT(endsWith('/'));
}
};
@ -228,28 +223,28 @@ private:
* full matcher would exclude. Example: "b" is excluded. traversal("b/c")
* returns not-excluded because "c" isn't a bname activation pattern.
*/
void prepare(const BasePathByteArray & basePath);
void prepare(const BasePathString &basePath);
void prepare();
QString _localPath;
/// Files to load excludes from
QMap<BasePathByteArray, QList<QString>> _excludeFiles;
QMap<BasePathString, QStringList> _excludeFiles;
/// Exclude patterns added with addManualExclude()
QMap<BasePathByteArray, QList<QByteArray>> _manualExcludes;
QMap<BasePathString, QStringList> _manualExcludes;
/// List of all active exclude patterns
QMap<BasePathByteArray, QList<QByteArray>> _allExcludes;
QMap<BasePathString, QStringList> _allExcludes;
/// see prepare()
QMap<BasePathByteArray, QRegularExpression> _bnameTraversalRegexFile;
QMap<BasePathByteArray, QRegularExpression> _bnameTraversalRegexDir;
QMap<BasePathByteArray, QRegularExpression> _fullTraversalRegexFile;
QMap<BasePathByteArray, QRegularExpression> _fullTraversalRegexDir;
QMap<BasePathByteArray, QRegularExpression> _fullRegexFile;
QMap<BasePathByteArray, QRegularExpression> _fullRegexDir;
QMap<BasePathString, QRegularExpression> _bnameTraversalRegexFile;
QMap<BasePathString, QRegularExpression> _bnameTraversalRegexDir;
QMap<BasePathString, QRegularExpression> _fullTraversalRegexFile;
QMap<BasePathString, QRegularExpression> _fullTraversalRegexDir;
QMap<BasePathString, QRegularExpression> _fullRegexFile;
QMap<BasePathString, QRegularExpression> _fullRegexDir;
bool _excludeConflictFiles = true;

View file

@ -100,16 +100,16 @@ static void check_csync_exclude_add(void **)
excludedFiles->addManualExclude("/tmp/check_csync1/*");
assert_int_equal(check_file_full("/tmp/check_csync1/foo"), CSYNC_FILE_EXCLUDE_LIST);
assert_int_equal(check_file_full("/tmp/check_csync2/foo"), CSYNC_NOT_EXCLUDED);
assert_true(excludedFiles->_allExcludes["/"].contains("/tmp/check_csync1/*"));
assert_true(excludedFiles->_allExcludes[QStringLiteral("/")].contains("/tmp/check_csync1/*"));
assert_true(excludedFiles->_fullRegexFile["/"].pattern().contains("csync1"));
assert_true(excludedFiles->_fullTraversalRegexFile["/"].pattern().contains("csync1"));
assert_false(excludedFiles->_bnameTraversalRegexFile["/"].pattern().contains("csync1"));
assert_true(excludedFiles->_fullRegexFile[QStringLiteral("/")].pattern().contains("csync1"));
assert_true(excludedFiles->_fullTraversalRegexFile[QStringLiteral("/")].pattern().contains("csync1"));
assert_false(excludedFiles->_bnameTraversalRegexFile[QStringLiteral("/")].pattern().contains("csync1"));
excludedFiles->addManualExclude("foo");
assert_true(excludedFiles->_bnameTraversalRegexFile["/"].pattern().contains("foo"));
assert_true(excludedFiles->_fullRegexFile["/"].pattern().contains("foo"));
assert_false(excludedFiles->_fullTraversalRegexFile["/"].pattern().contains("foo"));
assert_true(excludedFiles->_bnameTraversalRegexFile[QStringLiteral("/")].pattern().contains("foo"));
assert_true(excludedFiles->_fullRegexFile[QStringLiteral("/")].pattern().contains("foo"));
assert_false(excludedFiles->_fullTraversalRegexFile[QStringLiteral("/")].pattern().contains("foo"));
}
static void check_csync_exclude_add_per_dir(void **)
@ -117,15 +117,15 @@ static void check_csync_exclude_add_per_dir(void **)
excludedFiles->addManualExclude("*", "/tmp/check_csync1/");
assert_int_equal(check_file_full("/tmp/check_csync1/foo"), CSYNC_FILE_EXCLUDE_LIST);
assert_int_equal(check_file_full("/tmp/check_csync2/foo"), CSYNC_NOT_EXCLUDED);
assert_true(excludedFiles->_allExcludes["/tmp/check_csync1/"].contains("*"));
assert_true(excludedFiles->_allExcludes[QStringLiteral("/tmp/check_csync1/")].contains("*"));
excludedFiles->addManualExclude("foo");
assert_true(excludedFiles->_fullRegexFile["/"].pattern().contains("foo"));
assert_true(excludedFiles->_fullRegexFile[QStringLiteral("/")].pattern().contains("foo"));
excludedFiles->addManualExclude("foo/bar", "/tmp/check_csync1/");
assert_true(excludedFiles->_fullRegexFile["/tmp/check_csync1/"].pattern().contains("bar"));
assert_true(excludedFiles->_fullTraversalRegexFile["/tmp/check_csync1/"].pattern().contains("bar"));
assert_false(excludedFiles->_bnameTraversalRegexFile["/tmp/check_csync1/"].pattern().contains("foo"));
assert_true(excludedFiles->_fullRegexFile[QStringLiteral("/tmp/check_csync1/")].pattern().contains("bar"));
assert_true(excludedFiles->_fullTraversalRegexFile[QStringLiteral("/tmp/check_csync1/")].pattern().contains("bar"));
assert_false(excludedFiles->_bnameTraversalRegexFile[QStringLiteral("/tmp/check_csync1/")].pattern().contains("foo"));
}
static void check_csync_excluded(void **)