public UpdateManager(string urlOrPath, string applicationName = null, string rootDirectory = null, IFileDownloader urlDownloader = null) { Contract.Requires(!String.IsNullOrEmpty(urlOrPath)); Contract.Requires(!String.IsNullOrEmpty(applicationName)); updateUrlOrPath = urlOrPath; this.applicationName = applicationName ?? UpdateManager.getApplicationName(); if (urlDownloader != null) { this.urlDownloader = urlDownloader; } else { this.urlDownloader = (Utility.IsFtpUrl(urlOrPath) ? (IFileDownloader) new FtpFileDownloader() : new FileDownloader()); } if (rootDirectory != null) { this.rootAppDirectory = Path.Combine(rootDirectory, this.applicationName); return; } this.rootAppDirectory = Path.Combine(rootDirectory ?? GetLocalAppDataDirectory(), this.applicationName); }
public static ReleasePackage GetPreviousRelease(IEnumerable <ReleaseEntry> releaseEntries, IReleasePackage package, string targetDir, string prevReleasePath = null, IFullLogger log = null) { { if (releaseEntries == null || !releaseEntries.Any()) { return(null); } var first = releaseEntries .Where(x => x.IsDelta == false).Where(x => x.IsDelta == false) .Where(x => x.Version < package.ToSemanticVersion()).Where(x => x.Version < package.ToSemanticVersion()) .OrderByDescending(x => x.Version).OrderByDescending(x => x.Version) .Select(x => new ReleasePackage(Path.Combine(targetDir, x.Filename), true)) .FirstOrDefault(); if (first != null) { var prevReleaseFilePath = Path.Combine(targetDir, first.SuggestedReleaseFileName); if (!File.Exists(prevReleaseFilePath) && !string.IsNullOrEmpty(prevReleasePath)) { IFileDownloader downloader; if (Utility.IsHttpUrl(prevReleasePath)) { downloader = new FileDownloader(); } else if (Utility.IsFtpUrl(prevReleasePath)) { downloader = new FtpFileDownloader(); } else { return(null); } try { downloader.DownloadFile(Path.Combine(prevReleasePath, first.SuggestedReleaseFileName), prevReleaseFilePath, null); } catch (Exception) { return(null); } } if (File.Exists(prevReleaseFilePath)) { return(new ReleasePackage(prevReleaseFilePath, true)); } } return(null); } }
public async Task DownloadReleases(string updateUrlOrPath, IEnumerable <ReleaseEntry> releasesToDownload, Action <int> progress = null, IFileDownloader urlDownloader = null) { progress = progress ?? (_ => { }); if (urlDownloader == null && Utility.IsHttpUrl(updateUrlOrPath)) { urlDownloader = new FileDownloader(); } else if (urlDownloader == null && Utility.IsFtpUrl(updateUrlOrPath)) { urlDownloader = new FtpFileDownloader(); } var packagesDirectory = Path.Combine(rootAppDirectory, "packages"); double current = 0; double toIncrement = 100.0 / releasesToDownload.Count(); if (Utility.IsHttpUrl(updateUrlOrPath) || Utility.IsFtpUrl(updateUrlOrPath)) { // From Internet await releasesToDownload.ForEachAsync(async x => { var targetFile = Path.Combine(packagesDirectory, x.Filename); double component = 0; await downloadRelease(updateUrlOrPath, x, urlDownloader, targetFile, p => { lock (progress) { current -= component; component = toIncrement / 100.0 * p; progress((int)Math.Round(current += component)); } }); checksumPackage(x); }); } else { // From Disk await releasesToDownload.ForEachAsync(x => { var targetFile = Path.Combine(packagesDirectory, x.Filename); File.Copy( Path.Combine(updateUrlOrPath, x.Filename), targetFile, true); lock (progress) progress((int)Math.Round(current += toIncrement)); checksumPackage(x); }); } }
public async Task <UpdateInfo> CheckForUpdate( string localReleaseFile, string updateUrlOrPath, bool ignoreDeltaUpdates = false, Action <int> progress = null, IFileDownloader urlDownloader = null) { progress = progress ?? (_ => { }); var localReleases = Enumerable.Empty <ReleaseEntry>(); var stagingId = getOrCreateStagedUserId(); bool shouldInitialize = false; try { localReleases = Utility.LoadLocalReleases(localReleaseFile); } catch (Exception ex) { // Something has gone pear-shaped, let's start from scratch this.Log().WarnException("Failed to load local releases, starting from scratch", ex); shouldInitialize = true; } if (shouldInitialize) { await initializeClientAppDirectory(); } string releaseFile; var latestLocalRelease = localReleases.Count() > 0 ? localReleases.MaxBy(x => x.Version).First() : default(ReleaseEntry); // Fetch the remote RELEASES file, whether it's a local dir or an // HTTP URL if (Utility.IsHttpUrl(updateUrlOrPath) || Utility.IsFtpUrl(updateUrlOrPath)) { if (updateUrlOrPath.EndsWith("/")) { updateUrlOrPath = updateUrlOrPath.Substring(0, updateUrlOrPath.Length - 1); } this.Log().Info("Downloading RELEASES file from {0}", updateUrlOrPath); int retries = 3; retry: try { var uri = Utility.AppendPathToUri(new Uri(updateUrlOrPath), "RELEASES"); if (latestLocalRelease != null) { uri = Utility.AddQueryParamsToUri(uri, new Dictionary <string, string> { { "id", latestLocalRelease.PackageName }, { "localVersion", latestLocalRelease.Version.ToString() }, { "arch", Environment.Is64BitOperatingSystem ? "amd64" : "x86" } }); } var data = await urlDownloader.DownloadUrl(uri.ToString()); releaseFile = Encoding.UTF8.GetString(data); } catch (WebException ex) { this.Log().InfoException("Download resulted in WebException (returning blank release list)", ex); if (retries <= 0) { throw; } retries--; goto retry; } progress(33); } else { this.Log().Info("Reading RELEASES file from {0}", updateUrlOrPath); if (!Directory.Exists(updateUrlOrPath)) { var message = String.Format( "The directory {0} does not exist, something is probably broken with your application", updateUrlOrPath); throw new Exception(message); } var fi = new FileInfo(Path.Combine(updateUrlOrPath, "RELEASES")); if (!fi.Exists) { var message = String.Format( "The file {0} does not exist, something is probably broken with your application", fi.FullName); this.Log().Warn(message); var packages = (new DirectoryInfo(updateUrlOrPath)).GetFiles("*.nupkg"); if (packages.Length == 0) { throw new Exception(message); } // NB: Create a new RELEASES file since we've got a directory of packages ReleaseEntry.WriteReleaseFile( packages.Select(x => ReleaseEntry.GenerateFromFile(x.FullName)), fi.FullName); } releaseFile = File.ReadAllText(fi.FullName, Encoding.UTF8); progress(33); } var ret = default(UpdateInfo); var remoteReleases = ReleaseEntry.ParseReleaseFileAndApplyStaging(releaseFile, stagingId); progress(66); if (!remoteReleases.Any()) { throw new Exception("Remote release File is empty or corrupted"); } ret = determineUpdateInfo(localReleases, remoteReleases, ignoreDeltaUpdates); progress(100); return(ret); }