public void Verify_WithoutHash_VerifiesCorrectly()
    {
        using var testFolder = new TemporaryFolderAllocation();
        const string expectedMessage = "Oh noes!";

        var gameItem = new AppItem();

        var relativePath = Path.GetRandomFileName();
        var randomPath   = Path.Combine(testFolder.FolderPath, relativePath);

        File.Create(randomPath).Dispose();

        var warningItem = new WarningItem()
        {
            ErrorMessage = expectedMessage,
        };

        warningItem.Items.Add(new VerifyItem()
        {
            FilePath = relativePath
        });
        gameItem.Warnings.Add(warningItem);

        // Act
        var hasError = gameItem.TryGetError(testFolder.FolderPath, out var warnings);

        // Assert
        Assert.True(hasError);
        Assert.Single(warnings);
        Assert.Equal(expectedMessage, warnings[0].ErrorMessage);
    }
Exemple #2
0
    public async Task Index_CanDownload_ByHash()
    {
        const int numItems = 1;

        using var indexSourceDir      = new TemporaryFolderAllocation();
        using var indexDestinationDir = new TemporaryFolderAllocation();

        var index = BuildIndex(numItems, indexSourceDir.FolderPath, indexDestinationDir.FolderPath);
        var indexJsonExpectedPath = Path.Combine(indexDestinationDir.FolderPath, Routes.Index);

        Assert.True(File.Exists(indexJsonExpectedPath));
        var indexApi  = new IndexApi($"{indexDestinationDir.FolderPath}/");
        var indexCopy = await indexApi.GetIndexAsync();

        // Act
        var hash        = indexCopy.HashToAppDictionary.First().Key;
        var item        = indexCopy.FindApplication(hash, "", out _);
        var application = await indexApi.GetApplicationAsync(item[0]);

        // Assert
        Assert.NotNull(application);
        Assert.Equal(hash, application.Hash);
        Assert.True(!string.IsNullOrEmpty(application.AppId));
        Assert.True(!string.IsNullOrEmpty(application.Hash));
    }
Exemple #3
0
    /// <inheritdoc />
    public async Task <string> DownloadAsync(string packageFolder, IProgress <double>?progress, CancellationToken token = default)
    {
        using var tempDownloadDirectory = new TemporaryFolderAllocation();
        using var tempExtractDirectory  = new TemporaryFolderAllocation();
        var tempFilePath   = Path.Combine(tempDownloadDirectory.FolderPath, Path.GetRandomFileName());
        var progressSlicer = new ProgressSlicer(progress);

        // Start the modification download.
        using var httpClient = new HttpClient();
        var downloadProgress = progressSlicer.Slice(0.9);

        await using var fileStream = new FileStream(tempFilePath, FileMode.OpenOrCreate);
        var archiveStream = await httpClient.GetStreamAsync(_url, token).ConfigureAwait(false);

        await archiveStream.CopyToAsyncEx(fileStream, 262144, downloadProgress, FileSize.GetValueOrDefault(1), token);

        if (token.IsCancellationRequested)
        {
            return(string.Empty);
        }

        /* Extract to Temp Directory */
        var archiveExtractor = new SevenZipSharpExtractor();
        var extractProgress  = progressSlicer.Slice(0.1);
        await archiveExtractor.ExtractPackageAsync(tempFilePath, tempExtractDirectory.FolderPath, extractProgress, token);

        /* Get name of package. */
        return(CopyPackagesFromExtractFolderToTargetDir(packageFolder, tempExtractDirectory.FolderPath, token));
    }
Exemple #4
0
    public async Task RemoveItemFromIndex()
    {
        // Arrange
        using var tempFolder = new TemporaryFolderAllocation();
        IOEx.CopyDirectory(Assets.SampleIndexAssetsFolder, tempFolder.FolderPath);

        var api   = new IndexApi($"{tempFolder.FolderPath}/");
        var index = await api.GetIndexAsync();

        var builder = new IndexBuilder();

        builder.Sources.Add(new IndexSourceEntry(TestNuGetFeedUrl));
        var gbIndex    = index.Sources.First(x => x.Key.StartsWith(Routes.Source.IdentifierGameBanana)); // This will be removed.
        var nugetIndex = index.Sources.First(x => x.Key.StartsWith(Routes.Source.IdentifierNuGet));      // This will be preserved.

        // Act
        index = builder.RemoveNotInBuilder(index);

        // Assert
        Assert.Null(index.Sources.FirstOrDefault(x => x.Key.StartsWith(Routes.Source.IdentifierGameBanana)).Value);

        var oldNuGetFolder = Path.Combine(tempFolder.FolderPath, Path.GetDirectoryName(nugetIndex.Value));
        var oldGbFolder    = Path.Combine(tempFolder.FolderPath, Path.GetDirectoryName(gbIndex.Value));

        Assert.True(Directory.Exists(oldNuGetFolder));
        Assert.False(Directory.Exists(oldGbFolder));
    }
    public async Task ResolveAsync_WithExistingPackage_CanDownloadPackage()
    {
        // Arrange
        var config = new GitHubReleasesUpdateResolverFactory.GitHubConfig()
        {
            RepositoryName = "reloaded.universal.redirector",
            UserName       = "******",
            AssetFileName  = "reloaded.universal.monitor.zip",
            UseReleaseTag  = false
        };

        var clonedDependency = _testEnvironmoent.TestModConfigBTuple.DeepClone();

        clonedDependency.Config.ReleaseMetadataFileName = "Reloaded.Universal.Redirector.ReleaseMetadata.json";
        Singleton <GitHubReleasesUpdateResolverFactory> .Instance.SetConfiguration(clonedDependency, config);

        var clonedOriginal = _testEnvironmoent.TestModConfigATuple.DeepClone();

        var gameBanana = new GitHubReleasesDependencyMetadataWriter();

        gameBanana.Update(clonedOriginal.Config, new[] { clonedDependency.Config });

        // Act
        using var outputDirectory = new TemporaryFolderAllocation();
        var resolver = new GitHubDependencyResolver();
        var result   = await resolver.ResolveAsync(clonedDependency.Config.ModId, clonedOriginal.Config.PluginData);

        var downloadedPackagePath = await result.FoundDependencies[0].DownloadAsync(outputDirectory.FolderPath, null);

        // Assert
        Assert.True(Directory.Exists(downloadedPackagePath));
        Assert.True(File.Exists(Path.Combine(downloadedPackagePath, ModConfig.ConfigFileName)));
    }
    /// <inheritdoc />
    public async Task <string> DownloadAsync(string packageFolder, IProgress <double>?progress, CancellationToken token = default)
    {
        // Wait for background sync operation.
        await _initialiseTask;

        using var tempDownloadDir = new TemporaryFolderAllocation();
        using var tempExtractDir  = new TemporaryFolderAllocation();
        var tempDownloadPath = Path.Combine(tempDownloadDir.FolderPath, Path.GetRandomFileName());

        var progressSlicer = new ProgressSlicer(progress);

        // Download Package
        var downloadSlice = progressSlicer.Slice(0.9f);
        await PackageResolver.DownloadPackageAsync(Version !, tempDownloadPath, new ReleaseMetadataVerificationInfo()
        {
            FolderPath = tempDownloadPath
        }, downloadSlice, token);

        // Extract package.
        var extractSlice     = progressSlicer.Slice(0.1f);
        var archiveExtractor = new SevenZipSharpExtractor();
        await archiveExtractor.ExtractPackageAsync(tempDownloadPath, tempExtractDir.FolderPath, extractSlice, token);

        // Copy all packages from download.
        return(WebDownloadablePackage.CopyPackagesFromExtractFolderToTargetDir(packageFolder, tempExtractDir.FolderPath, token));
    }
    public async Task ResolveAsync_WithExistingPackage_CanDownloadPackage()
    {
        // Arrange
        var config = new GameBananaUpdateResolverFactory.GameBananaConfig()
        {
            ItemId = 333681
        };
        var clonedDependency = _testEnvironmoent.TestModConfigBTuple.DeepClone();

        clonedDependency.Config.ReleaseMetadataFileName = "IntegrationTest.ReleaseMetadata.json";
        Singleton <GameBananaUpdateResolverFactory> .Instance.SetConfiguration(clonedDependency, config);

        var clonedOriginal = _testEnvironmoent.TestModConfigATuple.DeepClone();

        var gameBanana = new GameBananaDependencyMetadataWriter();

        gameBanana.Update(clonedOriginal.Config, new[] { clonedDependency.Config });

        // Act
        using var outputDirectory = new TemporaryFolderAllocation();
        var resolver = new GameBananaDependencyResolver();
        var result   = await resolver.ResolveAsync(clonedDependency.Config.ModId, clonedOriginal.Config.PluginData);

        var downloadedPackagePath = await result.FoundDependencies[0].DownloadAsync(outputDirectory.FolderPath, null);

        // Assert
        Assert.True(Directory.Exists(downloadedPackagePath));
        Assert.True(File.Exists(Path.Combine(downloadedPackagePath, ModConfig.ConfigFileName)));
    }
    public async Task CanAutoGenerateDelta()
    {
        // Arrange
        using var oldVersionFolder = new TemporaryFolderAllocation();
        using var curVersionFolder = new TemporaryFolderAllocation();
        var zipUnarchiver = new ZipPackageExtractor();

        await zipUnarchiver.ExtractPackageAsync(TestArchiveFile, curVersionFolder.FolderPath);

        await zipUnarchiver.ExtractPackageAsync(TestArchiveFileOld, oldVersionFolder.FolderPath);

        // Act
        using var outputFolder = new TemporaryFolderAllocation();
        var modTuple = ConfigReader <ModConfig> .ReadConfigurations(curVersionFolder.FolderPath, ModConfig.ConfigFileName)[0];

        var metadata = await Publisher.PublishAsync(new Publisher.PublishArgs()
        {
            OutputFolder        = outputFolder.FolderPath,
            OlderVersionFolders = new List <string>()
            {
                oldVersionFolder.FolderPath
            },
            ModTuple = modTuple
        });

        // Assert
        Assert.Equal(2, metadata.Releases.Count);
        Assert.Contains(metadata.Releases, item => item.ReleaseType == PackageType.Delta);
    }
    public void Verify_WithoutMatchingFile_ReturnsEmpty()
    {
        using var testFolder = new TemporaryFolderAllocation();
        const string expectedMessage = "Oh noes!";

        var gameItem = new AppItem();

        var relativePath = Path.GetRandomFileName();
        var randomPath   = Path.Combine(testFolder.FolderPath, relativePath);

        File.Create(randomPath + "random").Dispose();

        // Add random file.
        var warningItem = new WarningItem()
        {
            ErrorMessage = expectedMessage,
        };

        warningItem.Items.Add(new VerifyItem()
        {
            FilePath = relativePath
        });
        gameItem.Warnings.Add(warningItem);

        // Act
        var hasError = gameItem.TryGetError(testFolder.FolderPath, out var warnings);

        // Assert
        Assert.False(hasError);
        Assert.Empty(warnings);
    }
Exemple #10
0
    /// <summary>
    /// Converts a mod archive (zip) into a NuGet package.
    /// </summary>
    /// <returns>The location of the newly created package.</returns>
    public static async Task <string> FromArchiveFileAsync(string archivePath, string outputDirectory)
    {
        using var temporaryFolder = new TemporaryFolderAllocation();
        var extractor = new NuGetPackageExtractor();
        await extractor.ExtractPackageAsync(archivePath, temporaryFolder.FolderPath);

        return(await FromModDirectoryAsync(temporaryFolder.FolderPath, outputDirectory));
    }
    private static void InstallDependenciesOnly()
    {
        var model = new MainWindowViewModel();

        using var progressBar     = SetupCliInstall("Installing (Dependencies Only)", model);
        using var temporaryFolder = new TemporaryFolderAllocation();
        Console.WriteLine($"Using Temporary Folder: {temporaryFolder.FolderPath}");
        Task.Run(() => model.InstallReloadedAsync(temporaryFolder.FolderPath, false, false)).Wait();
    }
Exemple #12
0
    public void Index_CanBuild(int numItems)
    {
        using var indexSourceDir      = new TemporaryFolderAllocation();
        using var indexDestinationDir = new TemporaryFolderAllocation();

        // Act
        var index = BuildIndex(numItems, indexSourceDir.FolderPath, indexDestinationDir.FolderPath);

        // Assert
        var indexJsonExpectedPath = Path.Combine(indexDestinationDir.FolderPath, Routes.Index);

        Assert.True(File.Exists(indexJsonExpectedPath));
        Assert.Equal(numItems, index.IdToApps.Count);
    }
    public async Task SearchAsync_CanDownloadReturnedPackage()
    {
        // Arrange
        var provider = new GameBananaPackageProvider(7486);

        // Act
        using var outputDirectory = new TemporaryFolderAllocation();
        var package = (await provider.SearchAsync("Update Lib. Test")).First();
        var downloadedPackagePath = await package.DownloadAsync(outputDirectory.FolderPath, null);

        // Assert
        Assert.True(Directory.Exists(downloadedPackagePath), "This test currently fails because GameBanana cannot distinguish between Delta and Normal packages.");
        Assert.True(File.Exists(Path.Combine(downloadedPackagePath, ModConfig.ConfigFileName)));
    }
Exemple #14
0
    public async Task SearchAsync_CanDownloadReturnedPackage()
    {
        // Arrange
        var repository = NugetRepository.FromSourceUrl(NugetRepositoryTests.TestNugetFeed);
        var provider   = new NuGetPackageProvider(repository);

        // Act
        using var outputDirectory = new TemporaryFolderAllocation();
        var package = (await provider.SearchAsync("Hooks")).First();
        var downloadedPackagePath = await package.DownloadAsync(outputDirectory.FolderPath, null);

        // Assert
        Assert.True(Directory.Exists(downloadedPackagePath));
        Assert.True(File.Exists(Path.Combine(downloadedPackagePath, ModConfig.ConfigFileName)));
    }
Exemple #15
0
    public async Task Index_CanRead()
    {
        const int numItems = 1;

        using var indexSourceDir      = new TemporaryFolderAllocation();
        using var indexDestinationDir = new TemporaryFolderAllocation();

        // Act
        var index = BuildIndex(numItems, indexSourceDir.FolderPath, indexDestinationDir.FolderPath);
        var indexJsonExpectedPath = Path.Combine(indexDestinationDir.FolderPath, Routes.Index);

        Assert.True(File.Exists(indexJsonExpectedPath));
        var indexApi = new IndexApi($"{indexDestinationDir.FolderPath}/");

        // Assert
        var indexCopy = await indexApi.GetIndexAsync();

        Assert.Single(indexCopy.IdToApps);
    }
Exemple #16
0
    private void OnApplySelfUpdate(string newUpdateDir)
    {
        var updates = Task.Run(() => DependencyInstaller.GetMissingRuntimeUrls(newUpdateDir)).GetAwaiter().GetResult();

        if (updates.Count <= 0)
        {
            return;
        }

        ActionWrappers.ExecuteWithApplicationDispatcher(() =>
        {
            // Install Updates
            using var tempFolder = new TemporaryFolderAllocation();

            // Display runtime invoke info.
            Actions.DisplayMessagebox.Invoke(Resources.RuntimeUpdateRequiredTitle.Get(), Resources.RuntimeUpdateRequiredDescription.Get(), new Actions.DisplayMessageBoxParams {
                StartupLocation = Actions.WindowStartupLocation.CenterScreen
            });

            Task.Run(() => DependencyInstaller.DownloadAndInstallRuntimesAsync(updates, tempFolder.FolderPath, null, null)).Wait();
        });
    }
Exemple #17
0
    public async Task UpdateExistingIndex()
    {
        const int heroesGameId = 6061;

        // Arrange
        using var tempFolder = new TemporaryFolderAllocation();
        IOEx.CopyDirectory(Assets.GameBananaIndexAssetsFolder, tempFolder.FolderPath);

        var api   = new IndexApi($"{tempFolder.FolderPath}/");
        var index = await api.GetIndexAsync();

        var builder = new IndexBuilder();

        builder.Sources.Add(new IndexSourceEntry(TestNuGetFeedUrl));

        // Act
        index = await builder.UpdateAsync(index);

        // Assert
        Assert.True(index.TryGetNuGetSourcePath(TestNuGetFeedUrl, out _));
        Assert.True(index.TryGetGameBananaSourcePath(heroesGameId, out _));
        Assert.True(Directory.Exists(index.BaseUrl.LocalPath));
    }
    public void Verify_WithHash_VerifiesCorrectly()
    {
        using var testFolder = new TemporaryFolderAllocation();
        const string expectedMessage = "Oh noes!";

        var gameItem = new AppItem();

        var relativePath = Path.GetRandomFileName();
        var randomPath   = Path.Combine(testFolder.FolderPath, relativePath);

        // Write random file.
        var seed  = DateTime.UtcNow.Ticks % int.MaxValue;
        var bytes = new byte[1024];

        new Random((int)seed).NextBytes(bytes);
        File.WriteAllBytes(randomPath, bytes);

        // Add random file.
        var warningItem = new WarningItem()
        {
            ErrorMessage = expectedMessage,
        };

        warningItem.Items.Add(new VerifyItem()
        {
            FilePath = relativePath, Hash = Hashing.ToString(xxHash64.ComputeHash(bytes))
        });
        gameItem.Warnings.Add(warningItem);

        // Act
        var hasError = gameItem.TryGetError(testFolder.FolderPath, out var warnings);

        // Assert
        Assert.True(hasError);
        Assert.Single(warnings);
        Assert.Equal(expectedMessage, warnings[0].ErrorMessage);
    }
    public async Task InstallReloadedAsync(string?installFolder = null, bool createShortcut = true, bool startReloaded = true)
    {
        // Step
        installFolder ??= Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "Reloaded-II");
        Directory.CreateDirectory(installFolder);

        using var tempDownloadDir = new TemporaryFolderAllocation();
        var progressSlicer = new ProgressSlicer(new Progress <double>(d =>
        {
            Progress = d * 100.0;
        }));

        try
        {
            var downloadLocation = Path.Combine(tempDownloadDir.FolderPath, $"Reloaded-II.zip");

            // 0.15
            CurrentStepNo = 0;
            await DownloadReloadedAsync(downloadLocation, progressSlicer.Slice(0.15));

            if (CancellationToken.IsCancellationRequested)
            {
                throw new TaskCanceledException();
            }

            // 0.20
            CurrentStepNo = 1;
            await ExtractReloadedAsync(installFolder, downloadLocation, progressSlicer.Slice(0.05));

            if (CancellationToken.IsCancellationRequested)
            {
                throw new TaskCanceledException();
            }

            // 1.00
            CurrentStepNo = 2;
            await CheckAndInstallMissingRuntimesAsync(installFolder, tempDownloadDir.FolderPath,
                                                      progressSlicer.Slice(0.8),
                                                      s => { CurrentStepDescription = s; }, CancellationToken.Token);

            var executableName = IntPtr.Size == 8 ? "Reloaded-II.exe" : "Reloaded-II32.exe";
            var executablePath = Path.Combine(installFolder, executableName);
            var shortcutPath   = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "Reloaded-II.lnk");

            if (createShortcut)
            {
                CurrentStepDescription = "Creating Shortcut";
                MakeShortcut(shortcutPath, executablePath);
            }

            CurrentStepDescription = "All Set";

            if (startReloaded)
            {
                Process.Start(executablePath);
            }
        }
        catch (TaskCanceledException)
        {
            IOEx.TryDeleteDirectory(installFolder);
        }
        catch (Exception e)
        {
            IOEx.TryDeleteDirectory(installFolder);
            MessageBox.Show("There was an error in installing Reloaded.\n" +
                            $"Feel free to open an issue on github.com/Reloaded-Project/Reloaded-II if you require support.\n" +
                            $"Message: {e.Message}\n" +
                            $"Stack Trace: {e.StackTrace}", "Error in Installing Reloaded");
        }
    }