Пример #1
0
        public async Task InstallArchives()
        {
            var grouped = ModList.Directives
                          .OfType <FromArchive>()
                          .Select(a => new { VF = VFS.Index.FileForArchiveHashPath(a.ArchiveHashPath), Directive = a })
                          .GroupBy(a => a.VF)
                          .ToDictionary(a => a.Key);

            if (grouped.Count == 0)
            {
                return;
            }

            await VFS.Extract(Queue, grouped.Keys.ToHashSet(), async (vf, sf) =>
            {
                foreach (var directive in grouped[vf])
                {
                    var file = directive.Directive;

                    switch (file)
                    {
                    case PatchedFromArchive pfa:
                        {
                            await using var s = await sf.GetStream();
                            s.Position        = 0;
                            var patchData     = await LoadBytesFromPath(pfa.PatchID);
                            var toFile        = file.To.RelativeTo(OutputFolder);
                            {
                                await using var os = await toFile.Create();
                                Utils.ApplyPatch(s, () => new MemoryStream(patchData), os);
                            }

                            if (await VirusScanner.ShouldScan(toFile) &&
                                await ClientAPI.GetVirusScanResult(toFile) == VirusScanner.Result.Malware)
                            {
                                await toFile.DeleteAsync();
                                Utils.ErrorThrow(new Exception($"Virus scan of patched executable reported possible malware: {toFile.ToString()} ({(long)await toFile.FileHashCachedAsync()})"));
                            }
                        }
                        break;

                    case FromArchive _:
                        if (grouped[vf].Count() == 1)
                        {
                            await sf.Move(directive.Directive.To.RelativeTo(OutputFolder));
                        }
                        else
                        {
                            await using var s = await sf.GetStream();
                            await directive.Directive.To.RelativeTo(OutputFolder).WriteAllAsync(s, false);
                        }

                        break;

                    default:
                        throw new Exception($"No handler for {directive}");
                    }

                    if (file is PatchedFromArchive)
                    {
                        await file.To.RelativeTo(OutputFolder).FileHashAsync();
                    }
                    else
                    {
                        file.To.RelativeTo(OutputFolder).FileHashWriteCache(file.Hash);
                    }

                    if (UseCompression)
                    {
                        Utils.Status($"Compacting {file.To}");
                        await file.To.RelativeTo(OutputFolder).Compact(FileCompaction.Algorithm.XPRESS16K);
                    }
                }
            }, tempFolder : OutputFolder, updateTracker : UpdateTracker);
        }