예제 #1
0
        private async Task InstallPackages(List <RemotePackage> toInstall, string tribesExePath)
        {
            try
            {
                BroadcastUpdatePhase(UpdatePhase.Preparing);
                if (!tribesExePath.ToLower().EndsWith(".exe"))
                {
                    throw new Exception($"Invalid tribes path {tribesExePath}");
                }

                // Exe is <basepath>/Binaries/Win32/TribesAscend.exe
                // So the directory two levels up is the base path of the install
                string tribesBasePath = Path.Combine(Path.GetDirectoryName(tribesExePath), "..", "..");

                // Clear temp directory if it exists
                if (Directory.Exists("./tmp"))
                {
                    Directory.Delete($"./tmp", true);
                }
                Directory.CreateDirectory("./tmp");

                double progressBarValue = 0;

                BroadcastUpdatePhase(UpdatePhase.Downloading);
                // Download compressed packages to temp folder
                List <string> archives = await DownloadPackages(toInstall, ".", (percentage) =>
                {
                    // Half the progress bar for download, then half for extract / copy
                    double pct = progressBarValue + 0.5 * percentage;
                    OnProgressTick?.Invoke(this, new OnProgressTickEventArgs(pct));
                });

                progressBarValue = 0.5;

                BroadcastUpdatePhase(UpdatePhase.Extracting);
                // Extract packages and delete the zips
                await ExtractArchives(archives, (idx, totalZips) =>
                {
                    // 25% of progress bar for extracts
                    double pct = progressBarValue + 0.25 * ((double)idx + 1) / totalZips;
                    OnProgressTick?.Invoke(this, new OnProgressTickEventArgs(pct));
                });

                progressBarValue = 0.75;

                BroadcastUpdatePhase(UpdatePhase.Copying);
                // For each package we downloaded, copy its files into the local dir / config dir / Tribes dir
                await CopyDownloadedPackages("./tmp", ".", tribesBasePath, (idx, totalPackages) =>
                {
                    // 25% of progress bar for package copy
                    double pct = progressBarValue + 0.25 * ((double)idx + 1) / totalPackages;
                    OnProgressTick?.Invoke(this, new OnProgressTickEventArgs(pct));
                });

                BroadcastUpdatePhase(UpdatePhase.Finalising);

                // Save the new installed package manifest
                UpdateInstalledPackageState(toInstall);

                // Delete temp directory
                Directory.Delete($"./tmp", true);

                BroadcastUpdatePhase(UpdatePhase.NotUpdating);
                // Raise finished event
                OnUpdateComplete?.Invoke(this, new EventArgs());
            } catch (Exception e)
            {
                // Reset update phase
                BroadcastUpdatePhase(UpdatePhase.NotUpdating);
                throw e;
            }
        }
예제 #2
0
        private async Task PerformUpdateInternal()
        {
            Dictionary <string, double> filesToDownload = GetFilesNeedingUpdate();

            // Download to temp folder
            using (var httpClient = new HttpClient())
            {
                // Download files in batches of 10, if there are at least 10 to download
                var batchSize   = filesToDownload.Count > 10 ? 10 : 1;
                var fileBatches = filesToDownload.Keys
                                  .Select((f, i) =>
                {
                    int dirSplitPos    = Math.Max(0, Math.Max(f.LastIndexOf('/'), f.LastIndexOf('\\')));
                    string relativeDir = f.Substring(0, dirSplitPos);
                    string dir         = $"{LocalBasePath}/tmp/{relativeDir}";
                    return(new { Idx = i, Filename = f, Directory = dir });
                })
                                  .Batch(batchSize)
                                  .Select((b, i) => new { Idx = i, Batch = b });
                var numBatches = fileBatches.Count();
                foreach (var batch in fileBatches)
                {
                    // Create directories for this batch if required
                    foreach (var file in batch.Batch)
                    {
                        if (!Directory.Exists(file.Directory))
                        {
                            Directory.CreateDirectory(file.Directory);
                        }
                    }

                    var tasks = batch.Batch.Select(async(file) =>
                    {
                        var response = await httpClient.GetAsync(new Uri($"{RemoteBaseUrl}/{file.Filename}"));
                        using (var memStream = response.Content.ReadAsStreamAsync().Result)
                        {
                            using (var fileStream = File.Create($"{LocalBasePath}/tmp/{file.Filename}"))
                            {
                                memStream.CopyTo(fileStream);
                            }
                        }
                    });
                    await Task.WhenAll(tasks);

                    double pct = ((double)batch.Idx + 1) / numBatches;
                    OnProgressTick?.Invoke(this, new OnProgressTickEventArgs(pct));
                }
            }

            // Copy files out
            foreach (string filename in filesToDownload.Keys)
            {
                string copyLocation;
                if (filename.StartsWith("!CONFIG/"))
                {
                    copyLocation = $"{ConfigBasePath}/{filename.Replace("!CONFIG/", "")}";
                }
                else
                {
                    copyLocation = $"{LocalBasePath}/{filename}";
                }

                // Create directory if required
                string dir = new FileInfo(copyLocation).Directory.FullName;
                if (!Directory.Exists(dir))
                {
                    Directory.CreateDirectory(dir);
                }

                // Copy the file
                File.Copy($"{LocalBasePath}/tmp/{filename}", copyLocation, true);
            }

            // Delete temp directory
            Directory.Delete($"{LocalBasePath}/tmp", true);

            // Download the current version manifest
            // TODO: THIS
            var newLocalManifest = XElement.Load($"{RemoteBaseUrl}/version.xml");

            newLocalManifest.Save($"{LocalBasePath}/version.xml");

            // Raise finished event
            OnUpdateComplete?.Invoke(this, new EventArgs());
        }