/// <summary>
        /// Installs the package internal.
        /// </summary>
        /// <param name="package">The package.</param>
        /// <param name="progress">The progress.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task.</returns>
        private async Task InstallPackageInternal(PackageVersionInfo package, IProgress <double> progress, CancellationToken cancellationToken)
        {
            // Do the install
            await _packageManager.InstallPackage(progress, package, cancellationToken).ConfigureAwait(false);

            // Do plugin-specific processing
            if (!(Path.GetExtension(package.targetFilename) ?? "").Equals(".zip", StringComparison.OrdinalIgnoreCase))
            {
                // Set last update time if we were installed before
                var plugin = ApplicationHost.Plugins.FirstOrDefault(p => p.Name.Equals(package.name, StringComparison.OrdinalIgnoreCase));

                if (plugin != null)
                {
                    // Synchronize the UpdateClass value
                    if (plugin.Configuration.UpdateClass != package.classification)
                    {
                        plugin.Configuration.UpdateClass = package.classification;
                        plugin.SaveConfiguration();
                    }

                    OnPluginUpdated(plugin, package);
                }
                else
                {
                    OnPluginInstalled(package);
                }
            }
        }
Exemplo n.º 2
0
        private async Task PerformPackageInstallation(IProgress <double> progress, PackageVersionInfo package, CancellationToken cancellationToken)
        {
            // Target based on if it is an archive or single assembly
            //  zip archives are assumed to contain directory structures relative to our ProgramDataPath
            var extension = Path.GetExtension(package.targetFilename);
            var isArchive = string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".rar", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".7z", StringComparison.OrdinalIgnoreCase);
            var target    = Path.Combine(isArchive ? _appPaths.TempUpdatePath : _appPaths.PluginsPath, package.targetFilename);

            // Download to temporary file so that, if interrupted, it won't destroy the existing installation
            var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
            {
                Url = package.sourceUrl,
                CancellationToken = cancellationToken,
                Progress          = progress
            }).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            // Validate with a checksum
            if (package.checksum != Guid.Empty) // support for legacy uploads for now
            {
                using (var crypto = new MD5CryptoServiceProvider())
                    using (var stream = new BufferedStream(File.OpenRead(tempFile), 100000))
                    {
                        var check = Guid.Parse(BitConverter.ToString(crypto.ComputeHash(stream)).Replace("-", String.Empty));
                        if (check != package.checksum)
                        {
                            throw new ApplicationException(string.Format("Download validation failed for {0}.  Probably corrupted during transfer.", package.name));
                        }
                    }
            }

            cancellationToken.ThrowIfCancellationRequested();

            // Success - move it to the real target
            try
            {
                File.Copy(tempFile, target, true);
                //If it is an archive - write out a version file so we know what it is
                if (isArchive)
                {
                    File.WriteAllText(target + ".ver", package.versionStr);
                }
            }
            catch (IOException e)
            {
                _logger.ErrorException("Error attempting to move file from {0} to {1}", e, tempFile, target);
                throw;
            }

            try
            {
                File.Delete(tempFile);
            }
            catch (IOException e)
            {
                // Don't fail because of this
                _logger.ErrorException("Error deleting temp file {0]", e, tempFile);
            }
        }
Exemplo n.º 3
0
        protected override void OnLoadPackages()
        {
            var potentialPackages = Directory.GetFiles(LocalRepositoryPath, "*.zip", SearchOption.TopDirectoryOnly);

            foreach (var filePath in potentialPackages)
            {
                using (var archive = ArchiveFactory.Open(filePath))
                    foreach (var entry in archive.Entries)
                    {
                        if (!"manifest.json".Equals(Path.GetFileName(entry.Key)))
                        {
                            continue;
                        }

                        var manifestJson = string.Empty;
                        using (var reader = new StreamReader(entry.OpenEntryStream()))
                            manifestJson = reader.ReadToEnd();

                        var tsp = JsonUtility.FromJson <PackageVersion>(manifestJson);

                        var versionId = Path.GetFileNameWithoutExtension(filePath);
                        var author    = versionId.Split('-')[0];
                        var groupId   = $"{author}-{tsp.name}";
                        var versions  = new PackageVersionInfo[] { new PackageVersionInfo(tsp.version_number, versionId, tsp.dependencies) };
                        AddPackageGroup(author, tsp.name, tsp.description, groupId, EmptyStringArray, versions);
                        //don't process additional manifest files
                        break;
                    }
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Installs the package internal.
        /// </summary>
        /// <param name="package">The package.</param>
        /// <param name="isPlugin">if set to <c>true</c> [is plugin].</param>
        /// <param name="progress">The progress.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task.</returns>
        private async Task InstallPackageInternal(PackageVersionInfo package, bool isPlugin, IProgress <double> progress, CancellationToken cancellationToken)
        {
            IPlugin plugin = null;

            if (isPlugin)
            {
                // Set last update time if we were installed before
                plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase))
                         ?? _applicationHost.Plugins.FirstOrDefault(p => p.Name.Equals(package.name, StringComparison.OrdinalIgnoreCase));
            }

            string targetPath = plugin == null ? null : plugin.AssemblyFilePath;

            // Do the install
            await PerformPackageInstallation(progress, targetPath, package, cancellationToken).ConfigureAwait(false);

            // Do plugin-specific processing
            if (isPlugin)
            {
                if (plugin == null)
                {
                    OnPluginInstalled(package);
                }
                else
                {
                    OnPluginUpdated(plugin, package);
                }
            }
        }
Exemplo n.º 5
0
 public bool DetectNewVersion()
 {
     using (FtpClient client = this.CreateFtpClient())
     {
         PackageVersionInfo diffVersionInfo = GetDifferenceVersionInfoWithServer(client);
         return(diffVersionInfo != null && diffVersionInfo.Files.Length > 0);
     }
 }
Exemplo n.º 6
0
        /// <summary>
        /// Updates the application.
        /// </summary>
        /// <param name="package">The package that contains the update</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <param name="progress">The progress.</param>
        /// <returns>Task.</returns>
        public override async Task UpdateApplication(PackageVersionInfo package, CancellationToken cancellationToken, IProgress <double> progress)
        {
            await InstallationManager.InstallPackage(package, progress, cancellationToken).ConfigureAwait(false);

            HasUpdateAvailable = false;

            OnApplicationUpdated(package);
        }
Exemplo n.º 7
0
        public async void Install(PackageVersionInfo version)
        {
            _installationManager.InstallPackage(version, new Progress <double>(), CancellationToken.None);

            await _nav.NavigateToSettingsPage();

            _nav.RemovePagesFromHistory(3);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Determines whether [is package version up to date] [the specified package version info].
        /// </summary>
        /// <param name="packageVersionInfo">The package version info.</param>
        /// <param name="currentServerVersion">The current server version.</param>
        /// <returns><c>true</c> if [is package version up to date] [the specified package version info]; otherwise, <c>false</c>.</returns>
        private static bool IsPackageVersionUpToDate(PackageVersionInfo packageVersionInfo, Version currentServerVersion)
        {
            if (string.IsNullOrEmpty(packageVersionInfo.requiredVersionStr))
            {
                return(true);
            }

            return(Version.TryParse(packageVersionInfo.requiredVersionStr, out var requiredVersion) && currentServerVersion >= requiredVersion);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Called when [plugin updated].
        /// </summary>
        /// <param name="plugin">The plugin.</param>
        /// <param name="newVersion">The new version.</param>
        private void OnPluginUpdated(IPlugin plugin, PackageVersionInfo newVersion)
        {
            _logger.LogInformation("Plugin updated: {0} {1} {2}", newVersion.name, newVersion.versionStr ?? string.Empty, newVersion.classification);

            PluginUpdated?.Invoke(this, new GenericEventArgs <Tuple <IPlugin, PackageVersionInfo> > {
                Argument = new Tuple <IPlugin, PackageVersionInfo>(plugin, newVersion)
            });

            _applicationHost.NotifyPendingRestart();
        }
Exemplo n.º 10
0
        /// <summary>
        /// Called when [plugin installed].
        /// </summary>
        /// <param name="package">The package.</param>
        private void OnPluginInstalled(PackageVersionInfo package)
        {
            _logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification);

            PluginInstalled?.Invoke(this, new GenericEventArgs <PackageVersionInfo> {
                Argument = package
            });

            _applicationHost.NotifyPendingRestart();
        }
Exemplo n.º 11
0
        /// <summary>
        /// Called when [plugin installed].
        /// </summary>
        /// <param name="package">The package.</param>
        private void OnPluginInstalled(PackageVersionInfo package)
        {
            _logger.Info("New plugin installed: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification);

            EventHelper.FireEventIfNotNull(PluginInstalled, this, new GenericEventArgs <PackageVersionInfo> {
                Argument = package
            }, _logger);

            _applicationHost.NotifyPendingRestart();
        }
Exemplo n.º 12
0
        /// <summary>
        /// Called when [plugin updated].
        /// </summary>
        /// <param name="plugin">The plugin.</param>
        /// <param name="newVersion">The new version.</param>
        private void OnPluginUpdated(IPlugin plugin, PackageVersionInfo newVersion)
        {
            _logger.Info("Plugin updated: {0} {1} {2}", newVersion.name, newVersion.versionStr ?? string.Empty, newVersion.classification);

            EventHelper.FireEventIfNotNull(PluginUpdated, this, new GenericEventArgs <Tuple <IPlugin, PackageVersionInfo> > {
                Argument = new Tuple <IPlugin, PackageVersionInfo>(plugin, newVersion)
            }, _logger);

            _applicationHost.NotifyPendingRestart();
        }
Exemplo n.º 13
0
        /// <summary>
        /// Updates the application.
        /// </summary>
        /// <param name="package">The package that contains the update</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <param name="progress">The progress.</param>
        /// <returns>Task.</returns>
        public async Task UpdateApplication(PackageVersionInfo package, CancellationToken cancellationToken, IProgress <double> progress)
        {
            await PackageManager.InstallPackage(progress, package, cancellationToken).ConfigureAwait(false);

            EventHelper.QueueEventIfNotNull(ApplicationUpdated, this, new GenericEventArgs <Version> {
                Argument = package.version
            }, Logger);

            NotifyPendingRestart();
        }
Exemplo n.º 14
0
        /// <summary>
        /// Determines whether [is package version up to date] [the specified package version info].
        /// </summary>
        /// <param name="packageVersionInfo">The package version info.</param>
        /// <param name="applicationVersion">The application version.</param>
        /// <returns><c>true</c> if [is package version up to date] [the specified package version info]; otherwise, <c>false</c>.</returns>
        private bool IsPackageVersionUpToDate(PackageVersionInfo packageVersionInfo, Version applicationVersion)
        {
            if (string.IsNullOrEmpty(packageVersionInfo.requiredVersionStr))
            {
                return(true);
            }

            Version requiredVersion;

            return(Version.TryParse(packageVersionInfo.requiredVersionStr, out requiredVersion) && applicationVersion >= requiredVersion);
        }
Exemplo n.º 15
0
        /// <summary>
        /// Called when [application updated].
        /// </summary>
        /// <param name="package">The package.</param>
        protected void OnApplicationUpdated(PackageVersionInfo package)
        {
            Logger.Info("Application has been updated to version {0}", package.versionStr);

            EventHelper.FireEventIfNotNull(ApplicationUpdated, this, new GenericEventArgs <PackageVersionInfo>
            {
                Argument = package
            }, Logger);

            NotifyPendingRestart();
        }
Exemplo n.º 16
0
 public bool TryUpgradeNow()
 {
     using (FtpClient client = this.CreateFtpClient())
     {
         PackageVersionInfo diffVersionInfo = GetDifferenceVersionInfoWithServer(client);
         if (diffVersionInfo == null || diffVersionInfo.Files.Length == 0)
         {
             return(false);
         }
         UpgradeNow(client, diffVersionInfo);
         return(true);
     }
 }
Exemplo n.º 17
0
 private static void CopyVersionFile(PackageVersionInfo versionInfo, string sourceFolder, string toFolder)
 {
     foreach (var item in versionInfo.Files)
     {
         string filePath = Path.Combine(sourceFolder, item.File.TrimStart('\\', '/'));
         if (!File.Exists(filePath))
         {
             continue;
         }
         string newFilePath = Path.Combine(toFolder, item.File.TrimStart('\\', '/'));
         Directory.CreateDirectory(Directory.GetParent(newFilePath).FullName);
         File.Copy(filePath, newFilePath, true);
     }
 }
Exemplo n.º 18
0
        private PackageVersionInfo GetDifferenceVersionInfoWithServer(FtpClient client)
        {
            if (!client.FileExists("/" + VersionFileName))
            {
                return(null);
            }
            byte[] versionData = null;
            if (!client.Download(out versionData, "/" + VersionFileName))
            {
                return(null);
            }
            PackageVersionInfo pvi = XmlSerializer.ToObject <PackageVersionInfo>(versionData);

            return(this._versionService.CompareDifference(_targetFolder, pvi));
        }
Exemplo n.º 19
0
        /// <summary>
        /// Download our specified package to an archive in a temp location
        /// </summary>
        /// <returns>The fully qualified name of the downloaded package</returns>
        protected async Task <string> DownloadPackage(PackageVersionInfo version)
        {
            var success     = false;
            var retryCount  = 0;
            var archiveFile = Path.Combine(PrepareTempLocation(), version.targetFilename);

            try
            {
                while (!success && retryCount < 3)
                {
                    // setup download progress and download the package
                    MainClient.DownloadProgressChanged += DownloadProgressChanged;
                    try
                    {
                        await MainClient.DownloadFileTaskAsync(version.sourceUrl, archiveFile);

                        success = true;
                    }
                    catch (WebException e)
                    {
                        if (e.Status == WebExceptionStatus.RequestCanceled)
                        {
                            return(null);
                        }
                        if (retryCount < 3 && (e.Status == WebExceptionStatus.Timeout || e.Status == WebExceptionStatus.ConnectFailure || e.Status == WebExceptionStatus.ProtocolError))
                        {
                            Thread.Sleep(500);     //wait just a sec
                            PrepareTempLocation(); //clear this out
                            retryCount++;
                        }
                        else
                        {
                            throw;
                        }
                    }
                }

                return(archiveFile);
            }
            catch (Exception e)
            {
                SystemClose(e.GetType().FullName + "\n\n" + e.Message);
            }
            return("");
        }
Exemplo n.º 20
0
        /// <summary>
        /// Gets the specified request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>System.Object.</returns>
        public async Task <object> Get(GetPackageVersionUpdates request)
        {
            PackageVersionInfo[] result = null;

            if (string.Equals(request.PackageType, "UserInstalled", StringComparison.OrdinalIgnoreCase) || string.Equals(request.PackageType, "All", StringComparison.OrdinalIgnoreCase))
            {
                result = (await _installationManager.GetAvailablePluginUpdates(_appHost.ApplicationVersion, false, CancellationToken.None).ConfigureAwait(false)).ToArray();
            }

            else if (string.Equals(request.PackageType, "System", StringComparison.OrdinalIgnoreCase) ||
                     string.Equals(request.PackageType, "All", StringComparison.OrdinalIgnoreCase))
            {
                var updateCheckResult = await _appHost
                                        .CheckForApplicationUpdate(CancellationToken.None, new SimpleProgress <double>()).ConfigureAwait(false);

                if (updateCheckResult.IsUpdateAvailable)
                {
                    result = new PackageVersionInfo[] { updateCheckResult.Package };
                }
            }

            return(ToOptimizedResult(result ?? new PackageVersionInfo[] { }));
        }
Exemplo n.º 21
0
 static void Main(string[] args)
 {
     try
     {
         var definition = Args.Configuration.Configure <CommandObject>();
         var command    = definition.CreateAndBind(args);
         if (command.Help != null)
         {
             var help = new Args.Help.HelpProvider().GenerateModelHelp(definition);
             var f    = new ConsoleHelpFormatter(80, 1, 5);
             Console.WriteLine(f.GetHelp(help));
             return;
         }
         Console.WriteLine($"正在生成...");
         Console.WriteLine($"目标文件夹:{command.TargetFolder}");
         Console.WriteLine($"秘钥:{command.SecretKey}");
         Console.WriteLine($"忽略文件:{ ((command.Ignore == null || command.Ignore.Count == 0) ? "无" : string.Join(", ", command.Ignore))}");
         VersionService versionService = new VersionService(command.SecretKey);
         if (command.Ignore == null)
         {
             command.Ignore = new List <string>(2);
         }
         command.Ignore.Add(Path.GetFileNameWithoutExtension(typeof(Program).Assembly.Location));
         command.Ignore.Add(versionFileName);
         command.Ignore.Add("Zl.AutoUpgrade.Core");
         PackageVersionInfo info = versionService.ComputeVersionInfo(command.TargetFolder,
                                                                     command.Ignore.ToArray());
         XmlSerializer.SaveToFile(info, System.IO.Path.Combine(command.TargetFolder, versionFileName));
         Console.WriteLine($"生成完毕.");
     }
     catch (Exception exc)
     {
         Console.ForegroundColor = ConsoleColor.Red;
         Console.WriteLine(exc);
         Console.ResetColor();
     }
 }
Exemplo n.º 22
0
        /// <summary>
        /// Download our specified package to an archive in a temp location
        /// </summary>
        /// <returns>The fully qualified name of the downloaded package</returns>
        protected async Task <string> DownloadPackage(PackageVersionInfo version)
        {
            var retryCount = 0;

            while (retryCount < 3)
            {
                var archiveFile = Path.Combine(GetTempLocation(), version.targetFilename);

                // setup download progress and download the package
                MainClient.DownloadProgressChanged += DownloadProgressChanged;
                try
                {
                    await MainClient.DownloadFileTaskAsync(version.sourceUrl, archiveFile);

                    return(archiveFile);
                }
                catch (WebException e)
                {
                    if (e.Status == WebExceptionStatus.RequestCanceled)
                    {
                        Trace.TraceInformation("Download cancelled");
                        return(null);
                    }
                    if (retryCount < 3 && (e.Status == WebExceptionStatus.Timeout || e.Status == WebExceptionStatus.ConnectFailure || e.Status == WebExceptionStatus.ProtocolError))
                    {
                        Thread.Sleep(500); //wait just a sec
                        retryCount++;
                    }
                    else
                    {
                        throw;
                    }
                }
            }
            return(null);
        }
Exemplo n.º 23
0
        /// <summary>
        /// Installs the package internal.
        /// </summary>
        /// <param name="package">The package.</param>
        /// <param name="progress">The progress.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task.</returns>
        private async Task InstallPackageInternal(PackageVersionInfo package, IProgress <double> progress, CancellationToken cancellationToken)
        {
            // Do the install
            await PerformPackageInstallation(progress, package, cancellationToken).ConfigureAwait(false);

            var extension = Path.GetExtension(package.targetFilename) ?? "";

            // Do plugin-specific processing
            if (!string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase) && !string.Equals(extension, ".rar", StringComparison.OrdinalIgnoreCase) && !string.Equals(extension, ".7z", StringComparison.OrdinalIgnoreCase))
            {
                // Set last update time if we were installed before
                var plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase))
                             ?? _applicationHost.Plugins.FirstOrDefault(p => p.Name.Equals(package.name, StringComparison.OrdinalIgnoreCase));

                if (plugin != null)
                {
                    OnPluginUpdated(plugin, package);
                }
                else
                {
                    OnPluginInstalled(package);
                }
            }
        }
Exemplo n.º 24
0
        private async Task PerformPackageInstallation(IProgress <double> progress, string target, PackageVersionInfo package, CancellationToken cancellationToken)
        {
            // Target based on if it is an archive or single assembly
            //  zip archives are assumed to contain directory structures relative to our ProgramDataPath
            var extension = Path.GetExtension(package.targetFilename);
            var isArchive = string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".rar", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".7z", StringComparison.OrdinalIgnoreCase);

            if (target == null)
            {
                target = Path.Combine(isArchive ? _appPaths.TempUpdatePath : _appPaths.PluginsPath, package.targetFilename);
            }

            // Download to temporary file so that, if interrupted, it won't destroy the existing installation
            var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
            {
                Url = package.sourceUrl,
                CancellationToken = cancellationToken,
                Progress          = progress
            }).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            // Validate with a checksum
            var packageChecksum = string.IsNullOrWhiteSpace(package.checksum) ? Guid.Empty : new Guid(package.checksum);

            if (!packageChecksum.Equals(Guid.Empty)) // support for legacy uploads for now
            {
                using (var stream = _fileSystem.OpenRead(tempFile))
                {
                    var check = Guid.Parse(BitConverter.ToString(_cryptographyProvider.ComputeMD5(stream)).Replace("-", string.Empty));
                    if (check != packageChecksum)
                    {
                        throw new Exception(string.Format("Download validation failed for {0}.  Probably corrupted during transfer.", package.name));
                    }
                }
            }

            cancellationToken.ThrowIfCancellationRequested();

            // Success - move it to the real target
            try
            {
                _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(target));
                _fileSystem.CopyFile(tempFile, target, true);
                //If it is an archive - write out a version file so we know what it is
                if (isArchive)
                {
                    _fileSystem.WriteAllText(target + ".ver", package.versionStr);
                }
            }
            catch (IOException ex)
            {
                _logger.LogError(ex, "Error attempting to move file from {TempFile} to {TargetFile}", tempFile, target);
                throw;
            }

            try
            {
                _fileSystem.DeleteFile(tempFile);
            }
            catch (IOException ex)
            {
                // Don't fail because of this
                _logger.LogError(ex, "Error deleting temp file {TempFile}", tempFile);
            }
        }
Exemplo n.º 25
0
 /// <summary>
 /// Updates the application.
 /// </summary>
 /// <param name="package">The package that contains the update</param>
 /// <param name="cancellationToken">The cancellation token.</param>
 /// <param name="progress">The progress.</param>
 /// <returns>Task.</returns>
 public abstract Task UpdateApplication(PackageVersionInfo package, CancellationToken cancellationToken,
                                        IProgress <double> progress);
Exemplo n.º 26
0
        /// <summary>
        /// Installs the package.
        /// </summary>
        /// <param name="package">The package.</param>
        /// <param name="progress">The progress.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>Task.</returns>
        /// <exception cref="System.ArgumentNullException">package</exception>
        public async Task InstallPackage(PackageVersionInfo package, IProgress <double> progress, CancellationToken cancellationToken)
        {
            if (package == null)
            {
                throw new ArgumentNullException("package");
            }

            if (progress == null)
            {
                throw new ArgumentNullException("progress");
            }

            var installationInfo = new InstallationInfo
            {
                Id           = Guid.NewGuid().ToString("N"),
                Name         = package.name,
                AssemblyGuid = package.guid,
                UpdateClass  = package.classification,
                Version      = package.versionStr
            };

            var innerCancellationTokenSource = new CancellationTokenSource();

            var tuple = new Tuple <InstallationInfo, CancellationTokenSource>(installationInfo, innerCancellationTokenSource);

            // Add it to the in-progress list
            lock (CurrentInstallations)
            {
                CurrentInstallations.Add(tuple);
            }

            var innerProgress = new ActionableProgress <double>();

            // Whenever the progress updates, update the outer progress object and InstallationInfo
            innerProgress.RegisterAction(percent =>
            {
                progress.Report(percent);

                installationInfo.PercentComplete = percent;
            });

            var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token).Token;

            var installationEventArgs = new InstallationEventArgs
            {
                InstallationInfo   = installationInfo,
                PackageVersionInfo = package
            };

            EventHelper.FireEventIfNotNull(PackageInstalling, this, installationEventArgs, _logger);

            try
            {
                await InstallPackageInternal(package, innerProgress, linkedToken).ConfigureAwait(false);

                lock (CurrentInstallations)
                {
                    CurrentInstallations.Remove(tuple);
                }

                progress.Report(100);

                CompletedInstallations.Add(installationInfo);

                EventHelper.FireEventIfNotNull(PackageInstallationCompleted, this, installationEventArgs, _logger);
            }
            catch (OperationCanceledException)
            {
                lock (CurrentInstallations)
                {
                    CurrentInstallations.Remove(tuple);
                }

                _logger.Info("Package installation cancelled: {0} {1}", package.name, package.versionStr);

                EventHelper.FireEventIfNotNull(PackageInstallationCancelled, this, installationEventArgs, _logger);

                throw;
            }
            catch (Exception ex)
            {
                _logger.ErrorException("Package installation failed", ex);

                lock (CurrentInstallations)
                {
                    CurrentInstallations.Remove(tuple);
                }

                EventHelper.FireEventIfNotNull(PackageInstallationFailed, this, new InstallationFailedEventArgs
                {
                    InstallationInfo = installationInfo,
                    Exception        = ex
                }, _logger);

                throw;
            }
            finally
            {
                // Dispose the progress object and remove the installation from the in-progress list
                innerProgress.Dispose();
                tuple.Item2.Dispose();
            }
        }
Exemplo n.º 27
0
 private Version GetPackageVersion(PackageVersionInfo version)
 {
     return(new Version(ValueOrDefault(version.versionStr, "0.0.0.1")));
 }
Exemplo n.º 28
0
        private void UpgradeNow(FtpClient client, PackageVersionInfo diffVersionInfo)
        {
            this.RaiseUpgradeStarted();
            float percent = 0f;

            try
            {
                Directory.CreateDirectory(_targetFolder);
                var currVersionInfo = this._versionService.ComputeVersionInfo(_targetFolder);
                XmlSerializer.SaveToFile(diffVersionInfo, Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "versionInfo_diff.xml"));
                XmlSerializer.SaveToFile(currVersionInfo, Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "versionInfo_curr.xml"));
                this.RaiseUpgradeProgress(percent += 0.01f);
            }
            catch (Exception exc)
            {
                string    msg  = "计算版本信息文件出错";
                Exception nexc = new CreateVersionInfoException(msg, exc);
                this.RaiseUpgradeEnded(msg, nexc);
                throw nexc;
            }
            //下载新版本,占比 90%
            string curentDownFile = string.Empty;

            try
            {
                DirectoryInfo newVersionTemp = Directory.CreateDirectory(NewVersionTempFolder);
                client.RetryAttempts = 3;
                long downLength = 0;
                foreach (var item in diffVersionInfo.Files)
                {
                    curentDownFile = item.File;
                    client.DownloadFile(Path.Combine(newVersionTemp.FullName, item.File.TrimStart('\\', '/')), item.File.Replace('\\', '/'), true, FtpVerify.Retry);
                    downLength += item.Length;
                    this.RaiseUpgradeProgress(percent += (float)Math.Round((downLength * 1.0 / diffVersionInfo.TotalLength * 0.9), 2));
                }
                XmlSerializer.SaveToFile(diffVersionInfo, Path.Combine(newVersionTemp.FullName, VersionFileName));
            }
            catch (Exception exc)
            {
                string    msg  = string.Format("下载新版文件({0})出错", curentDownFile);
                Exception nexc = new DownFileException(msg, exc);
                this.RaiseUpgradeEnded(msg, nexc);
                throw nexc;
            }
            //验证文件合法性,防篡改,占比 1%
            try
            {
                if (!this._versionService.Verify(diffVersionInfo, NewVersionTempFolder))
                {
                    string    msg  = "新版文件不合法";
                    Exception nexc = new UnlawfulException(msg, null);
                    this.RaiseUpgradeEnded(msg, nexc);
                    throw nexc;
                }
                this.RaiseUpgradeProgress(percent += 0.01f);
            }
            catch (UnlawfulException)
            {
                throw;
            }
            catch (Exception exc)
            {
                string    msg  = "新版文件验证出错";
                Exception nexc = new UnlawfulException(msg, exc);
                this.RaiseUpgradeEnded(msg, nexc);
                throw nexc;
            }
            //备份当前版本,占比 3%
            try
            {
                CopyVersionFile(diffVersionInfo, this._targetFolder, LastVersionBakFolder);
                this.RaiseUpgradeProgress(percent += 0.03f);
            }
            catch (Exception exc)
            {
                string    msg  = "版本当前版本出错";
                Exception nexc = new BackupFileException(msg, exc);
                this.RaiseUpgradeEnded(msg, nexc);
                throw nexc;
            }
            //新版覆盖当前版,占比 4%
            try
            {
                CopyVersionFile(diffVersionInfo, NewVersionTempFolder, this._targetFolder);
                XmlSerializer.SaveToFile(diffVersionInfo, Path.Combine(this._targetFolder, VersionFileName));
                this.RaiseUpgradeProgress(percent += 0.04f);
            }
            catch (Exception exc)
            {
                try
                {
                    CopyVersionFile(diffVersionInfo, LastVersionBakFolder, this._targetFolder);
                }
                catch (Exception exc1)
                {
                    string    msg1  = string.Format("新版覆盖当前版出错后回滚出错", curentDownFile);
                    Exception nexc1 = new RollbackException(msg1, exc1);
                    LogHelper.Log(nexc1, "升级忽略错误");
                }
                string    msg  = string.Format("新版覆盖当前版出错", curentDownFile);
                Exception nexc = new ReplaceNewVersionException(msg, exc);
                this.RaiseUpgradeEnded(msg, nexc);
                throw nexc;
            }
            //删除临时文件,占比 1%
            try
            {
                Directory.Delete(NewVersionTempFolder, true);
                Directory.Delete(LastVersionBakFolder, true);
                this.RaiseUpgradeProgress(percent += 0.01f);
            }
            catch (Exception exc)
            {
                string    msg  = string.Format("删除临时文件出错", curentDownFile);
                Exception nexc = new DeleteTempFileException(msg, exc);
                LogHelper.Log(nexc, "升级忽略错误");
            }
            this.RaiseUpgradeProgress(percent = 1f);
            this.RaiseUpgradeEnded();
        }
Exemplo n.º 29
0
        private async Task PerformPackageInstallation(IProgress <double> progress, string target, PackageVersionInfo package, CancellationToken cancellationToken)
        {
            var extension = Path.GetExtension(package.targetFilename);
            var isArchive = string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase);

            if (!isArchive)
            {
                _logger.LogError("Only zip packages are supported. {Filename} is not a zip archive.", package.targetFilename);
                return;
            }

            if (target == null)
            {
                target = Path.Combine(_appPaths.PluginsPath, Path.GetFileNameWithoutExtension(package.targetFilename));
            }

            // Download to temporary file so that, if interrupted, it won't destroy the existing installation
            var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
            {
                Url = package.sourceUrl,
                CancellationToken = cancellationToken,
                Progress          = progress
            }).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            // TODO: Validate with a checksum, *properly*

            // Success - move it to the real target
            try
            {
                using (var stream = File.OpenRead(tempFile))
                {
                    _zipClient.ExtractAllFromZip(stream, target, true);
                }
            }
            catch (IOException ex)
            {
                _logger.LogError(ex, "Error attempting to extract {TempFile} to {TargetFile}", tempFile, target);
                throw;
            }

            try
            {
                _fileSystem.DeleteFile(tempFile);
            }
            catch (IOException ex)
            {
                // Don't fail because of this
                _logger.LogError(ex, "Error deleting temp file {TempFile}", tempFile);
            }
        }
Exemplo n.º 30
0
        /// <summary>
        /// 添加版本记录
        /// </summary>
        /// <param name=""></param>
        public void AddVersionRecord(string branchName, long versionCode, string versionName, string versionDesc, bool saveBinary, bool dialog = true, bool log = true)
        {
            //编辑器那边限制了不能添加“比最大版本号更小的版本号”的版本,(也就是说版本号只能变大),但是这里实际上没做这个限制。以后如果有需要,可以让编辑器UI上去掉限制。
            if (mDict_Branches.TryGetValue(branchName, out var branch))
            {
                //判断一下版本号啦
                if (versionCode >= 0 && !branch.IsVersionCodeExists(versionCode))
                {
                    bool isMainPackage      = (branch.BType == VersionBranch.BranchType.MainPackage);
                    bool flag_process_error = false; //处理文件过程中如果出错则中断操作且不记录数据

                    string platform_name = XPlatformUtil.GetNameText(branch.Platform);
                    string source_packages_folder_path = VFSEditorUtil.GetSourcePackagesFolderPath(platform_name);
                    string data_folder = VFSEditorUtil.GetVersionDataFolderPath_InProjectVersion(branch.BranchName, versionCode); //存放数据的地方

                    string build_id = string.Empty;

                    try
                    {
                        XDirectory.DeleteIfExists(data_folder, true);
                        Directory.CreateDirectory(data_folder);

                        //复制并存档assets_hash文件
                        string assets_hash_path        = isMainPackage ? VFSEditorUtil.GetMainPackage_AssetsHashFilePath_InSourcePackagesFolder(platform_name) : VFSEditorUtil.GetExtensionGroup_AssetsHashFilePath_InSourcePackagesFolder(platform_name, branch.ExtensionGroupName);
                        string assets_hash_target_path = Path.Combine(data_folder, VFSConst.AssetsHashFileName);
                        if (File.Exists(assets_hash_path))
                        {
                            File.Copy(assets_hash_path, assets_hash_target_path, true);
                        }

                        //复制并存档Manifest文件
                        string manifest_target_path = VFSEditorUtil.GetVersionData_Manifest_FolderOrFilePath(!isMainPackage, branchName, versionCode);
                        string manifest_path        = isMainPackage ? VFSEditorUtil.GetMainPackage_AssetBundleManifestsFolderPath_InSourcePackagesFolder(platform_name) : VFSEditorUtil.GetExtensionGroup_AssetBundleManifestPath_InInSourcePackagesFolder(platform_name, branch.ExtensionGroupName);
                        if (isMainPackage)
                        {
                            if (Directory.Exists(manifest_path))
                            {
                                XDirectory.CopyDir(manifest_path, manifest_target_path);
                            }
                        }
                        else
                        {
                            if (File.Exists(manifest_path))
                            {
                                File.Copy(manifest_path, manifest_target_path);
                            }
                        }

                        //复制并存档AssetBundleHashs
                        string ab_hash_path        = isMainPackage ? VFSEditorUtil.GetMainPackage_AssetBundle_HashFiles_FolderPath_InSourcePackagesFolder(platform_name) : VFSEditorUtil.GetExtensionGroup_AssetBundle_HashFiles_Path_InInSourcePackagesFolder(platform_name, branch.ExtensionGroupName);
                        string ab_hash_target_path = VFSEditorUtil.GetVersionData_AssetBundle_HashFile_FolderOrFilePath(!isMainPackage, branchName, versionCode);
                        if (isMainPackage)
                        {
                            if (Directory.Exists(ab_hash_path))
                            {
                                XDirectory.CopyDir(ab_hash_path, ab_hash_target_path);
                            }
                        }
                        else
                        {
                            if (File.Exists(ab_hash_path))
                            {
                                File.Copy(ab_hash_path, ab_hash_target_path);
                            }
                        }

                        //复制并存档vfs config (main package)
                        if (isMainPackage)
                        {
                            string vfs_config_path = VFSUtil.GetVFSConfigFilePath_InPackages(VFSEditorUtil.GetSourcePackagesFolderPath(platform_name));
                            if (File.Exists(vfs_config_path))
                            {
                                string target_path = Path.Combine(data_folder, VFSConst.Config_Runtime_FileName);
                                File.Copy(vfs_config_path, target_path, true);
                            }
                        }

                        //Group Options
                        if (!isMainPackage)
                        {
                            string group_option_path = VFSUtil.GetExtensionPackages_GroupOptions_FilePath(source_packages_folder_path, branch.ExtensionGroupName);
                            if (File.Exists(group_option_path))
                            {
                                string target_path = Path.Combine(data_folder, VFSConst.ExtensionGroup_GroupOption_FileName);
                                File.Copy(group_option_path, target_path, true);
                            }
                        }

                        //Group Info
                        if (!isMainPackage)
                        {
                            string group_info_path = VFSUtil.GetExtensionGroup_GroupInfo_Path_InGroupPath(VFSUtil.GetExtensionGroupFolder(source_packages_folder_path, branch.ExtensionGroupName));
                            if (File.Exists(group_info_path))
                            {
                                string target_path = Path.Combine(data_folder, VFSConst.VFS_ExtensionGroupInfo_FileName);
                                File.Copy(group_info_path, target_path, true);
                            }
                        }

                        //复制并存档editor build info
                        string editor_build_info_path = VFSEditorUtil.Get_EditorBuildInfoPath(VFSEditorUtil.GetSourcePackagesFolderPath(platform_name));
                        if (File.Exists(editor_build_info_path))
                        {
                            string target_path = VFSEditorUtil.GetVersionData_EditorBuildInfo_Path(branchName, versionCode);
                            File.Copy(editor_build_info_path, target_path);
                        }

                        //复制并存档 build info
                        string build_info_path = VFSUtil.GetMainPackage_BuildInfo_Path(VFSEditorUtil.GetSourcePackagesFolderPath(platform_name));
                        if (File.Exists(build_info_path))
                        {
                            //存档
                            string target_path = VFSEditorUtil.GetVersionData_BuildInfo_Path(branchName, versionCode);
                            File.Copy(build_info_path, target_path);

                            //反写版本信息到source package
                            string build_info_json = File.ReadAllText(target_path, Encoding.UTF8);
                            var    obj             = JsonUtility.FromJson <BuildInfo>(build_info_json);

                            build_id = obj.BuildID;

                            //写出版本信息
                            var version_info = new PackageVersionInfo
                            {
                                version     = versionCode,
                                versionName = versionName,
                                buildId     = obj.BuildID,
                                branch      = branch.BranchName
                            };
                            string version_info_path = isMainPackage ? VFSEditorUtil.Get_MainPackage_PackageVersionFilePath_InSourcePackages(platform_name) : VFSEditorUtil.Get_ExtensionGroups_PackageVersionFilePath_InSourcePackages(ref platform_name, ref branch.ExtensionGroupName);
                            XFile.DeleteIfExists(version_info_path);
                            XConfig.SaveJson(version_info, version_info_path, AssetLoadType.SystemIO);

                            //检查当前StreamingAssets中是否有与之build id一致的情况,如果有,也写出
                            if (isMainPackage)
                            {
                                string buildinfo_in_stream = VFSUtil.GetMainPackage_BuildInfo_Path(VFSUtil.GetPackagesRootFolderInStreamingAssets(platform_name));
                                if (File.Exists(buildinfo_in_stream))
                                {
                                    try
                                    {
                                        var obj_stream = XConfig.GetJson <BuildInfo>(buildinfo_in_stream, AssetLoadType.SystemIO, false);
                                        if (obj_stream.BuildID == obj.BuildID)
                                        {
                                            //一致,写出
                                            string target_stream = VFSUtil.GetMainPackage_VersionInfo_Path(VFSUtil.GetPackagesRootFolderInStreamingAssets(platform_name));
                                            XConfig.SaveJson(version_info, target_stream, AssetLoadType.SystemIO);
                                        }
                                    }
                                    catch { }
                                }
                            }
                            else
                            {
                                string buildinfo_in_stream = VFSUtil.GetExtensionGroup_BuildInfo_Path(VFSUtil.GetPackagesRootFolderInStreamingAssets(platform_name), branch.ExtensionGroupName);
                                if (File.Exists(buildinfo_in_stream))
                                {
                                    try
                                    {
                                        var obj_stream = XConfig.GetJson <BuildInfo>(buildinfo_in_stream, AssetLoadType.SystemIO, false);
                                        if (obj_stream.BuildID == obj.BuildID)
                                        {
                                            //一致,写出
                                            string target_stream = VFSUtil.GetExtensionGroup_VersionInfo_Path(VFSUtil.GetPackagesRootFolderInStreamingAssets(platform_name), branch.ExtensionGroupName);
                                            XConfig.SaveJson(version_info, target_stream, AssetLoadType.SystemIO);
                                        }
                                    }
                                    catch { }
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        XDirectory.DeleteIfExists(data_folder, true);
                        flag_process_error = true;
                        throw e;
                    }

                    //保存二进制文件
                    if (saveBinary && !flag_process_error)
                    {
                        string binary_path = VFSEditorUtil.Get_AssetsBinaryFolderPath_InVersion(branchName, versionCode);

                        try
                        {
                            long total_count = 0;
                            //把所有二进制文件直接全拷进去
                            string binary_path_temp        = Path.Combine(binary_path, "temp");
                            string binary_path_temp_remote = Path.Combine(binary_path, "temp_remote");
                            XDirectory.DeleteIfExists(binary_path_temp, true);
                            Directory.CreateDirectory(binary_path_temp);

                            if (isMainPackage)
                            {
                                XDirectory.DeleteIfExists(binary_path_temp_remote, true);
                                Directory.CreateDirectory(binary_path_temp_remote);
                            }


                            //移动文件
                            if (isMainPackage)
                            {
                                string   local_path     = VFSEditorUtil.Get_MainPackage_AssetsFolderPath_InSourcePackages(platform_name);
                                int      local_path_len = local_path.Length + 1;
                                string[] local_files    = Directory.GetFiles(local_path, "*.*", SearchOption.AllDirectories);
                                if (local_files != null && local_files.Length > 0)
                                {
                                    ArrayUtil.RemoveDuplicationElements(ref local_files);
                                    foreach (var item in local_files)
                                    {
                                        total_count++;
                                        string pure_path   = item.Substring(local_path_len, item.Length - local_path_len);
                                        string target_path = Path.Combine(binary_path_temp, pure_path);
                                        XDirectory.CreateIfNotExists(Path.GetDirectoryName(target_path));
                                        File.Copy(item, target_path);
                                    }
                                }

                                string remote_path = VFSEditorUtil.Get_MainPackage_RemoteAssetsFolderPath_InSourcePackages(platform_name);
                                if (Directory.Exists(remote_path))
                                {
                                    int      remote_path_len = remote_path.Length + 1;
                                    string[] remote_files    = Directory.GetFiles(remote_path, "*.*", SearchOption.AllDirectories);
                                    if (remote_files != null && remote_files.Length > 0)
                                    {
                                        total_count++;
                                        ArrayUtil.RemoveDuplicationElements(ref remote_files);
                                        foreach (var item in remote_files)
                                        {
                                            string pure_path   = item.Substring(remote_path_len, item.Length - remote_path_len);
                                            string target_path = Path.Combine(binary_path_temp_remote, pure_path);
                                            XDirectory.CreateIfNotExists(Path.GetDirectoryName(target_path));
                                            File.Copy(item, target_path);
                                        }
                                    }
                                }
                            }
                            else
                            {
                                string   group_path     = VFSEditorUtil.Get_ExtensionGroupFolderPath_InSourcePackages(platform_name, branch.ExtensionGroupName);
                                int      group_path_len = group_path.Length + 1;
                                string[] group_files    = Directory.GetFiles(group_path, "*.*", SearchOption.AllDirectories);
                                if (group_files != null && group_files.Length > 0)
                                {
                                    total_count++;
                                    ArrayUtil.RemoveDuplicationElements(ref group_files);
                                    foreach (var item in group_files)
                                    {
                                        string pure_path   = item.Substring(group_path_len, item.Length - group_path_len);
                                        string target_path = Path.Combine(binary_path_temp, pure_path);
                                        XDirectory.CreateIfNotExists(Path.GetDirectoryName(target_path));
                                        File.Copy(item, target_path);
                                    }
                                }
                            }

                            long zip_counter   = 0;
                            int  zip_counter_t = 0;

                            //打包
                            string zip_file_path = Path.Combine(binary_path, VFSEditorConst.VFS_VERSION_AssetsBinary_Zip_Name);
                            ZipUtil.ZipDirectory(binary_path_temp, zip_file_path, fileName =>
                            {
                                if (log || dialog)
                                {
                                    zip_counter++;
                                    if (total_count > 100)
                                    {
                                        zip_counter_t++;
                                        if (zip_counter_t >= 20)
                                        {
                                            zip_counter_t = 0;
                                            if (log)
                                            {
                                                Debug.Log($"    Create Zip: {zip_counter}/{total_count}");
                                            }
                                            if (dialog)
                                            {
                                                EditorUtility.DisplayProgressBar("Create Zip", $"{zip_counter}/{total_count}\n{fileName}", zip_counter / total_count);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        if (log)
                                        {
                                            Debug.Log($"    Create Zip: {zip_counter}/{total_count} : {fileName}");
                                        }
                                        if (dialog)
                                        {
                                            EditorUtility.DisplayProgressBar("Create Zip", $"{zip_counter}/{total_count}\n{fileName}", zip_counter / total_count);
                                        }
                                    }
                                }
                            });

                            if (isMainPackage)
                            {
                                string zip_file_path_remote = Path.Combine(binary_path, VFSEditorConst.VFS_VERSION_AssetsBinary_REMOTE_Zip_Name);
                                zip_counter   = 0;
                                zip_counter_t = 0;
                                ZipUtil.ZipDirectory(binary_path_temp_remote, zip_file_path_remote, fileName =>
                                {
                                    if (log || dialog)
                                    {
                                        zip_counter++;
                                        if (total_count > 100)
                                        {
                                            zip_counter_t++;
                                            if (zip_counter_t >= 20)
                                            {
                                                zip_counter_t = 0;
                                                if (log)
                                                {
                                                    Debug.Log($"    Create Zip: {zip_counter}/{total_count}");
                                                }
                                                if (dialog)
                                                {
                                                    EditorUtility.DisplayProgressBar("Create Zip", $"{zip_counter}/{total_count}\n{fileName}", zip_counter / total_count);
                                                }
                                            }
                                        }
                                        else
                                        {
                                            if (log)
                                            {
                                                Debug.Log($"    Create Zip: {zip_counter}/{total_count} : {fileName}");
                                            }
                                            if (dialog)
                                            {
                                                EditorUtility.DisplayProgressBar("Create Zip", $"{zip_counter}/{total_count}\n{fileName}", zip_counter / total_count);
                                            }
                                        }
                                    }
                                });
                            }

                            if (dialog)
                            {
                                EditorUtility.ClearProgressBar(); //上面这个应该是同步方法,不会有时间错乱。(吧
                            }
                            //删除temp
                            XDirectory.DeleteIfExists(binary_path_temp);
                            XDirectory.DeleteIfExists(binary_path_temp_remote);
                        }
                        catch (Exception e)
                        {
                            flag_process_error = true;
                            XDirectory.DeleteIfExists(binary_path);
                            throw e;
                        }
                    }

                    if (!flag_process_error)
                    {
                        //登记到索引
                        var vr = new VersionRecord()
                        {
                            versionCode = versionCode,
                            versionName = versionName,
                            desc        = versionDesc,
                            build_id    = build_id
                        };
                        //记录版本
                        branch.AddVersion(ref vr);

                        //保存版本索引
                        SaveBranchFile(ref branch);
                    }
                }
            }
        }