summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--application/MainWindow.cpp2
-rw-r--r--logic/FileSystem.cpp116
-rw-r--r--logic/FileSystem.h39
-rw-r--r--logic/InstanceList.cpp12
-rw-r--r--logic/minecraft/Mod.cpp2
-rw-r--r--logic/minecraft/ModList.cpp2
-rw-r--r--logic/minecraft/World.cpp4
-rw-r--r--logic/pathmatcher/IPathMatcher.h2
-rw-r--r--logic/pathmatcher/MultiMatcher.h2
-rw-r--r--logic/pathmatcher/RegexpMatcher.h17
10 files changed, 138 insertions, 60 deletions
diff --git a/application/MainWindow.cpp b/application/MainWindow.cpp
index 71888870..2469f983 100644
--- a/application/MainWindow.cpp
+++ b/application/MainWindow.cpp
@@ -1090,7 +1090,7 @@ InstancePtr MainWindow::instanceFromZipPack(QString instName, QString instGroup,
CustomMessageBox::selectable(this, tr("Error"), tr("Archive does not contain instance.cfg"))->show();
return nullptr;
}
- if (!FS::copyPath(instanceCfgFile.absoluteDir().absolutePath(), instDir))
+ if (!FS::copy(instanceCfgFile.absoluteDir().absolutePath(), instDir)())
{
CustomMessageBox::selectable(this, tr("Error"), tr("Unable to copy instance"))->show();
return nullptr;
diff --git a/logic/FileSystem.cpp b/logic/FileSystem.cpp
index ca4a3ba0..006356b3 100644
--- a/logic/FileSystem.cpp
+++ b/logic/FileSystem.cpp
@@ -9,16 +9,18 @@
#include <QDesktopServices>
#include <QUrl>
+namespace FS {
+
void ensureExists(const QDir &dir)
{
if (!QDir().mkpath(dir.absolutePath()))
{
- throw FS::FileSystemException("Unable to create directory " + dir.dirName() + " (" +
+ throw FileSystemException("Unable to create directory " + dir.dirName() + " (" +
dir.absolutePath() + ")");
}
}
-void FS::write(const QString &filename, const QByteArray &data)
+void write(const QString &filename, const QByteArray &data)
{
ensureExists(QFileInfo(filename).dir());
QSaveFile file(filename);
@@ -39,7 +41,7 @@ void FS::write(const QString &filename, const QByteArray &data)
}
}
-QByteArray FS::read(const QString &filename)
+QByteArray read(const QString &filename)
{
QFile file(filename);
if (!file.open(QFile::ReadOnly))
@@ -58,7 +60,7 @@ QByteArray FS::read(const QString &filename)
return data;
}
-bool FS::ensureFilePathExists(QString filenamepath)
+bool ensureFilePathExists(QString filenamepath)
{
QFileInfo a(filenamepath);
QDir dir;
@@ -67,7 +69,7 @@ bool FS::ensureFilePathExists(QString filenamepath)
return success;
}
-bool FS::ensureFolderPathExists(QString foldernamepath)
+bool ensureFolderPathExists(QString foldernamepath)
{
QFileInfo a(foldernamepath);
QDir dir;
@@ -76,56 +78,77 @@ bool FS::ensureFolderPathExists(QString foldernamepath)
return success;
}
-bool FS::copyPath(const QString &src, const QString &dst, bool follow_symlinks)
+bool copy::operator()(const QString &offset)
{
//NOTE always deep copy on windows. the alternatives are too messy.
#if defined Q_OS_WIN32
- follow_symlinks = true;
+ m_followSymlinks = true;
#endif
- QDir dir(src);
- if (!dir.exists())
- return false;
- if (!ensureFolderPathExists(dst))
- return false;
+ auto src = PathCombine(m_src.absolutePath(), offset);
+ auto dst = PathCombine(m_dst.absolutePath(), offset);
- bool OK = true;
+ QFileInfo currentSrc(src);
+ if (!currentSrc.exists())
+ return false;
- qDebug() << "Looking at " << dir.absolutePath();
- foreach(QString f, dir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System))
+ if(!m_followSymlinks && currentSrc.isSymLink())
{
- QString inner_src = src + QDir::separator() + f;
- QString inner_dst = dst + QDir::separator() + f;
- qDebug() << f << "translates to"<< inner_src << "to" << inner_dst;
- QFileInfo fileInfo(inner_src);
- if(!follow_symlinks && fileInfo.isSymLink())
+ qDebug() << "creating symlink" << src << " - " << dst;
+ if (!ensureFilePathExists(dst))
{
- qDebug() << "creating symlink" << inner_src << " - " << inner_dst;
- OK &= QFile::link(fileInfo.symLinkTarget(),inner_dst);
+ qWarning() << "Cannot create path!";
+ return false;
}
- else if (fileInfo.isDir())
+ return QFile::link(currentSrc.symLinkTarget(), dst);
+ }
+ else if(currentSrc.isFile())
+ {
+ qDebug() << "copying file" << src << " - " << dst;
+ if (!ensureFilePathExists(dst))
{
- qDebug() << "recursing" << inner_src << " - " << inner_dst;
- OK &= copyPath(inner_src, inner_dst, follow_symlinks);
+ qWarning() << "Cannot create path!";
+ return false;
}
- else if (fileInfo.isFile())
+ return QFile::copy(src, dst);
+ }
+ else if(currentSrc.isDir())
+ {
+ qDebug() << "recursing" << offset;
+ if (!ensureFolderPathExists(dst))
{
- qDebug() << "copying file" << inner_src << " - " << inner_dst;
- OK &= QFile::copy(inner_src, inner_dst);
+ qWarning() << "Cannot create path!";
+ return false;
}
- else
+ QDir currentDir(src);
+ for(auto & f : currentDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System))
{
- OK = false;
- qCritical() << "Copy ERROR: Unknown filesystem object:" << inner_src;
+ auto inner_offset = PathCombine(offset, f);
+ // ignore and skip stuff that matches the blacklist.
+ if(m_blacklist && m_blacklist->matches(inner_offset))
+ {
+ continue;
+ }
+ if(!operator()(inner_offset))
+ {
+ return false;
+ }
}
}
- return OK;
+ else
+ {
+ qCritical() << "Copy ERROR: Unknown filesystem object:" << src;
+ return false;
+ }
+ return true;
}
+
+
#if defined Q_OS_WIN32
#include <windows.h>
#include <string>
#endif
-bool FS::deletePath(QString path)
+bool deletePath(QString path)
{
bool OK = true;
QDir dir(path);
@@ -138,7 +161,7 @@ bool FS::deletePath(QString path)
QDir::AllDirs | QDir::Files,
QDir::DirsFirst);
- for(QFileInfo info: allEntries)
+ for(auto & info: allEntries)
{
#if defined Q_OS_WIN32
QString nativePath = QDir::toNativeSeparators(info.absoluteFilePath());
@@ -182,7 +205,7 @@ bool FS::deletePath(QString path)
}
-QString FS::PathCombine(QString path1, QString path2)
+QString PathCombine(QString path1, QString path2)
{
if(!path1.size())
return path2;
@@ -191,17 +214,17 @@ QString FS::PathCombine(QString path1, QString path2)
return QDir::cleanPath(path1 + QDir::separator() + path2);
}
-QString FS::PathCombine(QString path1, QString path2, QString path3)
+QString PathCombine(QString path1, QString path2, QString path3)
{
return PathCombine(PathCombine(path1, path2), path3);
}
-QString FS::AbsolutePath(QString path)
+QString AbsolutePath(QString path)
{
return QFileInfo(path).absolutePath();
}
-QString FS::ResolveExecutable(QString path)
+QString ResolveExecutable(QString path)
{
if (path.isEmpty())
{
@@ -225,7 +248,7 @@ QString FS::ResolveExecutable(QString path)
* Any paths inside the current directory will be normalized to relative paths (to current)
* Other paths will be made absolute
*/
-QString FS::NormalizePath(QString path)
+QString NormalizePath(QString path)
{
QDir a = QDir::currentPath();
QString currentAbsolute = a.absolutePath();
@@ -245,7 +268,7 @@ QString FS::NormalizePath(QString path)
QString badFilenameChars = "\"\\/?<>:*|!";
-QString FS::RemoveInvalidFilenameChars(QString string, QChar replaceWith)
+QString RemoveInvalidFilenameChars(QString string, QChar replaceWith)
{
for (int i = 0; i < string.length(); i++)
{
@@ -257,7 +280,7 @@ QString FS::RemoveInvalidFilenameChars(QString string, QChar replaceWith)
return string;
}
-QString FS::DirNameFromString(QString string, QString inDir)
+QString DirNameFromString(QString string, QString inDir)
{
int num = 0;
QString baseName = RemoveInvalidFilenameChars(string, '-');
@@ -281,7 +304,7 @@ QString FS::DirNameFromString(QString string, QString inDir)
return dirName;
}
-void FS::openDirInDefaultProgram(QString path, bool ensureExists)
+void openDirInDefaultProgram(QString path, bool ensureExists)
{
QDir parentPath;
QDir dir(path);
@@ -292,14 +315,14 @@ void FS::openDirInDefaultProgram(QString path, bool ensureExists)
QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath()));
}
-void FS::openFileInDefaultProgram(QString filename)
+void openFileInDefaultProgram(QString filename)
{
QDesktopServices::openUrl(QUrl::fromLocalFile(filename));
}
// Does the directory path contain any '!'? If yes, return true, otherwise false.
// (This is a problem for Java)
-bool FS::checkProblemticPathJava(QDir folder)
+bool checkProblemticPathJava(QDir folder)
{
QString pathfoldername = folder.absolutePath();
return pathfoldername.contains("!", Qt::CaseInsensitive);
@@ -366,13 +389,13 @@ HRESULT CreateLink(LPCSTR linkPath, LPCSTR targetPath, LPCSTR args)
#endif
-QString FS::getDesktopDir()
+QString getDesktopDir()
{
return QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
}
// Cross-platform Shortcut creation
-bool FS::createShortCut(QString location, QString dest, QStringList args, QString name,
+bool createShortCut(QString location, QString dest, QStringList args, QString name,
QString icon)
{
#if defined Q_OS_LINUX
@@ -426,3 +449,4 @@ bool FS::createShortCut(QString location, QString dest, QStringList args, QStrin
return false;
#endif
}
+} \ No newline at end of file
diff --git a/logic/FileSystem.h b/logic/FileSystem.h
index 5055eb6c..5e21375b 100644
--- a/logic/FileSystem.h
+++ b/logic/FileSystem.h
@@ -3,9 +3,11 @@
#pragma once
#include "Exception.h"
+#include "pathmatcher/IPathMatcher.h"
#include "multimc_logic_export.h"
#include <QDir>
+#include <QFlags>
namespace FS
{
@@ -38,10 +40,39 @@ MULTIMC_LOGIC_EXPORT bool ensureFilePathExists(QString filenamepath);
*/
MULTIMC_LOGIC_EXPORT bool ensureFolderPathExists(QString filenamepath);
-/**
- * Copy a folder recursively
- */
-MULTIMC_LOGIC_EXPORT bool copyPath(const QString &src, const QString &dst, bool follow_symlinks = true);
+class MULTIMC_LOGIC_EXPORT copy
+{
+public:
+ copy(const copy&) = delete;
+ copy(const QString & src, const QString & dst)
+ {
+ m_src = src;
+ m_dst = dst;
+ }
+ copy & followSymlinks(const bool follow)
+ {
+ m_followSymlinks = follow;
+ return *this;
+ }
+ copy & blacklist(const IPathMatcher * filter)
+ {
+ m_blacklist = filter;
+ return *this;
+ }
+ bool operator()()
+ {
+ return operator()(QString());
+ }
+
+private:
+ bool operator()(const QString &offset);
+
+private:
+ bool m_followSymlinks = true;
+ const IPathMatcher * m_blacklist = nullptr;
+ QDir m_src;
+ QDir m_dst;
+};
/**
* Delete a folder recursively
diff --git a/logic/InstanceList.cpp b/logic/InstanceList.cpp
index b791cc32..a8acdf05 100644
--- a/logic/InstanceList.cpp
+++ b/logic/InstanceList.cpp
@@ -38,6 +38,7 @@
#include "ftb/FTBPlugin.h"
#include "NullInstance.h"
#include "FileSystem.h"
+#include "pathmatcher/RegexpMatcher.h"
const static int GROUP_FILE_FORMAT_VERSION = 1;
@@ -486,9 +487,18 @@ InstanceList::InstCreateError
InstanceList::copyInstance(InstancePtr &newInstance, InstancePtr &oldInstance, const QString &instDir, bool copySaves)
{
QDir rootDir(instDir);
+ std::unique_ptr<IPathMatcher> matcher;
+ if(!copySaves)
+ {
+ auto matcherReal = new RegexpMatcher("[.]?minecraft/saves");
+ matcherReal->caseSensitive(false);
+ matcher.reset(matcherReal);
+ }
qDebug() << instDir.toUtf8();
- if (!FS::copyPath(oldInstance->instanceRoot(), instDir, false))
+ FS::copy folderCopy(oldInstance->instanceRoot(), instDir);
+ folderCopy.followSymlinks(false).blacklist(matcher.get());
+ if (!folderCopy())
{
FS::deletePath(instDir);
return InstanceList::CantCreateDir;
diff --git a/logic/minecraft/Mod.cpp b/logic/minecraft/Mod.cpp
index 879ca195..9b9f76f9 100644
--- a/logic/minecraft/Mod.cpp
+++ b/logic/minecraft/Mod.cpp
@@ -278,7 +278,7 @@ bool Mod::replace(Mod &with)
}
if (t == MOD_FOLDER)
{
- success = FS::copyPath(with.m_file.filePath(), m_file.path());
+ success = FS::copy(with.m_file.filePath(), m_file.path())();
}
if (success)
{
diff --git a/logic/minecraft/ModList.cpp b/logic/minecraft/ModList.cpp
index 60f8b012..07affb72 100644
--- a/logic/minecraft/ModList.cpp
+++ b/logic/minecraft/ModList.cpp
@@ -286,7 +286,7 @@ bool ModList::installMod(const QFileInfo &filename, int index)
QString from = filename.filePath();
QString to = FS::PathCombine(m_dir.path(), filename.fileName());
- if (!FS::copyPath(from, to))
+ if (!FS::copy(from, to)())
return false;
m.repath(to);
beginInsertRows(QModelIndex(), index, index);
diff --git a/logic/minecraft/World.cpp b/logic/minecraft/World.cpp
index e4734556..6081a8ec 100644
--- a/logic/minecraft/World.cpp
+++ b/logic/minecraft/World.cpp
@@ -197,7 +197,7 @@ bool World::install(const QString &to, const QString &name)
else if(m_containerFile.isDir())
{
QString from = m_containerFile.filePath();
- ok = FS::copyPath(from, finalPath);
+ ok = FS::copy(from, finalPath)();
}
if(ok && !name.isEmpty() && m_actualName != name)
@@ -350,7 +350,7 @@ bool World::replace(World &with)
{
if (!destroy())
return false;
- bool success = FS::copyPath(with.m_containerFile.filePath(), m_containerFile.path());
+ bool success = FS::copy(with.m_containerFile.filePath(), m_containerFile.path())();
if (success)
{
m_folderName = with.m_folderName;
diff --git a/logic/pathmatcher/IPathMatcher.h b/logic/pathmatcher/IPathMatcher.h
index 806a750a..1d410947 100644
--- a/logic/pathmatcher/IPathMatcher.h
+++ b/logic/pathmatcher/IPathMatcher.h
@@ -8,5 +8,5 @@ public:
public:
virtual ~IPathMatcher(){};
- virtual bool matches(const QString &string) = 0;
+ virtual bool matches(const QString &string) const = 0;
};
diff --git a/logic/pathmatcher/MultiMatcher.h b/logic/pathmatcher/MultiMatcher.h
index e018967c..91f70aa4 100644
--- a/logic/pathmatcher/MultiMatcher.h
+++ b/logic/pathmatcher/MultiMatcher.h
@@ -15,7 +15,7 @@ public:
return *this;
}
- virtual bool matches(const QString &string) override
+ virtual bool matches(const QString &string) const override
{
for(auto iter: m_matchers)
{
diff --git a/logic/pathmatcher/RegexpMatcher.h b/logic/pathmatcher/RegexpMatcher.h
index f3cf90b1..da552123 100644
--- a/logic/pathmatcher/RegexpMatcher.h
+++ b/logic/pathmatcher/RegexpMatcher.h
@@ -5,13 +5,26 @@ class RegexpMatcher : public IPathMatcher
{
public:
virtual ~RegexpMatcher() {};
- RegexpMatcher(QString regexp)
+ RegexpMatcher(const QString &regexp)
{
m_regexp.setPattern(regexp);
m_onlyFilenamePart = !regexp.contains('/');
}
- virtual bool matches(const QString &string) override
+ RegexpMatcher &caseSensitive(bool cs = true)
+ {
+ if(cs)
+ {
+ m_regexp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
+ }
+ else
+ {
+ m_regexp.setPatternOptions(QRegularExpression::NoPatternOption);
+ }
+ return *this;
+ }
+
+ virtual bool matches(const QString &string) const override
{
if(m_onlyFilenamePart)
{