Beispiel #1
0
        private static IUpdateSource[] GetUpdateSources(string[] sourceArgs)
        {
            if (sourceArgs.Length == 0)
            {
                var updateSources = UpdateSourceManager.GetUpdateSources(_exeDirectory);
                if (updateSources == null || updateSources.Length == 0)
                {
                    MessageBox.Show("No links to update sources have been provided in arguments and the UpdateSources file is missing or has no valid sources.\n\nAdd one or more links to update sources as arguments or edit the UpdateSources file.", "Invalid arguments", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                return(updateSources);
            }

            var results = new List <IUpdateSource>();

            foreach (var source in sourceArgs)
            {
                try
                {
                    var link = new Uri(source);
                    results.Add(UpdateSourceManager.GetUpdater(link));
                }
                catch (Exception e)
                {
                    MessageBox.Show($"Error opening update source link: {source}\n\n{e}", "Invalid arguments", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Console.WriteLine(e);
                    return(null);
                }
            }
            return(results.ToArray());
        }
Beispiel #2
0
        public MainWindow()
        {
            Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);

            Program.MainSynchronizationContext = SynchronizationContext.Current;

            Instance = this;

            InitializeComponent();

            InstallDirectoryHelper.KoikatuDirectory = GetKoikatuDirectory();

            SetupTabs();

            Task.Run((Action)PopulateStartMenu);

            _updateSources = UpdateSourceManager.GetUpdateSources(Program.ProgramLocation);
            if (_updateSources.Length == 0)
            {
                updateSideloaderModpackToolStripMenuItem.Enabled = false;
            }

#if DEBUG
            var version = Assembly.GetExecutingAssembly().GetName().Version;
#else
            var version = Assembly.GetExecutingAssembly().GetName().Version.ToString(3);
#endif
            Text = $"KK Manager {version} (Fancy updates edition) - {InstallDirectoryHelper.KoikatuDirectory.FullName}";
        }
Beispiel #3
0
        private async void MainWindow_Shown(object sender, EventArgs e)
        {
            if (!Settings.Default.AutoUpdateSearch)
            {
                return;
            }
            // Check For Updates
            // todo make more efficient?
            try
            {
                var updateSources = GetUpdateSources();
                if (!updateSources.Any())
                {
                    return;
                }
                var results = await UpdateSourceManager.GetUpdates(_checkForUpdatesCancel.Token, updateSources);

                var updates = results.Count(item => !item.UpToDate);

                _checkForUpdatesCancel.Token.ThrowIfCancellationRequested();

                if (updates > 0)
                {
                    SetStatusText($"Found {updates} mod updates!");
                    updateSideloaderModpackToolStripMenuItem.BackColor = Color.Lime;
                }
                else
                {
                    SetStatusText("No mod updates were found");
                    updateSideloaderModpackToolStripMenuItem.ForeColor = Color.Gray;
                }
            }
            catch (OperationCanceledException) { }
            catch (Exception ex) { Console.WriteLine($"Crash during update check: {ex.Message}\nat {ex.Demystify().TargetSite}"); }
        }
Beispiel #4
0
        private static UpdateSourceBase[] GetUpdateSources(string[] sourceArgs)
        {
            if (sourceArgs.Length > 0)
            {
                return(UpdateSourceManager.GetUpdateSources(sourceArgs));
            }

            var updateSources = UpdateSourceManager.FindUpdateSources(_exeDirectory);

            if (updateSources == null || updateSources.Length == 0)
            {
                MessageBox.Show("No links to update sources have been provided in arguments and the UpdateSources file is missing or has no valid sources.\n\nAdd one or more links to update sources as arguments or edit the UpdateSources file.", "Invalid arguments", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            return(updateSources);
        }
Beispiel #5
0
        private static UpdateSourceBase[] GetUpdateSources(string[] sourceArgs)
        {
            if (sourceArgs.Length > 0)
            {
                return(UpdateSourceManager.GetUpdateSources(sourceArgs));
            }

            var updateSources = UpdateSourceManager.FindUpdateSources(_exeDirectory);

            if (updateSources == null || updateSources.Length == 0)
            {
                ShowArgError("No links to update sources have been provided in arguments and the UpdateSources file is missing or has no valid sources.\n\n" +
                             "Add one or more links to update sources as arguments or edit the UpdateSources file.");
            }
            return(updateSources);
        }
Beispiel #6
0
        private async void CheckForUpdates()
        {
            try
            {
                var results = await UpdateSourceManager.GetUpdates(_checkForUpdatesCancel.Token, _updateSources);

                var updates = results.Count(item => !item.UpToDate);

                _checkForUpdatesCancel.Token.ThrowIfCancellationRequested();

                if (updates > 0)
                {
                    SetStatusText($"Found {updates} mod updates!");
                    updateSideloaderModpackToolStripMenuItem.BackColor = Color.Lime;
                }
            }
            catch (OperationCanceledException) { }
            catch (Exception ex) { Console.WriteLine(ex); }
        }
Beispiel #7
0
        private async Task CheckForUpdates()
        {
            try
            {
                var _ = SelfUpdater.CheckForUpdatesAndShowDialog();

                var updateSources = GetUpdateSources();
                if (updateSources.Any())
                {
                    var results = await UpdateSourceManager.GetUpdates(_checkForUpdatesCancel.Token, updateSources);

                    var updates = results.Count(item => !item.UpToDate);

                    _checkForUpdatesCancel.Token.ThrowIfCancellationRequested();

                    if (updates > 0)
                    {
                        SetStatusText($"Found {updates} mod updates!");
                        updateSideloaderModpackToolStripMenuItem.BackColor = Color.Lime;
                    }
                    else
                    {
                        SetStatusText("No mod updates were found");
                        updateSideloaderModpackToolStripMenuItem.ForeColor = Color.Gray;
                    }
                }
            }
            catch (OperationCanceledException)
            {
            }
            catch (OutdatedVersionException ex)
            {
                ex.ShowKkmanOutdatedMessage();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Crash during update check: {ex.Message}\nat {ex.Demystify().TargetSite}");
            }
        }
Beispiel #8
0
        private async void MainWindow_Shown(object sender, EventArgs e)
        {
            if (!Settings.Default.AutoUpdateSearch)
            {
                return;
            }
            // Check For Updates
            // todo make more efficient?
            try
            {
                var updateSources = GetUpdateSources();
                if (!updateSources.Any())
                {
                    return;
                }
                var results = await UpdateSourceManager.GetUpdates(_checkForUpdatesCancel.Token, updateSources);

                var updates = results.Count(item => !item.UpToDate);

                _checkForUpdatesCancel.Token.ThrowIfCancellationRequested();

                if (updates > 0)
                {
                    SetStatusText($"Found {updates} mod updates!");
                    updateSideloaderModpackToolStripMenuItem.BackColor = Color.Lime;
                }
                else
                {
                    SetStatusText("No mod updates were found");
                    updateSideloaderModpackToolStripMenuItem.ForeColor = Color.Gray;
                }
            }
            catch (OperationCanceledException) { }
            catch (OutdatedVersionException) { MessageBox.Show("There's a newer version of KK Manager available. Visit github.com/IllusionMods/KKManager to get the latest update. Mod updates might not work until you update.", "KK Manager is outdated", MessageBoxButtons.OK, MessageBoxIcon.Information); }
            catch (Exception ex) { Console.WriteLine($"Crash during update check: {ex.Message}\nat {ex.Demystify().TargetSite}"); }
        }
        private async void ModUpdateProgress_Shown(object sender, EventArgs e)
        {
            var averageDownloadSpeed = new MovingAverage(20);
            var downloadStartTime    = DateTime.MinValue;

            try
            {
                #region Initialize UI

                progressBar1.Style   = ProgressBarStyle.Marquee;
                progressBar1.Value   = 0;
                progressBar1.Maximum = 1;

                labelPercent.Text = "";

                checkBoxSleep.Enabled = false;

                var random = new Random();
                if (random.Next(0, 10) >= 8)
                {
                    var offset    = random.Next(20, 80);
                    var offsetStr = new string(Enumerable.Repeat(' ', offset).ToArray());
                    labelPercent.Text  = offsetStr + " ( )  ( )\n";
                    labelPercent.Text += offsetStr + "( o . o)";
                }

                olvColumnProgress.Renderer     = new BarRenderer(0, 100);
                olvColumnProgress.AspectGetter = rowObject => (int)Math.Round(((UpdateDownloadItem)rowObject).FinishPercent);
                olvColumnSize.AspectGetter     = rowObject => ((UpdateDownloadItem)rowObject).TotalSize;
                //olvColumnDownloaded.AspectGetter = rowObject => ((UpdateDownloadItem)rowObject).GetDownloadedSize();
                olvColumnStatus.AspectGetter = rowObject =>
                {
                    var item = (UpdateDownloadItem)rowObject;
                    return(item.Exceptions.Count == 0
                        ? item.Status.ToString()
                        : item.Status + " - " + string.Join("; ", item.Exceptions.Select(x => x.Message)));
                };
                olvColumnName.AspectGetter = rowObject => ((UpdateDownloadItem)rowObject).DownloadPath.Name;
                olvColumnNo.AspectGetter   = rowObject => ((UpdateDownloadItem)rowObject).Order;

                fastObjectListView1.PrimarySortColumn   = olvColumnStatus;
                fastObjectListView1.SecondarySortColumn = olvColumnNo;
                fastObjectListView1.Sorting             = SortOrder.Ascending;
                fastObjectListView1.PrimarySortOrder    = SortOrder.Ascending;
                fastObjectListView1.SecondarySortOrder  = SortOrder.Ascending;
                fastObjectListView1.ShowSortIndicators  = true;
                fastObjectListView1.Sort();
                fastObjectListView1.ShowSortIndicator();

                _overallSize = _completedSize = FileSize.Empty;

                #endregion

                SetStatus("Preparing...");
                if (await ProcessWaiter.CheckForProcessesBlockingKoiDir() == false)
                {
                    throw new OperationCanceledException();
                }

                #region Find and select updates

                SetStatus("Searching for mod updates...");
                labelPercent.Text = "Please wait, this might take a couple of minutes.";
                var updateTasks = await UpdateSourceManager.GetUpdates(_cancelToken.Token, _updaters, _autoInstallGuids);

                _cancelToken.Token.ThrowIfCancellationRequested();

                progressBar1.Style = ProgressBarStyle.Blocks;

                if (updateTasks.All(x => x.UpToDate))
                {
                    SetStatus("Everything is up to date!");
                    progressBar1.Value = progressBar1.Maximum;
                    _cancelToken.Cancel();
                    return;
                }

                var isAutoInstall = _autoInstallGuids != null && _autoInstallGuids.Length > 0;
                if (!isAutoInstall)
                {
                    SetStatus($"Found {updateTasks.Count} updates, waiting for user confirmation.");
                    updateTasks = ModUpdateSelectDialog.ShowWindow(this, updateTasks);
                }
                else
                {
                    var skipped = updateTasks.RemoveAll(x => x.UpToDate);
                    SetStatus($"Found {updateTasks.Count} update tasks in silent mode, {skipped} are already up-to-date.", true, true);
                }

                if (updateTasks == null)
                {
                    throw new OperationCanceledException();
                }

                #endregion

                SleepControls.PreventSleepOrShutdown(Handle, "Update is in progress");

                #region Set up update downloader and start downloading

                downloadStartTime = DateTime.Now;

                var downloader    = UpdateDownloadCoordinator.Create(updateTasks);
                var downloadItems = downloader.UpdateItems;

                SetStatus($"{downloadItems.Count(items => items.DownloadSources.Count > 1)} out of {downloadItems.Count} items have more than 1 source", false, true);

                fastObjectListView1.Objects = downloadItems;

                progressBar1.Maximum  = 1000;
                progressBar1.Value    = 0;
                checkBoxSleep.Enabled = true;

                _overallSize = FileSize.SumFileSizes(downloadItems.Select(x => x.TotalSize));

                var lastCompletedSize = FileSize.Empty;
                updateTimer.Tick += (o, args) =>
                {
                    var itemCount = fastObjectListView1.GetItemCount();
                    if (itemCount > 0)
                    {
                        fastObjectListView1.BeginUpdate();
                        fastObjectListView1.RedrawItems(0, itemCount - 1, true);
                        // Needed if user changes sorting column
                        //fastObjectListView1.SecondarySortColumn = olvColumnNo;
                        fastObjectListView1.Sort();
                        fastObjectListView1.EndUpdate();
                    }

                    _completedSize = FileSize.SumFileSizes(downloadItems.Select(x => x.GetDownloadedSize()));

                    var totalPercent = (double)_completedSize.GetKbSize() / (double)_overallSize.GetKbSize() * 100d;
                    if (double.IsNaN(totalPercent))
                    {
                        totalPercent = 0;
                    }

                    // Download speed calc
                    var secondsPassed       = updateTimer.Interval / 1000d;
                    var downloadedSinceLast = FileSize.FromKilobytes((long)((_completedSize - lastCompletedSize).GetKbSize() / secondsPassed));
                    lastCompletedSize = _completedSize;
                    averageDownloadSpeed.Sample(downloadedSinceLast.GetKbSize());
                    var etaSeconds = (_overallSize - _completedSize).GetKbSize() / (double)averageDownloadSpeed.GetAverage();
                    var eta = double.IsNaN(etaSeconds) || etaSeconds <0 || etaSeconds> TimeSpan.MaxValue.TotalSeconds
                        ? "Unknown"
                        : TimeSpan.FromSeconds(etaSeconds).GetReadableTimespan();

                    labelPercent.Text =
                        $"Overall: {totalPercent:F1}% done  ({_completedSize} out of {_overallSize})\r\n" +
                        $"Speed: {downloadedSinceLast}/s  (ETA: {eta})";
                    //$"Speed: {downloadedSinceLast:F1}KB/s";

                    progressBar1.Value = Math.Min((int)Math.Round(totalPercent * 10), progressBar1.Maximum);
                };
                updateTimer.Start();

                SetStatus("Downloading updates...", true, true);

                await downloader.RunUpdate(_cancelToken.Token);

                _cancelToken.Token.ThrowIfCancellationRequested();

                #endregion

                #region Show finish messages

                var failedItems     = downloadItems.Where(x => x.Status == UpdateDownloadStatus.Failed).ToList();
                var unfinishedCount = downloadItems.Count(x => x.Status != UpdateDownloadStatus.Finished);

                var s = $"Successfully updated/removed {downloadItems.Count - unfinishedCount} files from {updateTasks.Count} tasks.";
                if (failedItems.Any())
                {
                    s += $"\nFailed to update {failedItems.Count} files because some sources crashed. Check log for details.";
                }

                SetStatus(s, true, true);

                updateTimer.Stop();
                progressBar1.Value = progressBar1.Maximum;
                labelPercent.Text  = "";

                if (failedItems.Any(x => x.Exceptions.Count > 0))
                {
                    var exceptionMessages = failedItems
                                            .SelectMany(x => x.Exceptions)
                                            .Where(y => !(y is DownloadSourceCrashedException))
                                            // Deal with wrapped exceptions
                                            .Select(y => y.Message.Contains("InnerException") && y.InnerException != null ? y.InnerException.Message : y.Message)
                                            .Distinct();

                    var failDetails = "Reason(s) for failing:\n" + string.Join("\n", exceptionMessages);
                    Console.WriteLine(failDetails);
                    s += " " + failDetails;
                }

                // Sleep before showing a messagebox since the box will block until user clicks ok
                SleepIfNecessary();

                MessageBox.Show(s, "Finished updating", MessageBoxButtons.OK, MessageBoxIcon.Information);

                #endregion
            }
            catch (OutdatedVersionException ex)
            {
                SetStatus("KK Manager needs to be updated to get updates.", true, true);
                ex.ShowKkmanOutdatedMessage();
            }
            catch (OperationCanceledException)
            {
                SetStatus("Update was cancelled by the user.", true, true);
            }
            catch (Exception ex)
            {
                var exceptions = ex is AggregateException aex?aex.Flatten().InnerExceptions : (ICollection <Exception>) new[] { ex };

                if (!exceptions.Any(x => x is OperationCanceledException))
                {
                    SleepIfNecessary();
                }

                SetStatus("Unexpected crash while updating mods, aborting.", true, true);
                SetStatus(string.Join("\n---\n", exceptions), false, true);
                MessageBox.Show("Something unexpected happened and the update could not be completed. Make sure that your internet connection is stable, " +
                                "and that you did not hit your download limits, then try again.\n\nError message (check log for more):\n" + string.Join("\n", exceptions.Select(x => x.Message)),
                                "Update failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                updateTimer.Stop();
                checkBoxSleep.Enabled = false;

                fastObjectListView1.EmptyListMsg = "Nothing was downloaded";

                _cancelToken.Cancel();

                labelPercent.Text = "";
                if (_completedSize != FileSize.Empty)
                {
                    labelPercent.Text += $"Downloaded {_completedSize} out of {_overallSize}";
                    if (downloadStartTime != DateTime.MinValue)
                    {
                        var timeSpent = DateTime.Now - downloadStartTime;
                        labelPercent.Text += $" in {timeSpent.GetReadableTimespan()}";
                    }
                    labelPercent.Text += "\n";
                }
                var averageDlSpeed = averageDownloadSpeed.GetAverage();
                if (averageDlSpeed > 0)
                {
                    labelPercent.Text += $"Average download speed: {new FileSize(averageDlSpeed)}/s";
                }

                progressBar1.Style = ProgressBarStyle.Blocks;
                button1.Enabled    = true;
                button1.Text       = "OK";

                if (_autoInstallGuids != null && _autoInstallGuids.Length > 0)
                {
                    Close();
                }

                SleepControls.AllowSleepOrShutdown(Handle);
            }
        }
Beispiel #10
0
        private List <IUpdateItem> ProcessDirectory(INode remoteDir, DirectoryInfo localDir,
                                                    bool recursive, bool removeExtraClientFiles, Func <INode, FileInfo, bool> versionEqualsComparer,
                                                    CancellationToken cancellationToken)
        {
            var results = new List <IUpdateItem>();

            var localContents = new List <FileSystemInfo>();

            if (localDir.Exists)
            {
                localContents.AddRange(localDir.GetFileSystemInfos("*", SearchOption.TopDirectoryOnly));
            }

            foreach (var remoteItem in GetSubNodes(remoteDir))
            {
                cancellationToken.ThrowIfCancellationRequested();

                switch (remoteItem.Type)
                {
                case NodeType.File:
                {
                    var localFile = localContents.OfType <FileInfo>().FirstOrDefault(x => string.Equals(x.Name, remoteItem.Name, StringComparison.OrdinalIgnoreCase));
                    if (localFile == null)
                    {
                        localFile = new FileInfo(Path.Combine(localDir.FullName, remoteItem.Name));
                    }
                    else
                    {
                        localContents.Remove(localFile);
                    }

                    var localIsUpToDate = localFile.Exists && versionEqualsComparer(remoteItem, localFile);

                    if (!localIsUpToDate)
                    {
                        results.Add(new MegaUpdateItem(remoteItem, this, localFile));
                    }

                    if (_latestModifiedDate < (remoteItem.ModificationDate ?? remoteItem.CreationDate))
                    {
                        _latestModifiedDate = remoteItem.ModificationDate ?? remoteItem.CreationDate;
                    }
                }
                break;

                case NodeType.Directory:
                    if (recursive)
                    {
                        var localItem = localContents.OfType <DirectoryInfo>().FirstOrDefault(x => string.Equals(x.Name, remoteItem.Name, StringComparison.OrdinalIgnoreCase));
                        if (localItem == null)
                        {
                            localItem = new DirectoryInfo(Path.Combine(localDir.FullName, remoteItem.Name));
                        }
                        else
                        {
                            localContents.Remove(localItem);
                        }

                        results.AddRange(ProcessDirectory(remoteItem, localItem, recursive, removeExtraClientFiles, versionEqualsComparer, cancellationToken));
                    }
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            // Remove all files that were not on the remote
            if (removeExtraClientFiles)
            {
                results.AddRange(UpdateSourceManager.FileInfosToDeleteItems(localContents));
            }

            return(results);
        }
Beispiel #11
0
 public UpdateSourceBase[] GetUpdateSources() => _updateSources ?? (_updateSources = UpdateSourceManager.FindUpdateSources(Program.ProgramLocation));
Beispiel #12
0
        private async void ModUpdateProgress_Shown(object sender, EventArgs e)
        {
            try
            {
                progressBar1.Style   = ProgressBarStyle.Marquee;
                progressBar1.Value   = 0;
                progressBar1.Maximum = 1;

                labelProgress.Text = "N/A";
                labelPercent.Text  = "";

                SetStatus("Searching for mod updates...");
                var updateTasks = await UpdateSourceManager.GetUpdates(_cancelToken.Token, _updaters, _autoInstallGuids);

                _cancelToken.Token.ThrowIfCancellationRequested();

                progressBar1.Style = ProgressBarStyle.Blocks;

                if (updateTasks.All(x => x.UpToDate))
                {
                    SetStatus("Everything is up to date!");
                    progressBar1.Value = progressBar1.Maximum;
                    _cancelToken.Cancel();
                    return;
                }

                if (_autoInstallGuids == null || _autoInstallGuids.Length == 0)
                {
                    SetStatus($"Found {updateTasks.Count} updates, waiting for user confirmation.");
                    updateTasks = ModUpdateSelectDialog.ShowWindow(this, updateTasks);
                }
                else
                {
                    var skipped = updateTasks.RemoveAll(x => x.UpToDate);
                    SetStatus($"Found {updateTasks.Count} update tasks in silent mode, {skipped} are already up-to-date.", true, true);
                }

                if (updateTasks == null)
                {
                    throw new OperationCanceledException();
                }

                _overallSize   = FileSize.SumFileSizes(updateTasks.Select(x => x.TotalUpdateSize));
                _completedSize = FileSize.Empty;

                var allItems = updateTasks.SelectMany(x => x.GetUpdateItems())
                               // Try items with a single source first since they are the most risky
                               .OrderBy(sources => sources.Count())
                               .ToList();

                SetStatus($"{allItems.Count(items => items.Count() > 1)} out of {allItems.Count} items have more than 1 source", false, true);

                progressBar1.Maximum = allItems.Count;

                for (var index = 0; index < allItems.Count; index++)
                {
                    _cancelToken.Token.ThrowIfCancellationRequested();

                    var task = allItems[index];

                    labelProgress.Text = (index + 1) + " / " + allItems.Count;
                    SetStatus("Downloading " + task.First().Item2.TargetPath.Name);

                    if (await UpdateSingleItem(task))
                    {
                        _completedSize += task.First().Item2.ItemSize;
                    }

                    progressBar1.Value = index + 1;
                }

                var s = $"Successfully updated/removed {allItems.Count} files from {updateTasks.Count} tasks.";
                if (_failedItems.Any())
                {
                    s += $"\n\nFailed to update {_failedItems.Count} files because some of the sources raised errors.";
                    if (_failedExceptions.Any())
                    {
                        s += " Reason(s) for failing:\n" + string.Join("\n", _failedExceptions.Select(x => x.Message).Distinct());
                    }
                }
                SetStatus(s, true, true);
                MessageBox.Show(s, "Finished updating", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (OperationCanceledException)
            {
                SetStatus("Operation was cancelled by the user.", true, true);
            }
            catch (Exception ex)
            {
                var exceptions = ex is AggregateException aex?aex.Flatten().InnerExceptions : (ICollection <Exception>) new[] { ex };

                SetStatus("Crash while updating mods, aborting.", true, true);
                SetStatus(string.Join("\n---\n", exceptions), false, true);
                MessageBox.Show("Something unexpected happened and the update could not be completed. Make sure that your internet connection is stable, " +
                                "and that you did not hit your download limit on Mega, then try again.\n\nError message (check log for more):\n" + string.Join("\n", exceptions.Select(x => x.Message)),
                                "Update failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                _cancelToken.Cancel();

                labelPercent.Text = _completedSize == FileSize.Empty ? "" : $"Downloaded {_completedSize} out of {_overallSize}.";

                progressBar1.Style = ProgressBarStyle.Blocks;
                button1.Enabled    = true;
                button1.Text       = "OK";

                if (_autoInstallGuids == null || _autoInstallGuids.Length == 0)
                {
                    Close();
                }
            }
        }
Beispiel #13
0
        private async Task <List <IUpdateItem> > ProcessDirectory(FtpListItem remoteDir, DirectoryInfo localDir,
                                                                  bool recursive, bool removeNotExisting, Func <FtpListItem, FileInfo, bool> versionEqualsComparer,
                                                                  CancellationToken cancellationToken)
        {
            if (remoteDir.Type != FtpFileSystemObjectType.Directory)
            {
                throw new DirectoryNotFoundException();
            }

            var results = new List <IUpdateItem>();

            var localContents = new List <FileSystemInfo>();

            if (localDir.Exists)
            {
                localContents.AddRange(localDir.GetFileSystemInfos("*", SearchOption.TopDirectoryOnly));
            }

            foreach (var remoteItem in GetSubNodes(remoteDir))
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (remoteItem.Type == FtpFileSystemObjectType.Directory)
                {
                    if (recursive)
                    {
                        var localItem = localContents.OfType <DirectoryInfo>().FirstOrDefault(x => string.Equals(x.Name, remoteItem.Name, StringComparison.OrdinalIgnoreCase));
                        if (localItem == null)
                        {
                            localItem = new DirectoryInfo(Path.Combine(localDir.FullName, remoteItem.Name));
                        }
                        else
                        {
                            localContents.Remove(localItem);
                        }

                        results.AddRange(await ProcessDirectory(remoteItem, localItem, recursive, removeNotExisting, versionEqualsComparer, cancellationToken));
                    }
                }
                else if (remoteItem.Type == FtpFileSystemObjectType.File)
                {
                    var itemDate = GetDate(remoteItem);
                    if (itemDate > _latestModifiedDate)
                    {
                        _latestModifiedDate = itemDate;
                    }

                    var localFile = localContents.OfType <FileInfo>().FirstOrDefault(x => string.Equals(x.Name, remoteItem.Name, StringComparison.OrdinalIgnoreCase));
                    if (localFile == null)
                    {
                        localFile = new FileInfo(Path.Combine(localDir.FullName, remoteItem.Name));
                    }
                    else
                    {
                        localContents.Remove(localFile);
                    }

                    var localIsUpToDate = localFile.Exists && versionEqualsComparer(remoteItem, localFile);
                    results.Add(new FtpUpdateItem(remoteItem, this, localFile, localIsUpToDate));
                }
            }

            cancellationToken.ThrowIfCancellationRequested();

            // Remove all files that were not on the remote
            if (removeNotExisting)
            {
                results.AddRange(UpdateSourceManager.FileInfosToDeleteItems(localContents));
            }

            return(results);
        }
        private async void ModUpdateProgress_Shown(object sender, EventArgs e)
        {
            try
            {
                progressBar1.Style   = ProgressBarStyle.Marquee;
                progressBar1.Value   = 0;
                progressBar1.Maximum = 1;

                labelPercent.Text = "";

                var random = new Random();
                if (random.Next(0, 10) >= 9)
                {
                    var offset    = random.Next(0, 136);
                    var offsetStr = new string(Enumerable.Repeat(' ', offset).ToArray());
                    labelPercent.Text  = offsetStr + " ( )  ( )\n";
                    labelPercent.Text += offsetStr + "( o . o)";
                }

                SetStatus("Preparing...");
                if (await ProcessWaiter.CheckForProcessesBlockingKoiDir() == false)
                {
                    throw new OperationCanceledException();
                }

                SetStatus("Searching for mod updates...");
                var updateTasks = await UpdateSourceManager.GetUpdates(_cancelToken.Token, _updaters, _autoInstallGuids);

                _cancelToken.Token.ThrowIfCancellationRequested();

                progressBar1.Style = ProgressBarStyle.Blocks;

                if (updateTasks.All(x => x.UpToDate))
                {
                    SetStatus("Everything is up to date!");
                    progressBar1.Value = progressBar1.Maximum;
                    _cancelToken.Cancel();
                    return;
                }

                if (_autoInstallGuids == null || _autoInstallGuids.Length == 0)
                {
                    SetStatus($"Found {updateTasks.Count} updates, waiting for user confirmation.");
                    updateTasks = ModUpdateSelectDialog.ShowWindow(this, updateTasks);
                }
                else
                {
                    var skipped = updateTasks.RemoveAll(x => x.UpToDate);
                    SetStatus($"Found {updateTasks.Count} update tasks in silent mode, {skipped} are already up-to-date.", true, true);
                }

                if (updateTasks == null)
                {
                    throw new OperationCanceledException();
                }

                _overallSize   = FileSize.SumFileSizes(updateTasks.Select(x => x.TotalUpdateSize));
                _completedSize = FileSize.Empty;

                var allItems = updateTasks.SelectMany(x => x.GetUpdateItems())
                               // Remove unnecessary to avoid potential conflicts if the update is aborted midway and a newer version is added
                               .OrderByDescending(sources => sources.Any(x => x.Item2 is DeleteFileUpdateItem))
                               // Try items with a single source first since they are the most risky
                               .ThenBy(sources => sources.Count())
                               .ThenBy(sources => sources.FirstOrDefault()?.Item2.TargetPath.FullName)
                               .ToList();

                SetStatus($"{allItems.Count(items => items.Count() > 1)} out of {allItems.Count} items have more than 1 source", false, true);

                progressBar1.Maximum = 1000;

                for (var index = 0; index < allItems.Count; index++)
                {
                    _cancelToken.Token.ThrowIfCancellationRequested();

                    var task = allItems[index];

                    SetStatus("Downloading " + task.First().Item2.TargetPath.Name);

                    await UpdateSingleItem(task);
                }

                var s = $"Successfully updated/removed {allItems.Count - _failedItems.Count} files from {updateTasks.Count} tasks.";
                if (_failedItems.Any())
                {
                    s += $"\nFailed to update {_failedItems.Count} files because some sources crashed. Check log for details.";
                }
                SetStatus(s, true, true);
                if (_failedExceptions.Any())
                {
                    var failDetails = "Reason(s) for failing:\n" + string.Join("\n", _failedExceptions.Select(x => x.Message).Distinct());
                    Console.WriteLine(failDetails);
                    s += " " + failDetails;
                }
                MessageBox.Show(s, "Finished updating", MessageBoxButtons.OK, MessageBoxIcon.Information);
                PerformAutoScale();
            }
            catch (OutdatedVersionException ex)
            {
                SetStatus("KK Manager needs to be updated to get updates.", true, true);
                ex.ShowKkmanOutdatedMessage();
            }
            catch (OperationCanceledException)
            {
                SetStatus("Operation was cancelled by the user.", true, true);
            }
            catch (Exception ex)
            {
                var exceptions = ex is AggregateException aex?aex.Flatten().InnerExceptions : (ICollection <Exception>) new[] { ex };

                SetStatus("Crash while updating mods, aborting.", true, true);
                SetStatus(string.Join("\n---\n", exceptions), false, true);
                MessageBox.Show("Something unexpected happened and the update could not be completed. Make sure that your internet connection is stable, " +
                                "and that you did not hit your download limits, then try again.\n\nError message (check log for more):\n" + string.Join("\n", exceptions.Select(x => x.Message)),
                                "Update failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                var wasCancelled = _cancelToken.IsCancellationRequested;
                _cancelToken.Cancel();

                labelPercent.Text = wasCancelled ? "Update was cancelled" : "Update finished";

                if (_completedSize != FileSize.Empty)
                {
                    labelPercent.Text += $"\nSuccessfully downloaded {_completedSize} out of {_overallSize}.";
                }

                progressBar1.Style = ProgressBarStyle.Blocks;
                button1.Enabled    = true;
                button1.Text       = "OK";

                if (_autoInstallGuids != null && _autoInstallGuids.Length > 0)
                {
                    Close();
                }
            }
        }
Beispiel #15
0
        private async Task <List <IUpdateItem> > ProcessDirectory(ZipEntry remoteDir, DirectoryInfo localDir,
                                                                  bool recursive, bool removeNotExisting, Func <ZipEntry, FileInfo, bool> versionEqualsComparer,
                                                                  CancellationToken cancellationToken)
        {
            if (!remoteDir.IsDirectory)
            {
                throw new DirectoryNotFoundException();
            }

            var results = new List <IUpdateItem>();

            var localContents = new List <FileSystemInfo>();

            if (localDir.Exists)
            {
                localContents.AddRange(localDir.GetFileSystemInfos("*", SearchOption.TopDirectoryOnly));
            }

            foreach (var remoteItem in GetChildren(remoteDir))
            {
                cancellationToken.ThrowIfCancellationRequested();

                var remoteFilename = Path.GetFileName(remoteItem.FileName.TrimEnd('\\', '/'));

                if (remoteItem.IsDirectory)
                {
                    if (recursive)
                    {
                        var localItem = localContents.OfType <DirectoryInfo>().FirstOrDefault(x => string.Equals(x.Name, remoteFilename, StringComparison.OrdinalIgnoreCase));
                        if (localItem == null)
                        {
                            localItem = new DirectoryInfo(Path.Combine(localDir.FullName, remoteFilename));
                        }
                        else
                        {
                            localContents.Remove(localItem);
                        }

                        results.AddRange(await ProcessDirectory(remoteItem, localItem, recursive, removeNotExisting, versionEqualsComparer, cancellationToken));
                    }
                }
                else
                {
                    var localFile = localContents.OfType <FileInfo>().FirstOrDefault(x => string.Equals(x.Name, remoteFilename, StringComparison.OrdinalIgnoreCase));
                    if (localFile == null)
                    {
                        localFile = new FileInfo(Path.Combine(localDir.FullName, remoteFilename));
                    }
                    else
                    {
                        localContents.Remove(localFile);
                    }

                    var localIsUpToDate = localFile.Exists && versionEqualsComparer(remoteItem, localFile);
                    if (!localIsUpToDate)
                    {
                        results.Add(new ZipUpdateItem(remoteItem, localFile, this));
                    }

                    if (_latestModifiedDate < remoteItem.LastModified)
                    {
                        _latestModifiedDate = remoteItem.LastModified;
                    }
                }
            }

            cancellationToken.ThrowIfCancellationRequested();

            // Remove all files that were not on the remote
            if (removeNotExisting)
            {
                results.AddRange(UpdateSourceManager.FileInfosToDeleteItems(localContents));
            }

            return(results);
        }
        private List <UpdateItem> ProcessDirectory(IRemoteItem remoteDir, DirectoryInfo localDir,
                                                   bool recursive, bool removeNotExisting, Func <IRemoteItem, FileInfo, bool> versionEqualsComparer,
                                                   CancellationToken cancellationToken)
        {
            if (!remoteDir.IsDirectory)
            {
                throw new DirectoryNotFoundException();
            }

            var results = new List <UpdateItem>();

            var localContents = new List <FileSystemInfo>();

            if (localDir.Exists)
            {
                localContents.AddRange(localDir.GetFileSystemInfos("*", SearchOption.TopDirectoryOnly));
            }

            var enabledName = localContents.OfType <FileInfo>().ToDictionary(x => x, GetEnabledName);

            foreach (var remoteItem in remoteDir.GetDirectoryContents(cancellationToken))
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (remoteItem.IsDirectory)
                {
                    if (recursive)
                    {
                        var localItem = localContents.OfType <DirectoryInfo>().FirstOrDefault(x => string.Equals(x.Name, remoteItem.Name, StringComparison.OrdinalIgnoreCase));
                        if (localItem == null)
                        {
                            localItem = new DirectoryInfo(Path.Combine(localDir.FullName, remoteItem.Name));
                        }
                        else
                        {
                            localContents.Remove(localItem);
                        }

                        results.AddRange(ProcessDirectory(remoteItem, localItem, recursive, removeNotExisting, versionEqualsComparer, cancellationToken));
                    }
                }
                else if (remoteItem.IsFile)
                {
                    var itemDate = remoteItem.ModifiedTime;
                    if (itemDate > _latestModifiedDate)
                    {
                        _latestModifiedDate = itemDate;
                    }

                    var localFile = localContents.OfType <FileInfo>().FirstOrDefault(x => string.Equals(enabledName[x], remoteItem.Name, StringComparison.OrdinalIgnoreCase));
                    if (localFile == null)
                    {
                        localFile = new FileInfo(Path.Combine(localDir.FullName, remoteItem.Name));
                    }
                    else
                    {
                        localContents.Remove(localFile);
                    }

                    var localIsUpToDate = localFile.Exists && versionEqualsComparer(remoteItem, localFile);
                    results.Add(new UpdateItem(localFile, remoteItem, localIsUpToDate));
                }
            }

            cancellationToken.ThrowIfCancellationRequested();

            // Remove all files that were not on the remote
            if (removeNotExisting)
            {
                results.AddRange(UpdateSourceManager.FileInfosToDeleteItems(localContents));
            }

            return(results);
        }