LCOV - code coverage report
Current view: top level - source/ps - ModInstaller.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 0 51 0.0 %
Date: 2022-06-14 00:41:00 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /* Copyright (C) 2021 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "precompiled.h"
      19             : 
      20             : #include "ModInstaller.h"
      21             : 
      22             : #include "lib/file/vfs/vfs_util.h"
      23             : #include "lib/file/file_system.h"
      24             : #include "ps/CLogger.h"
      25             : #include "ps/Filesystem.h"
      26             : #include "ps/XML/Xeromyces.h"
      27             : #include "scriptinterface/ScriptInterface.h"
      28             : #include "scriptinterface/JSON.h"
      29             : 
      30             : #include <fstream>
      31             : 
      32           0 : CModInstaller::CModInstaller(const OsPath& modsdir, const OsPath& tempdir) :
      33           0 :     m_ModsDir(modsdir), m_TempDir(tempdir / "_modscache"), m_CacheDir("cache/")
      34             : {
      35           0 :     m_VFS = CreateVfs();
      36           0 :     CreateDirectories(m_TempDir, 0700);
      37           0 : }
      38             : 
      39           0 : CModInstaller::~CModInstaller()
      40             : {
      41           0 :     m_VFS.reset();
      42           0 :     DeleteDirectory(m_TempDir);
      43           0 : }
      44             : 
      45           0 : CModInstaller::ModInstallationResult CModInstaller::Install(
      46             :     const OsPath& mod,
      47             :     const std::shared_ptr<ScriptContext>& scriptContext,
      48             :     bool keepFile)
      49             : {
      50           0 :     const OsPath modTemp = m_TempDir / mod.Basename() / mod.Filename().ChangeExtension(L".zip");
      51           0 :     CreateDirectories(modTemp.Parent(), 0700);
      52             : 
      53           0 :     if (keepFile)
      54             :     {
      55           0 :         if (CopyFile(mod, modTemp, true) != INFO::OK)
      56             :         {
      57           0 :             LOGERROR("Failed to copy '%s' to '%s'", mod.string8().c_str(), modTemp.string8().c_str());
      58           0 :             return FAIL_ON_MOD_COPY;
      59             :         }
      60             :     }
      61           0 :     else if (RenameFile(mod, modTemp) != INFO::OK)
      62             :     {
      63           0 :         LOGERROR("Failed to rename '%s' into '%s'", mod.string8().c_str(), modTemp.string8().c_str());
      64           0 :         return FAIL_ON_MOD_MOVE;
      65             :     }
      66             : 
      67             :     // Load the mod to VFS
      68           0 :     if (m_VFS->Mount(m_CacheDir, m_TempDir / "") != INFO::OK)
      69             :         return FAIL_ON_VFS_MOUNT;
      70           0 :     CVFSFile modinfo;
      71           0 :     PSRETURN modinfo_status = modinfo.Load(m_VFS, m_CacheDir / modTemp.Basename() / "mod.json", false);
      72           0 :     m_VFS->Clear();
      73           0 :     if (modinfo_status != PSRETURN_OK)
      74             :         return FAIL_ON_MOD_LOAD;
      75             : 
      76             :     // Extract the name of the mod
      77           0 :     CStr modName;
      78           0 :     {
      79           0 :         ScriptInterface scriptInterface("Engine", "ModInstaller", scriptContext);
      80           0 :         ScriptRequest rq(scriptInterface);
      81             : 
      82           0 :         JS::RootedValue json_val(rq.cx);
      83           0 :         if (!Script::ParseJSON(rq, modinfo.GetAsString(), &json_val))
      84           0 :             return FAIL_ON_PARSE_JSON;
      85           0 :         JS::RootedObject json_obj(rq.cx, json_val.toObjectOrNull());
      86           0 :         JS::RootedValue name_val(rq.cx);
      87           0 :         if (!JS_GetProperty(rq.cx, json_obj, "name", &name_val))
      88           0 :             return FAIL_ON_EXTRACT_NAME;
      89           0 :         Script::FromJSVal(rq, name_val, modName);
      90           0 :         if (modName.empty())
      91             :             return FAIL_ON_EXTRACT_NAME;
      92             :     }
      93             : 
      94           0 :     const OsPath modDir = m_ModsDir / modName;
      95           0 :     const OsPath modPath = modDir / (modName + ".zip");
      96             : 
      97             :     // Create a directory with the following structure:
      98             :     //   mod-name/
      99             :     //     mod-name.zip
     100             :     //     mod.json
     101           0 :     CreateDirectories(modDir, 0700);
     102           0 :     if (RenameFile(modTemp, modPath) != INFO::OK)
     103             :     {
     104           0 :         LOGERROR("Failed to rename '%s' into '%s'", modTemp.string8().c_str(), modPath.string8().c_str());
     105           0 :         return FAIL_ON_MOD_MOVE;
     106             :     }
     107             : 
     108           0 :     DeleteDirectory(modTemp.Parent());
     109             : 
     110           0 :     std::ofstream mod_json((modDir / "mod.json").string8());
     111           0 :     if (mod_json.good())
     112             :     {
     113           0 :         mod_json << modinfo.GetAsString();
     114           0 :         mod_json.close();
     115             :     }
     116             :     else
     117             :         return FAIL_ON_JSON_WRITE;
     118             : 
     119           0 :     m_InstalledMods.emplace_back(modName);
     120             : 
     121             :     return SUCCESS;
     122             : }
     123             : 
     124           0 : const std::vector<CStr>& CModInstaller::GetInstalledMods() const
     125             : {
     126           0 :     return m_InstalledMods;
     127             : }

Generated by: LCOV version 1.13