public static async Task<Tuple<DynatreeItem, Exception>> ReadRepo(string url) { try { string json = await _client.DownloadStringTaskAsync(new Uri(url)); DynatreeItem fileTree = DynatreeItem.JsonToDynatree(json); return Tuple.Create<DynatreeItem, Exception>(fileTree, null); } catch (Exception ex) { return Tuple.Create<DynatreeItem, Exception>(null, ex); } }
private async Task <bool> WalkFolder(Repo repo, DynatreeItem folder, string path = "/") { string repoFolder = repo.Folder + "/" + repo.FolderName; if (!Directory.Exists(repoFolder)) { Directory.CreateDirectory(repoFolder); } foreach (DynatreeItem item in folder.children) { if (_cancel) { return(false); } while (_activeThreads >= 5) { await Task.Delay(50); } if (item.isFolder) { string folderPath = path + "/" + item.title; if (!Directory.Exists(repoFolder + "/" + folderPath)) { Directory.CreateDirectory(repoFolder + "/" + folderPath); } if (!await WalkFolder(repo, item, folderPath)) { return(false); } } else { string remotePath = path + "/" + item.title; string filePath = repoFolder + "/" + remotePath; _allFiles.Add(filePath); float totalValue = (((float)_filesHandled / (float)_totalFiles) * 100); if (totalValue <= progressTotal.MaximumValue) { progressTotal.Value = (int)totalValue; } string fileTitle = item.title; if (fileTitle.Length > 18) { fileTitle = fileTitle.Substring(0, 18) + "..."; } labCurrentFile.Text = "Current File: " + fileTitle; if (File.Exists(filePath)) { string checkSum = await Files.CheckSum(filePath); if (checkSum == item.hash) { labProcessed.Text = $"Processed: {_filesHandled}/{_totalFiles} (Active: {_activeThreads})"; _filesHandled++; continue; } } _updated++; int lastPercent = 0; //if (_progresses.ContainsKey(filePath)) //continue; Thread t = new Thread(async() => { _activeThreads++; bool result = await Ftp.RequestFile(repo, remotePath, filePath, item.fileSize, (long progress) => { int percCompleted = (int)progress; if (_cancel) { Ftp.Cancel = true; } if (percCompleted <= lastPercent) { return; } lastPercent = percCompleted; _activeDownloads[filePath] = percCompleted; Invoke((MethodInvoker) delegate { labProcessed.Text = $"Processed: {_filesHandled}/{_totalFiles} (Active: {_activeDownloads.Count})"; string tip = ""; foreach (KeyValuePair <string, double> kv in _activeDownloads.ToList()) { tip += Path.GetFileName(kv.Key) + ": " + kv.Value + "%\n"; } toolTip.SetToolTip(labProcessed, tip); }); return; }); if (!result) { _cancel = true; } _filesHandled++; _activeThreads--; _activeDownloads.Remove(filePath); }); t.Start(); // avoid too many threads starting? slow start? await Task.Delay(5); } } return(true); }
private async void btnUpdate_Click(object sender, EventArgs e) { if (_selected == null) { return; } Process[] p1 = Process.GetProcessesByName("arma3_x64"); Process[] p2 = Process.GetProcessesByName("arma3"); if (p1.Length > 0 || p2.Length > 0) { DialogResult dialogRes = MessageBox.Show("Arma 3 is running, this may cause errors. Do you want to continue?", "Arma 3 is running", MessageBoxButtons.YesNo, MessageBoxIcon.Information); if (dialogRes == DialogResult.No) { return; } } ButtonsEnable(false); Tuple <Repo, Exception> res = await Web.ReadUrlAsync(_selected.Url); Repo repo = res.Item1; if (repo == null) { MessageBox.Show("Error updating repository: " + res.Item2.Message, "An error occured :(", MessageBoxButtons.OK, MessageBoxIcon.Error); ButtonsEnable(true); return; } if (repo != _selected) { repo.LastCheck = Misc.UnixTime; repo.LastUpdate = _selected.LastUpdate; repo = Files.Update(_selected, repo); int index = _repos.IndexOf(_selected); _repos[index] = repo; Files.UpdateRepos(_repos); UpdateRepos(); } // start file downloads and stuff Tuple <DynatreeItem, Exception> filesResponse = await Web.ReadRepo(repo.RemoteFolder); DynatreeItem files = filesResponse.Item1; if (files == null) { MessageBox.Show("Error downloading repository info: " + filesResponse.Item2.Message, "An error occured :(", MessageBoxButtons.OK, MessageBoxIcon.Error); ButtonsEnable(true); return; } _filesHandled = 0; _totalFiles = files.totalFiles; progressTotal.Visible = true; labCurrentFile.Visible = true; labProcessed.Visible = true; bool success = await WalkFolder(repo, files); // make sure all the paths are rooted for (int i = 0; i < _allFiles.Count; i++) { _allFiles[i] = Path.GetFullPath(_allFiles[i]); } // delete unwanted files string[] currentFiles = Directory.GetFiles(repo.Folder + "/" + repo.FolderName, "*", SearchOption.AllDirectories); foreach (string s in currentFiles) { string full = Path.GetFullPath(s); if (!_allFiles.Contains(full)) { File.Delete(full); } } // wait for all downloads to finish while (_activeThreads > 0) { await Task.Delay(50); } // clean up a bit (remove active text) if (success) { labProcessed.Text = $"Processed: {_filesHandled}/{_totalFiles}"; } if (_updated > 0 && success) { int index = _repos.IndexOf(_selected); repo.LastUpdate = Misc.UnixTime; _repos[index] = repo; Files.UpdateRepos(_repos); UpdateRepos(); MessageBox.Show($"Updating files finished.\nTotal files checked: {_totalFiles}, files updated: {_updated}", "Update Finished", MessageBoxButtons.OK, MessageBoxIcon.Information); _updated = 0; } else if (!success) { MessageBox.Show($"Failed to update repository", "Update Failed", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { MessageBox.Show("No new updates found.", "Update Finished", MessageBoxButtons.OK, MessageBoxIcon.Information); } ButtonsEnable(true); }