예제 #1
0
        /// <summary>
        /// Commits pre-release to GitHub converting it to Latest Release.
        /// </summary>
        /// <param name="settings">Zombie Settings.</param>
        public async void PushReleaseToGitHub(ZombieSettings settings)
        {
            try
            {
                var client    = new GitHubClient(new ProductHeaderValue("Zombie"));
                var tokenAuth = new Credentials(settings.AccessToken);
                client.Credentials = tokenAuth;

                var segments = GitHubUtils.ParseUrl(settings.Address);
                var unused   = await client.Repository.Release.Edit(segments["owner"], segments["repo"], settings.LatestRelease.Id,
                                                                    new ReleaseUpdate
                {
                    Body            = settings.LatestRelease.Body,
                    Draft           = false,
                    Name            = settings.LatestRelease.Name,
                    Prerelease      = false,
                    TagName         = settings.LatestRelease.TagName,
                    TargetCommitish = "master"
                });

                Messenger.Default.Send(new UpdateStatus {
                    Message = "Zombie changed your Release!"
                });
            }
            catch (Exception e)
            {
                _logger.Fatal(e.Message);
                Messenger.Default.Send(new UpdateStatus {
                    Message = "Failed to push updates to your release!"
                });
            }
        }
예제 #2
0
        /// <summary>
        /// Downloads latest pre-release from GitHub.
        /// </summary>
        /// <param name="settings">Zombie Settings.</param>
        public async void DownloadPreRelease(ZombieSettings settings)
        {
            var segments  = GitHubUtils.ParseUrl(settings.Address);
            var client    = new GitHubClient(new ProductHeaderValue("Zombie"));
            var tokenAuth = new Credentials(settings.AccessToken);

            client.Credentials = tokenAuth;

            Release prerelease = null;

            try
            {
                var releases = await client.Repository.Release.GetAll(segments["owner"], segments["repo"], ApiOptions.None);

                if (releases.Any())
                {
                    prerelease = releases.OrderBy(x => x.PublishedAt).FirstOrDefault(x => x.Prerelease);
                }
                if (prerelease == null)
                {
                    Messenger.Default.Send(new PrereleaseDownloaded
                    {
                        Status   = PrereleaseStatus.Failed,
                        Settings = null
                    });
                    return;
                }
            }
            catch (Exception e)
            {
                _logger.Fatal("Failed to retrieve Pre-Release from GitHub. " + e.Message);
                return;
            }

            settings.LatestRelease = new ReleaseObject(prerelease);

            Messenger.Default.Send(new PrereleaseDownloaded
            {
                Status   = PrereleaseStatus.Found,
                Settings = settings
            });
        }
예제 #3
0
        /// <summary>
        /// Method that retrieves the latest release from GitHub.
        /// </summary>
        /// <param name="settings">Zombie Settings to be used to retrieve latest Release.</param>
        public static async void GetLatestRelease(ZombieSettings settings)
        {
            if (IsProcessRunning("Revit"))
            {
                _logger.Error("Update failed. Revit is running.");

                // (Konrad) Since release was not up to date. Let's show a notification to user that update is in progress.
                PublishGuiUpdate(Program.Settings, Status.Notification, "Update failed. Revit is running.");

                return;
            }

            if (string.IsNullOrWhiteSpace(settings?.AccessToken) || string.IsNullOrWhiteSpace(settings.Address))
            {
                var a = string.IsNullOrWhiteSpace(settings.Address) ? "Not found" : "Exists";
                _logger.Error($"Connection failed! Address: {a}");
                return;
            }

            var segments  = GitHubUtils.ParseUrl(settings.Address);
            var client    = new GitHubClient(new ProductHeaderValue("Zombie"));
            var tokenAuth = new Credentials(settings.AccessToken);

            client.Credentials = tokenAuth;

            Release release;

            try
            {
                release = await client.Repository.Release.GetLatest(segments["owner"], segments["repo"]);

                var currentVersion = RegistryUtils.GetZombieVersion();
                if (!release.Assets.Any() || new Version(release.TagName).CompareTo(new Version(currentVersion)) <= 0)
                {
                    PublishGuiUpdate(Program.Settings, Status.UpToDate, "Your release is up to date! Version: " + currentVersion);
                    return;
                }
            }
            catch (Exception e)
            {
                _logger.Fatal("Failed to retrieve Release from GitHub. " + e.Message);
                return;
            }

            // (Konrad) Since release was not up to date. Let's show a notification to user that update is in progress.
            PublishGuiUpdate(Program.Settings, Status.Notification, "Update in progress. Please do not launch Revit.");

            var dir        = FileUtils.GetZombieDownloadsDirectory();
            var downloaded = 0;

            foreach (var asset in release.Assets)
            {
                var filePath = Path.Combine(dir, asset.Name);
                if (GitHubUtils.DownloadAssets(settings, asset.Url, filePath))
                {
                    downloaded++;
                }
            }

            if (downloaded != release.Assets.Count)
            {
                _logger.Error("Failed to download assets!");

                // (Konrad) Since release was not up to date. Let's show a notification to user that update is in progress.
                PublishGuiUpdate(Program.Settings, Status.Notification, "Update failed. Check your internet connection and try again.");

                return;
            }

            // (Konrad) Let's get updated settings, they might be local, or remote.
            // We need latest settings since there might be changes to the target locations.
            ZombieSettings newSettings;

            if (File.Exists(settings.SettingsLocation))
            {
                if (!SettingsUtils.TryGetStoredSettings(settings.SettingsLocation, out newSettings))
                {
                    _logger.Error("Could not get latest local Zombie Settings!");

                    // (Konrad) Since release was not up to date. Let's show a notification to user that update is in progress.
                    PublishGuiUpdate(Program.Settings, Status.Notification, "Update failed. Zombie Settings not found.");

                    return;
                }
            }
            else
            {
                if (!SettingsUtils.TryGetRemoteSettings(settings.SettingsLocation, out newSettings))
                {
                    _logger.Error("Could not get latest remote Zombie Settings!");

                    // (Konrad) Since release was not up to date. Let's show a notification to user that update is in progress.
                    PublishGuiUpdate(Program.Settings, Status.Notification, "Update failed. Zombie Settings not found.");

                    return;
                }
            }

            // (Konrad) Let's make sure that we own the files that we are trying to override
            var fileStreams = new Dictionary <string, FileStream>();

            foreach (var loc in newSettings.DestinationAssets.OrderByDescending(x => (int)x.LocationType))
            {
                foreach (var asset in loc.Assets)
                {
                    if (asset.IsArchive())
                    {
                        // (Konrad) Use old settings
                        if (LockAllContents(loc.LocationType == LocationType.Trash ? settings : newSettings, asset, loc.DirectoryPath, loc.LocationType, out var zippedStreams))
                        {
                            fileStreams = fileStreams
                                          .Concat(zippedStreams)
                                          .GroupBy(x => x.Key)
                                          .ToDictionary(x => x.Key, x => x.First().Value);
                            continue;
                        }

                        ReleaseStreams(fileStreams);

                        // (Konrad) Since release was not up to date. Let's show a notification to user that update is in progress.
                        PublishGuiUpdate(Program.Settings, Status.Notification, "Update failed. Revit is potentially running preventing an update.");

                        return;
                    }

                    if (loc.LocationType != LocationType.Trash)
                    {
                        // (Konrad) Make sure that destination folder exists.
                        if (!Directory.Exists(loc.DirectoryPath))
                        {
                            FileUtils.CreateDirectory(loc.DirectoryPath);
                        }
                    }

                    var to = Path.Combine(loc.DirectoryPath, asset.Name);
                    if (!File.Exists(to))
                    {
                        continue;
                    }

                    try
                    {
                        var fs = new FileStream(to, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
                        fileStreams.Add(to, fs);
                    }
                    catch (Exception e)
                    {
                        _logger.Fatal(e.Message);
                        ReleaseStreams(fileStreams);

                        // (Konrad) Since release was not up to date. Let's show a notification to user that update is in progress.
                        PublishGuiUpdate(Program.Settings, Status.Notification, "Update failed...due to unknown reasons. Sorry about that.");

                        return;
                    }
                }
            }

            // (Konrad) Move assets to target locations.
            // We sort the locations list so that Trash (3) is first.
            // This should make sure that we delete first, then move.
            // Could be important with Zipped contents and overriding.
            foreach (var loc in newSettings.DestinationAssets.OrderByDescending(x => (int)x.LocationType))
            {
                if (loc.LocationType == LocationType.Trash)
                {
                    // (Konrad) Let's remove these files.
                    foreach (var asset in loc.Assets)
                    {
                        if (asset.IsArchive())
                        {
                            if (DeleteZipContents(asset, loc.DirectoryPath, fileStreams))
                            {
                                continue;
                            }

                            ReleaseStreams(fileStreams);

                            // (Konrad) Since release was not up to date. Let's show a notification to user that update is in progress.
                            PublishGuiUpdate(Program.Settings, Status.Notification, "Update failed. Revit is potentially running preventing an update.");

                            return;
                        }

                        var to = Path.Combine(loc.DirectoryPath, asset.Name);
                        if (fileStreams.ContainsKey(to))
                        {
                            // make sure that file is not locked
                            var stream = fileStreams[to];
                            stream?.Close();
                        }

                        if (FileUtils.DeleteFile(to))
                        {
                            continue;
                        }

                        ReleaseStreams(fileStreams);

                        // (Konrad) Since release was not up to date. Let's show a notification to user that update is in progress.
                        PublishGuiUpdate(Program.Settings, Status.Notification, "Update failed. Revit is potentially running preventing an update.");

                        return;
                    }
                }
                else
                {
                    // (Konrad) Let's copy these files.
                    foreach (var asset in loc.Assets)
                    {
                        if (asset.IsArchive())
                        {
                            if (ExtractToDirectory(asset, loc.DirectoryPath, fileStreams))
                            {
                                continue;
                            }

                            ReleaseStreams(fileStreams);

                            // (Konrad) Since release was not up to date. Let's show a notification to user that update is in progress.
                            PublishGuiUpdate(Program.Settings, Status.Notification, "Update failed. Revit is potentially running preventing an update.");

                            return;
                        }

                        var from = Path.Combine(dir, asset.Name);
                        var to   = Path.Combine(loc.DirectoryPath, asset.Name);
                        if (fileStreams.ContainsKey(to))
                        {
                            // make sure that file is not locked
                            var stream = fileStreams[to];
                            stream?.Close();
                        }

                        // (Konrad) Make sure that directory exists.
                        if (!Directory.Exists(Path.GetDirectoryName(to)))
                        {
                            FileUtils.CreateDirectory(Path.GetDirectoryName(to));
                        }

                        if (FileUtils.Copy(from, to))
                        {
                            continue;
                        }

                        ReleaseStreams(fileStreams);

                        // (Konrad) Since release was not up to date. Let's show a notification to user that update is in progress.
                        PublishGuiUpdate(Program.Settings, Status.Notification, "Update failed. Revit is potentially running preventing an update.");

                        return;
                    }
                }
            }

            // (Konrad) Remove temporary assets
            if (!FileUtils.DeleteDirectory(dir))
            {
                // (Konrad) Cleanup failed but we can continue.
                _logger.Error("Could not remove temporary download assets!");
            }

            // (Konrad) This is important!
            ReleaseStreams(fileStreams);

            // (Konrad) We need to store the current version for comparison on next update
            RegistryUtils.SetZombieVersion(release.TagName);

            // (Konrad) Settings need to be updated with the latest one just downloaded
            newSettings.LatestRelease = new ReleaseObject(release);
            if (!newSettings.StoreSettings)
            {
                newSettings.AccessToken      = Program.Settings.AccessToken;
                newSettings.SettingsLocation = Program.Settings.SettingsLocation;
            }
            Program.Settings = newSettings;

            // (Konrad) Publish to any open GUIs
            PublishGuiUpdate(newSettings, Status.Succeeded, "Successfully updated to Version: " + release.TagName);

            // (Konrad) Since release was not up to date. Let's show a notification to user that update is in progress.
            PublishGuiUpdate(Program.Settings, Status.Notification, "Update succeeded. Go ahead and launch Revit to see what's new.");
        }
예제 #4
0
        /// <summary>
        /// Commits Zombie Settings to GitHub overriding existing file.
        /// </summary>
        /// <param name="settings">Zombie Settings.</param>
        public async void PushSettingsToGitHub(ZombieSettings settings)
        {
            try
            {
                var segments  = GitHubUtils.ParseUrl(settings.SettingsLocation);
                var client    = new GitHubClient(new ProductHeaderValue("Zombie"));
                var tokenAuth = new Credentials(settings.AccessToken);
                client.Credentials = tokenAuth;

                var contents = await client.Repository.Content.GetAllContents(segments["owner"], segments["repo"], segments["file"]);

                if (!contents.Any())
                {
                    Messenger.Default.Send(new UpdateStatus {
                        Message = "Could not get contents of the repo!"
                    });
                    return;
                }

                var sha = string.Empty;
                foreach (var rc in contents)
                {
                    if (rc.Name != segments["file"])
                    {
                        continue;
                    }

                    sha = rc.Sha;
                    break;
                }

                if (string.IsNullOrEmpty(sha))
                {
                    Messenger.Default.Send(new UpdateStatus {
                        Message = "Could not get valid SHA for the ZombieSettings!"
                    });
                    return;
                }

                var jsonSettings = new JsonSerializerSettings
                {
                    NullValueHandling      = NullValueHandling.Ignore,
                    MissingMemberHandling  = MissingMemberHandling.Ignore,
                    CheckAdditionalContent = true,
                    Formatting             = Formatting.Indented
                };
                settings.ShouldSerialize = false;
                var json = JsonConvert.SerializeObject(settings, jsonSettings);

                var unused = await client.Repository.Content.UpdateFile(segments["owner"], segments["repo"], segments["file"],
                                                                        new UpdateFileRequest("Zombie changed you!", json, sha, "master", true));

                Messenger.Default.Send(new UpdateStatus {
                    Message = "Zombie changed your settings!"
                });
            }
            catch (Exception e)
            {
                _logger.Fatal(e.Message);
                Messenger.Default.Send(new UpdateStatus {
                    Message = "Failed to push update to your Zombie Settings!"
                });
            }
        }