|  | /*
  ==============================================================================
   This file is part of the JUCE library.
   Copyright (c) 2020 - Raw Material Software Limited
   JUCE is an open source library subject to commercial or open-source
   licensing.
   By using JUCE, you agree to the terms of both the JUCE 6 End-User License
   Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
   End User License Agreement: www.juce.com/juce-6-licence
   Privacy Policy: www.juce.com/juce-privacy-policy
   Or: You may also use this code under the terms of the GPL v3 (see
   www.gnu.org/licenses).
   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.
  ==============================================================================
*/
#include "../Application/jucer_Headers.h"
#include "jucer_DownloadCompileEngineThread.h"
#include "../LiveBuildEngine/jucer_CompileEngineDLL.h"
#include "../Utility/Helpers/jucer_VersionInfo.h"
//==============================================================================
bool DownloadCompileEngineThread::downloadAndInstall()
{
    DownloadCompileEngineThread d;
    if (d.runThread())
    {
        if (d.result.failed())
            return withError (d.result.getErrorMessage());
        return true;
    }
    if (d.cancelledByUser)
        return false;
    return withError (d.result.getErrorMessage());
}
DownloadCompileEngineThread::DownloadCompileEngineThread()
    : ThreadWithProgressWindow ("Downloading live-build engine", true, true),
      result (Result::ok()), cancelledByUser (false)
{
}
void DownloadCompileEngineThread::threadComplete (bool userPressedCancel)
{
    cancelledByUser = userPressedCancel;
}
void DownloadCompileEngineThread::run()
{
    setProgress (-1.0);
    setStatusMessage ("Downloading...");
    MemoryBlock zipData;
    result = download (zipData);
    if (result.failed())
        return;
    setStatusMessage ("Installing...");
    File installFolder = getInstallFolder();
    if (! installFolder.createDirectory())
    {
        result = Result::fail ("Install error: cannot create target directory");
        return;
    }
    result = install (zipData, installFolder);
}
Result DownloadCompileEngineThread::download (MemoryBlock& dest)
{
    auto info = VersionInfo::fetchFromUpdateServer (ProjectInfo::versionString);
    if (info == nullptr)
        return Result::fail ("Download error: cannot communicate with server");
    auto requiredAssetName = []
    {
        String name ("JUCECompileEngine_");
       #if JUCE_MAC
        name << "osx_";
       #elif JUCE_WINDOWS
        name << "windows_";
       #else
        jassertfalse;
       #endif
        return name + ProjectInfo::versionString + ".zip";
    }();
    for (auto& asset : info->assets)
    {
        if (asset.name == requiredAssetName)
        {
            int statusCode = 0;
            auto in = VersionInfo::createInputStreamForAsset (asset, statusCode);
            if (in == nullptr || statusCode != 200)
                return Result::fail ("Download error: cannot establish connection");
            MemoryOutputStream mo (dest, true);
            int64 size = in->getTotalLength();
            int64 bytesReceived = -1;
            String msg("Downloading...  (123)");
            for (int64 pos = 0; pos < size; pos += bytesReceived)
            {
                setStatusMessage (msg.replace ("123", File::descriptionOfSizeInBytes (pos)));
                if (threadShouldExit())
                    return Result::fail ("Download error: operation interrupted");
                bytesReceived = mo.writeFromInputStream (*in, 8192);
                if (bytesReceived == 0)
                    return Result::fail ("Download error: lost connection");
            }
            return Result::ok();
        }
    }
    return Result::fail ("Download error: no downloads available");
}
Result DownloadCompileEngineThread::install (const MemoryBlock& data, File& targetFolder)
{
    MemoryInputStream input (data, false);
    ZipFile zip (input);
    if (zip.getNumEntries() == 0)
        return Result::fail ("Install error: downloaded file is corrupt");
    if (threadShouldExit())
        return Result::fail ("Install error: operation interrupted");
    return zip.uncompressTo (targetFolder);
}
File DownloadCompileEngineThread::getInstallFolder()
{
    return CompileEngineDLL::getVersionedUserAppSupportFolder();
}
bool DownloadCompileEngineThread::withError(const String& msg)
{
    AlertWindow::showMessageBox (AlertWindow::WarningIcon,
                                 "Download and install", msg);
    return false;
}
 |