Example #1
0
        internal static async Task <Version> Update(bool updateOverride = false)
        {
            if (!SharedInfo.BuildInfo.CanUpdate || (GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.None))
            {
                return(null);
            }

            await UpdateSemaphore.WaitAsync().ConfigureAwait(false);

            try {
                ArchiLogger.LogGenericInfo(Strings.UpdateCheckingNewVersion);

                // If backup directory from previous update exists, it's a good idea to purge it now
                string backupDirectory = Path.Combine(SharedInfo.HomeDirectory, SharedInfo.UpdateDirectory);

                if (Directory.Exists(backupDirectory))
                {
                    // It's entirely possible that old process is still running, wait a short moment for eventual cleanup
                    await Task.Delay(5000).ConfigureAwait(false);

                    try {
                        Directory.Delete(backupDirectory, true);
                    } catch (Exception e) {
                        ArchiLogger.LogGenericException(e);

                        return(null);
                    }
                }

                GitHub.ReleaseResponse releaseResponse = await GitHub.GetLatestRelease(GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.Stable).ConfigureAwait(false);

                if (releaseResponse == null)
                {
                    ArchiLogger.LogGenericWarning(Strings.ErrorUpdateCheckFailed);

                    return(null);
                }

                if (string.IsNullOrEmpty(releaseResponse.Tag))
                {
                    ArchiLogger.LogGenericWarning(Strings.ErrorUpdateCheckFailed);

                    return(null);
                }

                Version newVersion = new Version(releaseResponse.Tag);

                ArchiLogger.LogGenericInfo(string.Format(Strings.UpdateVersionInfo, SharedInfo.Version, newVersion));

                if (SharedInfo.Version >= newVersion)
                {
                    if (SharedInfo.Version > newVersion)
                    {
                        ArchiLogger.LogGenericWarning(Strings.WarningPreReleaseVersion);
                        await Task.Delay(15 * 1000).ConfigureAwait(false);
                    }

                    return(newVersion);
                }

                if (!updateOverride && (GlobalConfig.UpdatePeriod == 0))
                {
                    ArchiLogger.LogGenericInfo(Strings.UpdateNewVersionAvailable);
                    await Task.Delay(5000).ConfigureAwait(false);

                    return(null);
                }

                // Auto update logic starts here
                if (releaseResponse.Assets == null)
                {
                    ArchiLogger.LogGenericWarning(Strings.ErrorUpdateNoAssets);

                    return(null);
                }

                string targetFile = SharedInfo.ASF + "-" + SharedInfo.BuildInfo.Variant + ".zip";
                GitHub.ReleaseResponse.Asset binaryAsset = releaseResponse.Assets.FirstOrDefault(asset => asset.Name.Equals(targetFile, StringComparison.OrdinalIgnoreCase));

                if (binaryAsset == null)
                {
                    ArchiLogger.LogGenericWarning(Strings.ErrorUpdateNoAssetForThisVersion);

                    return(null);
                }

                if (string.IsNullOrEmpty(binaryAsset.DownloadURL))
                {
                    ArchiLogger.LogNullError(nameof(binaryAsset.DownloadURL));

                    return(null);
                }

                if (!string.IsNullOrEmpty(releaseResponse.ChangelogPlainText))
                {
                    ArchiLogger.LogGenericInfo(releaseResponse.ChangelogPlainText);
                }

                ArchiLogger.LogGenericInfo(string.Format(Strings.UpdateDownloadingNewVersion, newVersion, binaryAsset.Size / 1024 / 1024));

                WebBrowser.BinaryResponse response = await WebBrowser.UrlGetToBinaryWithProgress(binaryAsset.DownloadURL).ConfigureAwait(false);

                if (response?.Content == null)
                {
                    return(null);
                }

                try {
                    using (ZipArchive zipArchive = new ZipArchive(new MemoryStream(response.Content))) {
                        if (!UpdateFromArchive(zipArchive, SharedInfo.HomeDirectory))
                        {
                            ArchiLogger.LogGenericError(Strings.WarningFailed);
                        }
                    }
                } catch (Exception e) {
                    ArchiLogger.LogGenericException(e);

                    return(null);
                }

                if (OS.IsUnix)
                {
                    string executable = Path.Combine(SharedInfo.HomeDirectory, SharedInfo.AssemblyName);

                    if (File.Exists(executable))
                    {
                        OS.UnixSetFileAccessExecutable(executable);
                    }
                }

                ArchiLogger.LogGenericInfo(Strings.UpdateFinished);

                return(newVersion);
            } finally {
                UpdateSemaphore.Release();
            }
        }
Example #2
0
        internal static async Task <Version> CheckAndUpdateProgram(bool updateOverride = false)
        {
            if (Program.GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.None)
            {
                return(null);
            }

            string assemblyFile = Assembly.GetEntryAssembly().Location;

            if (string.IsNullOrEmpty(assemblyFile))
            {
                ArchiLogger.LogNullError(nameof(assemblyFile));
                return(null);
            }

            if (!File.Exists(SharedInfo.VersionFile))
            {
                ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsEmpty, SharedInfo.VersionFile));
                return(null);
            }

            string version;

            try {
                version = await File.ReadAllTextAsync(SharedInfo.VersionFile).ConfigureAwait(false);
            } catch (Exception e) {
                ArchiLogger.LogGenericException(e);
                return(null);
            }

            if (string.IsNullOrEmpty(version))
            {
                ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsInvalid, SharedInfo.VersionFile));
                return(null);
            }

            version = version.TrimEnd();
            if (string.IsNullOrEmpty(version) || !IsValidVersion(version))
            {
                ArchiLogger.LogGenericError(string.Format(Strings.ErrorIsInvalid, SharedInfo.VersionFile));
                return(null);
            }

            if (version.Equals(DefaultVersion))
            {
                return(null);
            }

            if ((AutoUpdatesTimer == null) && Program.GlobalConfig.AutoUpdates)
            {
                TimeSpan autoUpdatePeriod = TimeSpan.FromHours(AutoUpdatePeriodInHours);

                AutoUpdatesTimer = new Timer(
                    async e => await CheckAndUpdateProgram().ConfigureAwait(false),
                    null,
                    autoUpdatePeriod,                    // Delay
                    autoUpdatePeriod                     // Period
                    );

                ArchiLogger.LogGenericInfo(string.Format(Strings.AutoUpdateCheckInfo, autoUpdatePeriod.ToHumanReadable()));
            }

            ArchiLogger.LogGenericInfo(Strings.UpdateCheckingNewVersion);

            string targetDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);

            // Cleanup from previous update - update directory for old in-use runtime files
            string backupDirectory = Path.Combine(targetDirectory, SharedInfo.UpdateDirectory);

            if (Directory.Exists(backupDirectory))
            {
                // It's entirely possible that old process is still running, wait a short moment for eventual cleanup
                await Task.Delay(5000).ConfigureAwait(false);

                try {
                    Directory.Delete(backupDirectory, true);
                } catch (Exception e) {
                    ArchiLogger.LogGenericException(e);
                    return(null);
                }
            }

            // Cleanup from previous update - old non-runtime in-use files
            foreach (string file in Directory.EnumerateFiles(targetDirectory, "*.old", SearchOption.AllDirectories))
            {
                try {
                    File.Delete(file);
                } catch (Exception e) {
                    ArchiLogger.LogGenericException(e);
                    return(null);
                }
            }

            string releaseURL = SharedInfo.GithubReleaseURL + (Program.GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.Stable ? "/latest" : "?per_page=1");

            GitHub.ReleaseResponse releaseResponse;

            if (Program.GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.Stable)
            {
                releaseResponse = await Program.WebBrowser.UrlGetToJsonResultRetry <GitHub.ReleaseResponse>(releaseURL).ConfigureAwait(false);

                if (releaseResponse == null)
                {
                    ArchiLogger.LogGenericWarning(Strings.ErrorUpdateCheckFailed);
                    return(null);
                }
            }
            else
            {
                List <GitHub.ReleaseResponse> releases = await Program.WebBrowser.UrlGetToJsonResultRetry <List <GitHub.ReleaseResponse> >(releaseURL).ConfigureAwait(false);

                if ((releases == null) || (releases.Count == 0))
                {
                    ArchiLogger.LogGenericWarning(Strings.ErrorUpdateCheckFailed);
                    return(null);
                }

                releaseResponse = releases[0];
            }

            if (string.IsNullOrEmpty(releaseResponse.Tag))
            {
                ArchiLogger.LogGenericWarning(Strings.ErrorUpdateCheckFailed);
                return(null);
            }

            Version newVersion = new Version(releaseResponse.Tag);

            ArchiLogger.LogGenericInfo(string.Format(Strings.UpdateVersionInfo, SharedInfo.Version, newVersion));

            if (SharedInfo.Version == newVersion)
            {
                return(SharedInfo.Version);
            }

            if (SharedInfo.Version > newVersion)
            {
                ArchiLogger.LogGenericWarning(Strings.WarningPreReleaseVersion);
                await Task.Delay(15 * 1000).ConfigureAwait(false);

                return(SharedInfo.Version);
            }

            if (!updateOverride && !Program.GlobalConfig.AutoUpdates)
            {
                ArchiLogger.LogGenericInfo(Strings.UpdateNewVersionAvailable);
                await Task.Delay(5000).ConfigureAwait(false);

                return(null);
            }

            // Auto update logic starts here
            if (releaseResponse.Assets == null)
            {
                ArchiLogger.LogGenericWarning(Strings.ErrorUpdateNoAssets);
                return(null);
            }

            string targetFile = SharedInfo.ASF + "-" + version + ".zip";

            GitHub.ReleaseResponse.Asset binaryAsset = releaseResponse.Assets.FirstOrDefault(asset => asset.Name.Equals(targetFile, StringComparison.OrdinalIgnoreCase));

            if (binaryAsset == null)
            {
                ArchiLogger.LogGenericWarning(Strings.ErrorUpdateNoAssetForThisVersion);
                return(null);
            }

            if (string.IsNullOrEmpty(binaryAsset.DownloadURL))
            {
                ArchiLogger.LogNullError(nameof(binaryAsset.DownloadURL));
                return(null);
            }

            ArchiLogger.LogGenericInfo(string.Format(Strings.UpdateDownloadingNewVersion, newVersion, binaryAsset.Size / 1024 / 1024));

            byte[] result = await Program.WebBrowser.UrlGetToBytesRetry(binaryAsset.DownloadURL).ConfigureAwait(false);

            if (result == null)
            {
                return(null);
            }

            try {
                using (ZipArchive zipArchive = new ZipArchive(new MemoryStream(result))) {
                    UpdateFromArchive(zipArchive, targetDirectory);
                }
            } catch (Exception e) {
                ArchiLogger.LogGenericException(e);
                return(null);
            }

            if (IsUnixVersion(version))
            {
                string executable = Path.Combine(targetDirectory, SharedInfo.AssemblyName);
                if (File.Exists(executable))
                {
                    OS.UnixSetFileAccessExecutable(executable);
                }
            }

            ArchiLogger.LogGenericInfo(Strings.UpdateFinished);
            await RestartOrExit().ConfigureAwait(false);

            return(newVersion);
        }
Example #3
0
        internal static GlobalConfig Load(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                ASF.ArchiLogger.LogNullError(nameof(filePath));
                return(null);
            }

            if (!File.Exists(filePath))
            {
                return(null);
            }

            GlobalConfig globalConfig;

            try {
                globalConfig = JsonConvert.DeserializeObject <GlobalConfig>(File.ReadAllText(filePath));
            } catch (Exception e) {
                ASF.ArchiLogger.LogGenericException(e);
                return(null);
            }

            if (globalConfig == null)
            {
                ASF.ArchiLogger.LogNullError(nameof(globalConfig));
                return(null);
            }

            // User might not know what he's doing
            // Ensure that he can't screw core ASF variables
            if (globalConfig.MaxFarmingTime == 0)
            {
                ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorConfigPropertyInvalid, nameof(globalConfig.MaxFarmingTime), globalConfig.MaxFarmingTime));
                return(null);
            }

            if (globalConfig.FarmingDelay == 0)
            {
                ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorConfigPropertyInvalid, nameof(globalConfig.FarmingDelay), globalConfig.FarmingDelay));
                return(null);
            }

            if (globalConfig.ConnectionTimeout == 0)
            {
                ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorConfigPropertyInvalid, nameof(globalConfig.ConnectionTimeout), globalConfig.ConnectionTimeout));
                return(null);
            }

            if (globalConfig.IPCPort == 0)
            {
                ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorConfigPropertyInvalid, nameof(globalConfig.IPCPort), globalConfig.IPCPort));
                return(null);
            }

            if (globalConfig.SteamProtocols.HasFlag(ProtocolTypes.WebSocket) && !OS.SupportsWebSockets())
            {
                globalConfig.SteamProtocols &= ~ProtocolTypes.WebSocket;
                if (globalConfig.SteamProtocols == 0)
                {
                    globalConfig.SteamProtocols = ProtocolTypes.Tcp;
                }
            }

            GlobalConfig result = globalConfig;

            return(result);
        }
Example #4
0
File: ASF.cs Project: noiresol/AF3
        internal static async Task <Version> CheckAndUpdateProgram(bool updateOverride = false)
        {
            if (!SharedInfo.BuildInfo.CanUpdate || (Program.GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.None))
            {
                return(null);
            }

            if ((AutoUpdatesTimer == null) && (Program.GlobalConfig.UpdatePeriod > 0))
            {
                TimeSpan autoUpdatePeriod = TimeSpan.FromHours(Program.GlobalConfig.UpdatePeriod);

                AutoUpdatesTimer = new Timer(
                    async e => await CheckAndUpdateProgram().ConfigureAwait(false),
                    null,
                    autoUpdatePeriod,                    // Delay
                    autoUpdatePeriod                     // Period
                    );

                ArchiLogger.LogGenericInfo(string.Format(Strings.AutoUpdateCheckInfo, autoUpdatePeriod.ToHumanReadable()));
            }

            ArchiLogger.LogGenericInfo(Strings.UpdateCheckingNewVersion);

            // Cleanup from previous update - update directory for old in-use runtime files
            string backupDirectory = Path.Combine(SharedInfo.HomeDirectory, SharedInfo.UpdateDirectory);

            if (Directory.Exists(backupDirectory))
            {
                // It's entirely possible that old process is still running, wait a short moment for eventual cleanup
                await Task.Delay(5000).ConfigureAwait(false);

                try {
                    Directory.Delete(backupDirectory, true);
                } catch (Exception e) {
                    ArchiLogger.LogGenericException(e);
                    return(null);
                }
            }

            // Cleanup from previous update - old non-runtime in-use files
            try {
                foreach (string file in Directory.EnumerateFiles(SharedInfo.HomeDirectory, "*.old", SearchOption.AllDirectories))
                {
                    File.Delete(file);
                }
            } catch (Exception e) {
                ArchiLogger.LogGenericException(e);
                return(null);
            }

            string releaseURL = SharedInfo.GithubReleaseURL + (Program.GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.Stable ? "/latest" : "?per_page=1");

            GitHub.ReleaseResponse releaseResponse;

            if (Program.GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.Stable)
            {
                WebBrowser.ObjectResponse <GitHub.ReleaseResponse> objectResponse = await Program.WebBrowser.UrlGetToJsonObject <GitHub.ReleaseResponse>(releaseURL).ConfigureAwait(false);

                if (objectResponse?.Content == null)
                {
                    ArchiLogger.LogGenericWarning(Strings.ErrorUpdateCheckFailed);
                    return(null);
                }

                releaseResponse = objectResponse.Content;
            }
            else
            {
                WebBrowser.ObjectResponse <List <GitHub.ReleaseResponse> > objectResponse = await Program.WebBrowser.UrlGetToJsonObject <List <GitHub.ReleaseResponse> >(releaseURL).ConfigureAwait(false);

                if ((objectResponse?.Content == null) || (objectResponse.Content.Count == 0))
                {
                    ArchiLogger.LogGenericWarning(Strings.ErrorUpdateCheckFailed);
                    return(null);
                }

                releaseResponse = objectResponse.Content[0];
            }

            if (string.IsNullOrEmpty(releaseResponse.Tag))
            {
                ArchiLogger.LogGenericWarning(Strings.ErrorUpdateCheckFailed);
                return(null);
            }

            Version newVersion = new Version(releaseResponse.Tag);

            ArchiLogger.LogGenericInfo(string.Format(Strings.UpdateVersionInfo, SharedInfo.Version, newVersion));

            if (SharedInfo.Version == newVersion)
            {
                return(SharedInfo.Version);
            }

            if (SharedInfo.Version > newVersion)
            {
                ArchiLogger.LogGenericWarning(Strings.WarningPreReleaseVersion);
                await Task.Delay(15 * 1000).ConfigureAwait(false);

                return(SharedInfo.Version);
            }

            if (!updateOverride && (Program.GlobalConfig.UpdatePeriod == 0))
            {
                ArchiLogger.LogGenericInfo(Strings.UpdateNewVersionAvailable);
                await Task.Delay(5000).ConfigureAwait(false);

                return(null);
            }

            // Auto update logic starts here
            if (releaseResponse.Assets == null)
            {
                ArchiLogger.LogGenericWarning(Strings.ErrorUpdateNoAssets);
                return(null);
            }

            string targetFile = SharedInfo.ASF + "-" + SharedInfo.BuildInfo.Variant + ".zip";

            GitHub.ReleaseResponse.Asset binaryAsset = releaseResponse.Assets.FirstOrDefault(asset => asset.Name.Equals(targetFile, StringComparison.OrdinalIgnoreCase));

            if (binaryAsset == null)
            {
                ArchiLogger.LogGenericWarning(Strings.ErrorUpdateNoAssetForThisVersion);
                return(null);
            }

            if (string.IsNullOrEmpty(binaryAsset.DownloadURL))
            {
                ArchiLogger.LogNullError(nameof(binaryAsset.DownloadURL));
                return(null);
            }

            ArchiLogger.LogGenericInfo(string.Format(Strings.UpdateDownloadingNewVersion, newVersion, binaryAsset.Size / 1024 / 1024));

            WebBrowser.BinaryResponse response = await Program.WebBrowser.UrlGetToBinaryWithProgress(binaryAsset.DownloadURL).ConfigureAwait(false);

            if (response?.Content == null)
            {
                return(null);
            }

            try {
                using (ZipArchive zipArchive = new ZipArchive(new MemoryStream(response.Content))) {
                    if (!UpdateFromArchive(zipArchive, SharedInfo.HomeDirectory))
                    {
                        ArchiLogger.LogGenericError(Strings.WarningFailed);
                    }
                }
            } catch (Exception e) {
                ArchiLogger.LogGenericException(e);
                return(null);
            }

            if (OS.IsUnix)
            {
                string executable = Path.Combine(SharedInfo.HomeDirectory, SharedInfo.AssemblyName);
                if (File.Exists(executable))
                {
                    OS.UnixSetFileAccessExecutable(executable);
                }
            }

            ArchiLogger.LogGenericInfo(Strings.UpdateFinished);
            await RestartOrExit().ConfigureAwait(false);

            return(newVersion);
        }