mirror of
https://github.com/MultiMC/MultiMC5.git
synced 2024-12-24 12:14:30 +00:00
Working on legacy support, incomplete.
This commit is contained in:
parent
ff33d4a1a4
commit
77e8066542
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,3 +7,4 @@ CMakeLists.txt.user
|
|||||||
build
|
build
|
||||||
resources/CMakeFiles
|
resources/CMakeFiles
|
||||||
resources/MultiMCLauncher.jar
|
resources/MultiMCLauncher.jar
|
||||||
|
*~
|
||||||
|
@ -28,6 +28,8 @@ BaseUpdate.h
|
|||||||
BaseInstance.h
|
BaseInstance.h
|
||||||
BaseInstance_p.h
|
BaseInstance_p.h
|
||||||
MinecraftProcess.h
|
MinecraftProcess.h
|
||||||
|
Mod.h
|
||||||
|
ModList.h
|
||||||
|
|
||||||
# network stuffs
|
# network stuffs
|
||||||
net/DownloadJob.h
|
net/DownloadJob.h
|
||||||
@ -38,6 +40,7 @@ net/NetWorker.h
|
|||||||
LegacyInstance.h
|
LegacyInstance.h
|
||||||
LegacyInstance_p.h
|
LegacyInstance_p.h
|
||||||
LegacyUpdate.h
|
LegacyUpdate.h
|
||||||
|
LegacyForge.h
|
||||||
|
|
||||||
# 1.6 instances
|
# 1.6 instances
|
||||||
OneSixAssets.h
|
OneSixAssets.h
|
||||||
@ -68,6 +71,8 @@ InstanceFactory.cpp
|
|||||||
BaseUpdate.cpp
|
BaseUpdate.cpp
|
||||||
BaseInstance.cpp
|
BaseInstance.cpp
|
||||||
MinecraftProcess.cpp
|
MinecraftProcess.cpp
|
||||||
|
Mod.cpp
|
||||||
|
ModList.cpp
|
||||||
|
|
||||||
# network stuffs
|
# network stuffs
|
||||||
net/NetWorker.cpp
|
net/NetWorker.cpp
|
||||||
@ -76,6 +81,7 @@ net/DownloadJob.cpp
|
|||||||
# legacy instances
|
# legacy instances
|
||||||
LegacyInstance.cpp
|
LegacyInstance.cpp
|
||||||
LegacyUpdate.cpp
|
LegacyUpdate.cpp
|
||||||
|
LegacyForge.cpp
|
||||||
|
|
||||||
# 1.6 instances
|
# 1.6 instances
|
||||||
OneSixAssets.cpp
|
OneSixAssets.cpp
|
||||||
|
57
backend/LegacyForge.cpp
Normal file
57
backend/LegacyForge.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2012 MultiMC Contributors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "LegacyForge.h"
|
||||||
|
|
||||||
|
MinecraftForge::MinecraftForge ( const QString& file ) : Mod ( file )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
bool MinecraftForge::FixVersionIfNeeded ( QString newVersion )
|
||||||
|
{/*
|
||||||
|
wxString reportedVersion = GetModVersion();
|
||||||
|
if(reportedVersion == "..." || reportedVersion.empty())
|
||||||
|
{
|
||||||
|
std::auto_ptr<wxFFileInputStream> in(new wxFFileInputStream("forge.zip"));
|
||||||
|
wxTempFileOutputStream out("forge.zip");
|
||||||
|
wxTextOutputStream textout(out);
|
||||||
|
wxZipInputStream inzip(*in);
|
||||||
|
wxZipOutputStream outzip(out);
|
||||||
|
std::auto_ptr<wxZipEntry> entry;
|
||||||
|
// preserve metadata
|
||||||
|
outzip.CopyArchiveMetaData(inzip);
|
||||||
|
// copy all entries
|
||||||
|
while (entry.reset(inzip.GetNextEntry()), entry.get() != NULL)
|
||||||
|
if (!outzip.CopyEntry(entry.release(), inzip))
|
||||||
|
return false;
|
||||||
|
// release last entry
|
||||||
|
in.reset();
|
||||||
|
outzip.PutNextEntry("forgeversion.properties");
|
||||||
|
|
||||||
|
wxStringTokenizer tokenizer(newVersion,".");
|
||||||
|
wxString verFile;
|
||||||
|
verFile << wxString("forge.major.number=") << tokenizer.GetNextToken() << "\n";
|
||||||
|
verFile << wxString("forge.minor.number=") << tokenizer.GetNextToken() << "\n";
|
||||||
|
verFile << wxString("forge.revision.number=") << tokenizer.GetNextToken() << "\n";
|
||||||
|
verFile << wxString("forge.build.number=") << tokenizer.GetNextToken() << "\n";
|
||||||
|
auto buf = verFile.ToUTF8();
|
||||||
|
outzip.Write(buf.data(), buf.length());
|
||||||
|
// check if we succeeded
|
||||||
|
return inzip.Eof() && outzip.Close() && out.Commit();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
25
backend/LegacyForge.h
Normal file
25
backend/LegacyForge.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2012 MultiMC Contributors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "Mod.h"
|
||||||
|
|
||||||
|
class MinecraftForge : public Mod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MinecraftForge ( const QString& file );
|
||||||
|
bool FixVersionIfNeeded(QString newVersion);
|
||||||
|
};
|
@ -212,6 +212,13 @@ void LegacyUpdate::jarStart()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nuke the backup file, we are replacing the base jar anyway
|
||||||
|
QFile mc_backup(inst->mcBackup());
|
||||||
|
if (mc_backup.exists())
|
||||||
|
{
|
||||||
|
mc_backup.remove();
|
||||||
|
}
|
||||||
|
|
||||||
// Get a pointer to the version object that corresponds to the instance's version.
|
// Get a pointer to the version object that corresponds to the instance's version.
|
||||||
auto targetVersion = MinecraftVersionList::getMainList().findVersion(intended_version_id);
|
auto targetVersion = MinecraftVersionList::getMainList().findVersion(intended_version_id);
|
||||||
|
|
||||||
@ -260,3 +267,115 @@ void LegacyUpdate::jarFailed()
|
|||||||
// bad, bad
|
// bad, bad
|
||||||
emitFailed("Failed to download the minecraft jar. Try again later.");
|
emitFailed("Failed to download the minecraft jar. Try again later.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LegacyUpdate::ModTheJar()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
LegacyInstance * inst = (LegacyInstance *) m_inst;
|
||||||
|
// Get the mod list
|
||||||
|
auto modList = inst->getJarModList();
|
||||||
|
|
||||||
|
QFileInfo mcBin(inst->binDir());
|
||||||
|
QFileInfo mcJar(inst->mcJar());
|
||||||
|
QFileInfo mcBackup(inst->mcBackup());
|
||||||
|
|
||||||
|
// Nothing to do if there are no jar mods to install, no backup and just the mc jar
|
||||||
|
if(mcJar.isFile() && !mcBackup.exists() && modList->empty())
|
||||||
|
{
|
||||||
|
inst->setShouldRebuild(false);
|
||||||
|
emitSucceeded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStatus("Installing mods - backing up minecraft.jar...");
|
||||||
|
if (!mcBackup.exists() && !QFile::copy(mcJar.absoluteFilePath(), mcBackup.absoluteFilePath()) )
|
||||||
|
{
|
||||||
|
emitFailed("Failed to back up minecraft.jar");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mcJar.isFile() && !QFile::remove(mcJar.absoluteFilePath()))
|
||||||
|
{
|
||||||
|
emitFailed("Failed to delete old minecraft.jar");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStatus("Installing mods - Opening minecraft.jar");
|
||||||
|
|
||||||
|
wxFFileOutputStream jarStream(mcJar.absoluteFilePath());
|
||||||
|
wxZipOutputStream zipOut(jarStream);
|
||||||
|
|
||||||
|
// Files already added to the jar.
|
||||||
|
// These files will be skipped.
|
||||||
|
QSet<QString> addedFiles;
|
||||||
|
|
||||||
|
// Modify the jar
|
||||||
|
setStatus("Installing mods - Adding mod files...");
|
||||||
|
for (ModList::const_reverse_iterator iter = modList->rbegin(); iter != modList->rend(); iter++)
|
||||||
|
{
|
||||||
|
wxFileName modFileName = iter->GetFileName();
|
||||||
|
setStatus("Installing mods - Adding " + modFileName.GetFullName());
|
||||||
|
if (iter->GetModType() == Mod::ModType::MOD_ZIPFILE)
|
||||||
|
{
|
||||||
|
wxFFileInputStream modStream(modFileName.GetFullPath());
|
||||||
|
wxZipInputStream zipStream(modStream);
|
||||||
|
std::unique_ptr<wxZipEntry> entry;
|
||||||
|
while (entry.reset(zipStream.GetNextEntry()), entry.get() != NULL)
|
||||||
|
{
|
||||||
|
if (entry->IsDir())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wxString name = entry->GetName();
|
||||||
|
if (addedFiles.count(name) == 0)
|
||||||
|
{
|
||||||
|
if (!zipOut.CopyEntry(entry.release(), zipStream))
|
||||||
|
break;
|
||||||
|
addedFiles.insert(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxFileName destFileName = modFileName;
|
||||||
|
destFileName.MakeRelativeTo(m_inst->GetInstModsDir().GetFullPath());
|
||||||
|
wxString destFile = destFileName.GetFullPath();
|
||||||
|
|
||||||
|
if (addedFiles.count(destFile) == 0)
|
||||||
|
{
|
||||||
|
wxFFileInputStream input(modFileName.GetFullPath());
|
||||||
|
zipOut.PutNextEntry(destFile);
|
||||||
|
zipOut.Write(input);
|
||||||
|
|
||||||
|
addedFiles.insert(destFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
wxFFileInputStream inStream(mcBackup.GetFullPath());
|
||||||
|
wxZipInputStream zipIn(inStream);
|
||||||
|
|
||||||
|
std::auto_ptr<wxZipEntry> entry;
|
||||||
|
while (entry.reset(zipIn.GetNextEntry()), entry.get() != NULL)
|
||||||
|
{
|
||||||
|
wxString name = entry->GetName();
|
||||||
|
|
||||||
|
if (!name.Matches("META-INF*") &&
|
||||||
|
addedFiles.count(name) == 0)
|
||||||
|
{
|
||||||
|
if (!zipOut.CopyEntry(entry.release(), zipIn))
|
||||||
|
break;
|
||||||
|
addedFiles.insert(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recompress the jar
|
||||||
|
TaskStep(); // STEP 3
|
||||||
|
SetStatus(_("Installing mods - Recompressing jar..."));
|
||||||
|
|
||||||
|
inst->SetNeedsRebuild(false);
|
||||||
|
inst->UpdateVersion(true);
|
||||||
|
return (ExitCode)1;
|
||||||
|
*/
|
||||||
|
}
|
@ -44,6 +44,8 @@ private slots:
|
|||||||
void jarFailed();
|
void jarFailed();
|
||||||
|
|
||||||
void extractLwjgl();
|
void extractLwjgl();
|
||||||
|
|
||||||
|
void ModTheJar();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QSharedPointer<QNetworkReply> m_reply;
|
QSharedPointer<QNetworkReply> m_reply;
|
||||||
|
264
backend/Mod.cpp
Normal file
264
backend/Mod.cpp
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2012 MultiMC Contributors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Mod.h"
|
||||||
|
#include <pathutils.h>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
Mod::Mod( const QFileInfo& file )
|
||||||
|
{
|
||||||
|
repath(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mod::repath ( const QFileInfo& file )
|
||||||
|
{
|
||||||
|
m_file = file;
|
||||||
|
m_name = file.baseName();
|
||||||
|
m_id = file.fileName();
|
||||||
|
|
||||||
|
m_type = Mod::MOD_UNKNOWN;
|
||||||
|
if (m_file.isDir())
|
||||||
|
m_type = MOD_FOLDER;
|
||||||
|
else if (m_file.isFile())
|
||||||
|
{
|
||||||
|
QString ext = m_file.suffix().toLower();
|
||||||
|
if (ext == "zip" || ext == "jar")
|
||||||
|
m_type = MOD_ZIPFILE;
|
||||||
|
else
|
||||||
|
m_type = MOD_SINGLEFILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
switch (modType)
|
||||||
|
{
|
||||||
|
case MOD_ZIPFILE:
|
||||||
|
{
|
||||||
|
wxFFileInputStream fileIn(modFile.GetFullPath());
|
||||||
|
wxZipInputStream zipIn(fileIn);
|
||||||
|
|
||||||
|
std::auto_ptr<wxZipEntry> entry;
|
||||||
|
|
||||||
|
bool is_forge = false;
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
entry.reset(zipIn.GetNextEntry());
|
||||||
|
if (entry.get() == nullptr)
|
||||||
|
break;
|
||||||
|
if(entry->GetInternalName().EndsWith("mcmod.info"))
|
||||||
|
break;
|
||||||
|
if(entry->GetInternalName().EndsWith("forgeversion.properties"))
|
||||||
|
{
|
||||||
|
is_forge = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.get() != nullptr)
|
||||||
|
{
|
||||||
|
// Read the info file into text
|
||||||
|
wxString infoFileData;
|
||||||
|
wxStringOutputStream stringOut(&infoFileData);
|
||||||
|
zipIn.Read(stringOut);
|
||||||
|
if(!is_forge)
|
||||||
|
ReadModInfoData(infoFileData);
|
||||||
|
else
|
||||||
|
ReadForgeInfoData(infoFileData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MOD_FOLDER:
|
||||||
|
{
|
||||||
|
wxString infoFile = Path::Combine(modFile, "mcmod.info");
|
||||||
|
if (!wxFileExists(infoFile))
|
||||||
|
{
|
||||||
|
infoFile = wxEmptyString;
|
||||||
|
|
||||||
|
wxDir modDir(modFile.GetFullPath());
|
||||||
|
|
||||||
|
if (!modDir.IsOpened())
|
||||||
|
{
|
||||||
|
wxLogError(_("Can't fine mod info file. Failed to open mod folder."));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString currentFile;
|
||||||
|
if (modDir.GetFirst(¤tFile))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (currentFile.EndsWith("mcmod.info"))
|
||||||
|
{
|
||||||
|
infoFile = Path::Combine(modFile.GetFullPath(), currentFile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (modDir.GetNext(¤tFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (infoFile != wxEmptyString && wxFileExists(infoFile))
|
||||||
|
{
|
||||||
|
wxString infoStr;
|
||||||
|
wxFFileInputStream fileIn(infoFile);
|
||||||
|
wxStringOutputStream strOut(&infoStr);
|
||||||
|
fileIn.Read(strOut);
|
||||||
|
ReadModInfoData(infoStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
void ReadModInfoData(QString info)
|
||||||
|
{
|
||||||
|
using namespace boost::property_tree;
|
||||||
|
|
||||||
|
// Read the data
|
||||||
|
ptree ptRoot;
|
||||||
|
|
||||||
|
std::stringstream stringIn(cStr(info));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
read_json(stringIn, ptRoot);
|
||||||
|
|
||||||
|
ptree pt = ptRoot.get_child(ptRoot.count("modlist") == 1 ? "modlist" : "").begin()->second;
|
||||||
|
|
||||||
|
modID = wxStr(pt.get<std::string>("modid"));
|
||||||
|
modName = wxStr(pt.get<std::string>("name"));
|
||||||
|
modVersion = wxStr(pt.get<std::string>("version"));
|
||||||
|
}
|
||||||
|
catch (json_parser_error e)
|
||||||
|
{
|
||||||
|
// Silently fail...
|
||||||
|
}
|
||||||
|
catch (ptree_error e)
|
||||||
|
{
|
||||||
|
// Silently fail...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// FIXME: abstraction violated.
|
||||||
|
/*
|
||||||
|
void Mod::ReadForgeInfoData(QString infoFileData)
|
||||||
|
{
|
||||||
|
using namespace boost::property_tree;
|
||||||
|
|
||||||
|
// Read the data
|
||||||
|
ptree ptRoot;
|
||||||
|
modName = "Minecraft Forge";
|
||||||
|
modID = "Forge";
|
||||||
|
std::stringstream stringIn(cStr(infoFileData));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
read_ini(stringIn, ptRoot);
|
||||||
|
wxString major, minor, revision, build;
|
||||||
|
// BUG: boost property tree is bad. won't let us get a key with dots in it
|
||||||
|
// Likely cause = treating the dots as path separators.
|
||||||
|
for (auto iter = ptRoot.begin(); iter != ptRoot.end(); iter++)
|
||||||
|
{
|
||||||
|
auto &item = *iter;
|
||||||
|
std::string key = item.first;
|
||||||
|
std::string value = item.second.get_value<std::string>();
|
||||||
|
if(key == "forge.major.number")
|
||||||
|
major = value;
|
||||||
|
if(key == "forge.minor.number")
|
||||||
|
minor = value;
|
||||||
|
if(key == "forge.revision.number")
|
||||||
|
revision = value;
|
||||||
|
if(key == "forge.build.number")
|
||||||
|
build = value;
|
||||||
|
}
|
||||||
|
modVersion.Empty();
|
||||||
|
modVersion << major << "." << minor << "." << revision << "." << build;
|
||||||
|
}
|
||||||
|
catch (json_parser_error e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what();
|
||||||
|
}
|
||||||
|
catch (ptree_error e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Mod::replace ( Mod& with )
|
||||||
|
{
|
||||||
|
if(!destroy())
|
||||||
|
return false;
|
||||||
|
bool success = false;
|
||||||
|
auto t = with.type();
|
||||||
|
if(t == MOD_ZIPFILE || t == MOD_SINGLEFILE)
|
||||||
|
{
|
||||||
|
success = QFile::copy(with.m_file.filePath(), m_file.path());
|
||||||
|
}
|
||||||
|
if(t == MOD_FOLDER)
|
||||||
|
{
|
||||||
|
success = copyPath(with.m_file.filePath(), m_file.path());
|
||||||
|
}
|
||||||
|
if(success)
|
||||||
|
{
|
||||||
|
m_id = with.m_id;
|
||||||
|
m_mcversion = with.m_mcversion;
|
||||||
|
m_type = with.m_type;
|
||||||
|
m_name = with.m_name;
|
||||||
|
m_version = with.m_version;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mod::destroy()
|
||||||
|
{
|
||||||
|
if(m_type == MOD_FOLDER)
|
||||||
|
{
|
||||||
|
QDir d(m_file.filePath());
|
||||||
|
if(d.removeRecursively())
|
||||||
|
{
|
||||||
|
m_type = MOD_UNKNOWN;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (m_type == MOD_SINGLEFILE || m_type == MOD_ZIPFILE)
|
||||||
|
{
|
||||||
|
QFile f(m_file.filePath());
|
||||||
|
if(f.remove())
|
||||||
|
{
|
||||||
|
m_type = MOD_UNKNOWN;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString Mod::version() const
|
||||||
|
{
|
||||||
|
switch(type())
|
||||||
|
{
|
||||||
|
case MOD_ZIPFILE:
|
||||||
|
return m_version;
|
||||||
|
case MOD_FOLDER:
|
||||||
|
return "Folder";
|
||||||
|
case MOD_SINGLEFILE:
|
||||||
|
return "File";
|
||||||
|
}
|
||||||
|
}
|
69
backend/Mod.h
Normal file
69
backend/Mod.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2012 MultiMC Contributors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
class Mod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum ModType
|
||||||
|
{
|
||||||
|
MOD_UNKNOWN, //!< Indicates an unspecified mod type.
|
||||||
|
MOD_ZIPFILE, //!< The mod is a zip file containing the mod's class files.
|
||||||
|
MOD_SINGLEFILE, //!< The mod is a single file (not a zip file).
|
||||||
|
MOD_FOLDER, //!< The mod is in a folder on the filesystem.
|
||||||
|
};
|
||||||
|
|
||||||
|
Mod(const QFileInfo &file);
|
||||||
|
|
||||||
|
QFileInfo filename() const { return m_file; }
|
||||||
|
QString id() const { return m_id; }
|
||||||
|
ModType type() const { return m_type; }
|
||||||
|
QString mcversion() const;
|
||||||
|
bool valid() {return m_type != MOD_UNKNOWN;}
|
||||||
|
|
||||||
|
QString version() const;
|
||||||
|
|
||||||
|
// delete all the files of this mod
|
||||||
|
bool destroy();
|
||||||
|
// replace this mod with a copy of the other
|
||||||
|
bool replace(Mod & with);
|
||||||
|
// change the mod's filesystem path (used by mod lists for *MAGIC* purposes)
|
||||||
|
void repath(const QFileInfo &file);
|
||||||
|
|
||||||
|
|
||||||
|
bool operator ==(const Mod &other) const
|
||||||
|
{
|
||||||
|
return filename() == other.filename();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
//FIXME: what do do with those? HMM...
|
||||||
|
/*
|
||||||
|
void ReadModInfoData(QString info);
|
||||||
|
void ReadForgeInfoData(QString infoFileData);
|
||||||
|
*/
|
||||||
|
|
||||||
|
QFileInfo m_file;
|
||||||
|
QString m_id;
|
||||||
|
QString m_name;
|
||||||
|
QString m_version;
|
||||||
|
QString m_mcversion;
|
||||||
|
|
||||||
|
ModType m_type;
|
||||||
|
};
|
418
backend/ModList.cpp
Normal file
418
backend/ModList.cpp
Normal file
@ -0,0 +1,418 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2012 MultiMC Contributors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ModList.h"
|
||||||
|
#include "LegacyInstance.h"
|
||||||
|
#include <pathutils.h>
|
||||||
|
|
||||||
|
ModList::ModList ( const QString& dir ) : QObject(), m_dir(dir)
|
||||||
|
{
|
||||||
|
m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs | QDir::NoSymLinks);
|
||||||
|
m_dir.setSorting(QDir::Name);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModList::update()
|
||||||
|
{
|
||||||
|
if (!isValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool initial = mods.empty();
|
||||||
|
|
||||||
|
bool listChanged = false;
|
||||||
|
|
||||||
|
auto list = m_dir.entryInfoList();
|
||||||
|
for(auto entry: list)
|
||||||
|
{
|
||||||
|
Mod mod(entry);
|
||||||
|
if (initial || !mods.contains(mod))
|
||||||
|
{
|
||||||
|
mods.push_back(mod);
|
||||||
|
listChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return listChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModList::isValid()
|
||||||
|
{
|
||||||
|
return m_dir.exists() && m_dir.isReadable();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModList::installMod ( const QFileInfo& filename, size_t index )
|
||||||
|
{
|
||||||
|
if(!filename.exists() || !filename.isReadable())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Mod m(filename);
|
||||||
|
if(!m.valid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// if it's already there, replace the original mod (in place)
|
||||||
|
int idx = mods.indexOf(m);
|
||||||
|
if(idx != -1)
|
||||||
|
{
|
||||||
|
if(mods[idx].replace(m))
|
||||||
|
{
|
||||||
|
emit changed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto type = m.type();
|
||||||
|
if(type == Mod::MOD_UNKNOWN)
|
||||||
|
return false;
|
||||||
|
if(type == Mod::MOD_SINGLEFILE || type == Mod::MOD_ZIPFILE)
|
||||||
|
{
|
||||||
|
QString newpath = PathCombine(m_dir.path(), filename.fileName());
|
||||||
|
if(!QFile::copy(filename.filePath(), newpath))
|
||||||
|
return false;
|
||||||
|
m.repath(newpath);
|
||||||
|
mods.append(m);
|
||||||
|
emit changed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(type == Mod::MOD_FOLDER)
|
||||||
|
{
|
||||||
|
QString newpath = PathCombine(m_dir.path(), filename.fileName());
|
||||||
|
if(!copyPath(filename.filePath(), newpath))
|
||||||
|
return false;
|
||||||
|
m.repath(newpath);
|
||||||
|
mods.append(m);
|
||||||
|
emit changed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModList::deleteMod ( size_t index )
|
||||||
|
{
|
||||||
|
if(index >= mods.size())
|
||||||
|
return false;
|
||||||
|
Mod & m = mods[index];
|
||||||
|
if(m.destroy())
|
||||||
|
{
|
||||||
|
mods.erase(mods.begin() + index);
|
||||||
|
emit changed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
ModList::ModList(const QString &dir)
|
||||||
|
: modsFolder(dir)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModList::update(bool quickLoad)
|
||||||
|
{
|
||||||
|
bool listChanged = false;
|
||||||
|
|
||||||
|
// Check for mods in the list whose files do not exist and remove them from the list.
|
||||||
|
// If doing a quickLoad, erase the whole list.
|
||||||
|
for (size_t i = 0; i < size(); i++)
|
||||||
|
{
|
||||||
|
if (quickLoad || !at(i).GetFileName().FileExists())
|
||||||
|
{
|
||||||
|
erase(begin() + i);
|
||||||
|
i--;
|
||||||
|
listChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add any mods in the mods folder that aren't already in the list.
|
||||||
|
if (LoadModListFromDir(QString(), quickLoad))
|
||||||
|
listChanged = true;
|
||||||
|
|
||||||
|
return listChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModList::LoadModListFromDir(const QString& loadFrom, bool quickLoad)
|
||||||
|
{
|
||||||
|
QString dir(loadFrom.isEmpty() ? modsFolder : loadFrom);
|
||||||
|
|
||||||
|
QDir modDir(dir);
|
||||||
|
if (!modDir.exists())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool listChanged = false;
|
||||||
|
|
||||||
|
auto list = modDir.entryInfoList(QDir::Readable|QDir::NoDotAndDotDot, QDir::Name);
|
||||||
|
for(auto currentFile: list)
|
||||||
|
{
|
||||||
|
if (currentFile.isFile())
|
||||||
|
{
|
||||||
|
if (quickLoad || FindByFilename(currentFile.absoluteFilePath()) == nullptr)
|
||||||
|
{
|
||||||
|
Mod mod(currentFile.absoluteFilePath());
|
||||||
|
push_back(mod);
|
||||||
|
listChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (currentFile.isDir())
|
||||||
|
{
|
||||||
|
if (LoadModListFromDir(currentFile.absoluteFilePath()))
|
||||||
|
listChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return listChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mod *ModList::FindByFilename(const QString& filename)
|
||||||
|
{
|
||||||
|
// Search the list for a mod with the given filename.
|
||||||
|
for (auto iter = begin(); iter != end(); ++iter)
|
||||||
|
{
|
||||||
|
if (iter->GetFileName() == QFileInfo(filename))
|
||||||
|
return &(*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If nothing is found, return nullptr.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ModList::FindIndexByFilename(const QString& filename)
|
||||||
|
{
|
||||||
|
// Search the list for a mod with the given filename.
|
||||||
|
int i = 0;
|
||||||
|
for (auto iter = begin(); iter != end(); ++iter, i++)
|
||||||
|
{
|
||||||
|
if (iter->GetFileName() == QFileInfo(filename))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If nothing is found, return nullptr.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mod* ModList::FindByID(const QString& modID, const QString& modVersion)
|
||||||
|
{
|
||||||
|
// Search the list for a mod that matches
|
||||||
|
for (auto iter = begin(); iter != end(); ++iter)
|
||||||
|
{
|
||||||
|
QString ID = iter->GetModID();
|
||||||
|
QString version = iter->GetModVersion();
|
||||||
|
if ( ID == modID && version == modVersion)
|
||||||
|
return &(*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If nothing is found, return nullptr.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModList::LoadFromFile(const QString& file)
|
||||||
|
{
|
||||||
|
if (!wxFileExists(file))
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxFFileInputStream inputStream(file);
|
||||||
|
wxArrayString modListFile = ReadAllLines(inputStream);
|
||||||
|
|
||||||
|
for (wxArrayString::iterator iter = modListFile.begin(); iter != modListFile.end(); iter++)
|
||||||
|
{
|
||||||
|
// Normalize the path to the instMods dir.
|
||||||
|
wxFileName modFile(*iter);
|
||||||
|
modFile.Normalize(wxPATH_NORM_ALL, modsFolder);
|
||||||
|
modFile.MakeRelativeTo();
|
||||||
|
// if the file is gone, do not load it
|
||||||
|
if(!modFile.Exists())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FindByFilename(modFile.GetFullPath()) == nullptr)
|
||||||
|
{
|
||||||
|
push_back(Mod(modFile));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModList::SaveToFile(const QString& file)
|
||||||
|
{
|
||||||
|
QString text;
|
||||||
|
for (iterator iter = begin(); iter != end(); ++iter)
|
||||||
|
{
|
||||||
|
wxFileName modFile = iter->GetFileName();
|
||||||
|
modFile.MakeRelativeTo(modsFolder);
|
||||||
|
text.append(modFile.GetFullPath());
|
||||||
|
text.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
wxTempFileOutputStream out(file);
|
||||||
|
WriteAllText(out, text);
|
||||||
|
out.Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModList::InsertMod(size_t index, const QString &filename, const QString& saveToFile)
|
||||||
|
{
|
||||||
|
QFileInfo source(filename);
|
||||||
|
QFileInfo dest(PathCombine(modsFolder, source.fileName()));
|
||||||
|
|
||||||
|
if (source != dest)
|
||||||
|
{
|
||||||
|
QFile::copy(source.absoluteFilePath(), dest.absoluteFilePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
int oldIndex = FindIndexByFilename(dest.absoluteFilePath());
|
||||||
|
|
||||||
|
if (oldIndex != -1)
|
||||||
|
{
|
||||||
|
erase(begin() + oldIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index >= size())
|
||||||
|
push_back(Mod(dest));
|
||||||
|
else
|
||||||
|
insert(begin() + index, Mod(dest));
|
||||||
|
|
||||||
|
if (!saveToFile.isEmpty())
|
||||||
|
SaveToFile(saveToFile);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModList::DeleteMod(size_t index, const QString& saveToFile)
|
||||||
|
{
|
||||||
|
Mod *mod = &at(index);
|
||||||
|
if(mod->GetModType() == Mod::MOD_FOLDER)
|
||||||
|
{
|
||||||
|
QDir dir(mod->GetFileName().absoluteFilePath());
|
||||||
|
if(dir.removeRecursively())
|
||||||
|
{
|
||||||
|
erase(begin() + index);
|
||||||
|
|
||||||
|
if (!saveToFile.isEmpty())
|
||||||
|
SaveToFile(saveToFile);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// wxLogError(_("Failed to delete mod."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (QFile(mod->GetFileName().absoluteFilePath()).remove())
|
||||||
|
{
|
||||||
|
erase(begin() + index);
|
||||||
|
|
||||||
|
if (!saveToFile.isEmpty())
|
||||||
|
SaveToFile(saveToFile);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// wxLogError(_("Failed to delete mod."));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JarModList::InsertMod(size_t index, const QString &filename, const QString& saveToFile)
|
||||||
|
{
|
||||||
|
QString saveFile = saveToFile;
|
||||||
|
if (saveToFile.isEmpty())
|
||||||
|
saveFile = m_inst->GetModListFile().GetFullPath();
|
||||||
|
|
||||||
|
if (ModList::InsertMod(index, filename, saveFile))
|
||||||
|
{
|
||||||
|
m_inst->setLWJGLVersion(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JarModList::DeleteMod(size_t index, const QString& saveToFile)
|
||||||
|
{
|
||||||
|
QString saveFile = saveToFile;
|
||||||
|
if (saveToFile.IsEmpty())
|
||||||
|
saveFile = m_inst->GetModListFile().GetFullPath();
|
||||||
|
|
||||||
|
if (ModList::DeleteMod(index, saveFile))
|
||||||
|
{
|
||||||
|
m_inst->SetNeedsRebuild();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JarModList::UpdateModList(bool quickLoad)
|
||||||
|
{
|
||||||
|
if (ModList::UpdateModList(quickLoad))
|
||||||
|
{
|
||||||
|
m_inst->SetNeedsRebuild();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FolderModList::LoadModListFromDir(const QString& loadFrom, bool quickLoad)
|
||||||
|
{
|
||||||
|
QString dir(loadFrom.IsEmpty() ? modsFolder : loadFrom);
|
||||||
|
|
||||||
|
if (!wxDirExists(dir))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool listChanged = false;
|
||||||
|
wxDir modDir(dir);
|
||||||
|
|
||||||
|
if (!modDir.IsOpened())
|
||||||
|
{
|
||||||
|
wxLogError(_("Failed to open directory: ") + dir);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString currentFile;
|
||||||
|
if (modDir.GetFirst(¤tFile))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
wxFileName modFile(Path::Combine(dir, currentFile));
|
||||||
|
|
||||||
|
if (wxFileExists(modFile.GetFullPath()) || wxDirExists(modFile.GetFullPath()))
|
||||||
|
{
|
||||||
|
if (quickLoad || FindByFilename(modFile.GetFullPath()) == nullptr)
|
||||||
|
{
|
||||||
|
Mod mod(modFile.GetFullPath());
|
||||||
|
push_back(mod);
|
||||||
|
listChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (modDir.GetNext(¤tFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
return listChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModNameSort (const Mod & i,const Mod & j)
|
||||||
|
{
|
||||||
|
if(i.GetModType() == j.GetModType())
|
||||||
|
return (i.GetName().toLower() < j.GetName().toLower());
|
||||||
|
return (i.GetModType() < j.GetModType());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FolderModList::UpdateModList ( bool quickLoad )
|
||||||
|
{
|
||||||
|
bool changed = ModList::UpdateModList(quickLoad);
|
||||||
|
std::sort(begin(),end(),ModNameSort);
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
*/
|
75
backend/ModList.h
Normal file
75
backend/ModList.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2012 MultiMC Contributors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class LegacyInstance;
|
||||||
|
class BaseInstance;
|
||||||
|
#include <QList>
|
||||||
|
#include <QString>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
#include "Mod.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A basic mod list.
|
||||||
|
* Backed by a folder.
|
||||||
|
*/
|
||||||
|
class ModList : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
ModList(const QString& dir = QString());
|
||||||
|
|
||||||
|
size_t size() { return mods.size(); };
|
||||||
|
Mod& operator[](size_t index) { return mods[index]; };
|
||||||
|
|
||||||
|
/// Reloads the mod list and returns true if the list changed.
|
||||||
|
virtual bool update();
|
||||||
|
|
||||||
|
/// Adds the given mod to the list at the given index.
|
||||||
|
virtual bool installMod(const QFileInfo& filename, size_t index = 0);
|
||||||
|
|
||||||
|
/// Deletes the mod at the given index.
|
||||||
|
virtual bool deleteMod(size_t index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* move the mod at index to the position N
|
||||||
|
* 0 is the beginning of the list, length() is the end of the list.
|
||||||
|
*/
|
||||||
|
virtual bool moveMod(size_t from, size_t to) { return false; };
|
||||||
|
|
||||||
|
virtual bool isValid();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
virtual void changed();
|
||||||
|
protected:
|
||||||
|
QDir m_dir;
|
||||||
|
QList<Mod> mods;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A jar mod list.
|
||||||
|
* Backed by a folder and a file which specifies the load order.
|
||||||
|
*/
|
||||||
|
class JarModList : public ModList
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
JarModList(const QString& dir, const QString& list_file, LegacyInstance * inst)
|
||||||
|
: ModList(dir), m_listfile(list_file), m_inst(inst) {}
|
||||||
|
|
||||||
|
virtual bool update();
|
||||||
|
virtual bool installMod(const QString &filename, size_t index);
|
||||||
|
virtual bool deleteMod(size_t index);
|
||||||
|
virtual bool moveMod(size_t from, size_t to);
|
||||||
|
protected:
|
||||||
|
QString m_listfile;
|
||||||
|
LegacyInstance * m_inst;
|
||||||
|
};
|
@ -92,12 +92,15 @@ void OneSixUpdate::versionFileFinished()
|
|||||||
{
|
{
|
||||||
QString version1 = PathCombine(inst_dir, "/version.json");
|
QString version1 = PathCombine(inst_dir, "/version.json");
|
||||||
ensurePathExists(version1);
|
ensurePathExists(version1);
|
||||||
|
// FIXME: detect errors here, download to a temp file, swap
|
||||||
QFile vfile1 (version1);
|
QFile vfile1 (version1);
|
||||||
vfile1.open(QIODevice::Truncate | QIODevice::WriteOnly );
|
vfile1.open(QIODevice::Truncate | QIODevice::WriteOnly );
|
||||||
vfile1.write(DlJob->m_data);
|
vfile1.write(DlJob->m_data);
|
||||||
vfile1.close();
|
vfile1.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the version is downloaded safely. update is 'done' at this point
|
||||||
|
m_inst->setShouldUpdate(false);
|
||||||
// save the version file in versions/$version/$version.json
|
// save the version file in versions/$version/$version.json
|
||||||
/*
|
/*
|
||||||
//QString version2 = QString("versions/") + version_id + "/" + version_id + ".json";
|
//QString version2 = QString("versions/") + version_id + "/" + version_id + ".json";
|
||||||
|
@ -31,4 +31,7 @@ LIBUTIL_EXPORT QString DirNameFromString(QString string, QString inDir = ".");
|
|||||||
|
|
||||||
LIBUTIL_EXPORT bool ensurePathExists(QString filenamepath);
|
LIBUTIL_EXPORT bool ensurePathExists(QString filenamepath);
|
||||||
|
|
||||||
|
LIBUTIL_EXPORT bool copyPath(QString src, QString dst);
|
||||||
|
|
||||||
|
|
||||||
#endif // PATHUTILS_H
|
#endif // PATHUTILS_H
|
||||||
|
@ -73,3 +73,22 @@ bool ensurePathExists(QString filenamepath)
|
|||||||
return (dir.mkpath ( a.path() ));
|
return (dir.mkpath ( a.path() ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool copyPath(QString src, QString dst)
|
||||||
|
{
|
||||||
|
QDir dir(src);
|
||||||
|
if (!dir.exists())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (QString d, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot))
|
||||||
|
{
|
||||||
|
QString dst_path = dst + QDir::separator() + d;
|
||||||
|
dir.mkpath(dst_path);
|
||||||
|
copyPath(src+ QDir::separator() + d, dst_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (QString f, dir.entryList(QDir::Files))
|
||||||
|
{
|
||||||
|
QFile::copy(src + QDir::separator() + f, dst + QDir::separator() + f);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user