/// <summary> /// Runs the Validation of a Modlist /// </summary> /// <returns></returns> protected override async Task <ExitCode> Run() { ModList modlist; try { modlist = AInstaller.LoadFromFile((AbsolutePath)Input); } catch (Exception e) { return(CLIUtils.Exit($"Error while loading the Modlist!\n{e}", ExitCode.Error)); } if (modlist == null) { return(CLIUtils.Exit($"The Modlist could not be loaded!", ExitCode.Error)); } var queue = new WorkQueue(); try { ValidateModlist.RunValidation(modlist).RunSynchronously(); } catch (Exception e) { return(CLIUtils.Exit($"Error during Validation!\n{e}", ExitCode.Error)); } return(CLIUtils.Exit("The Modlist passed the Validation", 0)); }
protected override async Task <ExitCode> Run() { var state = await DownloadDispatcher.Infer(Url); if (state == null) { return(CLIUtils.Exit($"Could not find download source for URL {Url}", ExitCode.Error)); } await DownloadDispatcher.PrepareAll(new [] { state }); using var queue = new WorkQueue(); queue.Status .Where(s => s.ProgressPercent != Percent.Zero) .Debounce(TimeSpan.FromSeconds(1)) .Subscribe(s => Console.WriteLine($"Downloading {s.ProgressPercent}")); new[] { state } .PMap(queue, async s => { await s.Download(new Archive(state: null !) { Name = Path.GetFileName(Output) }, (AbsolutePath)Output); }).Wait();
protected override async Task <ExitCode> Run() { if (ID == -1) { Console.WriteLine("{0,-3} {1,-21} {2,-4}", "ID", "Time", "Values"); foreach (var x in BackupsHandler.Backups) { Console.WriteLine("{0,-3} {1,-21} {2,-4}", $"{x.ID}", $"{x.Time:G}", $"{x.Value.Count(c => c.Equals(';'))}"); } return(ExitCode.Ok); } var backup = BackupsHandler.LoadBackup(ID); if (backup == null) { return(CLIUtils.Exit($"Unable to find Backup with ID {ID}!", ExitCode.Error)); } CLIUtils.Log($"Loaded Backup with ID {backup.ID} from {backup.Time:f}"); try { Environment.SetEnvironmentVariable("Path", backup.Value, EnvironmentVariableTarget.Machine); return(ExitCode.Ok); } catch (Exception e) { CLIUtils.LogException(e, "Unable to set PATH variable!"); return(ExitCode.Error); } }
public int Execute() { if (!CLIUtils.HasValidArguments(this)) { CLIUtils.Exit("The provided arguments are not valid! Check previous messages for more information", ExitCode.BadArguments); } return((int)Run().Result); }
public static void BuildWithArgs() { string buildFilePath = CLIUtils.GetCommandLineArg(BUILD_FILE_RELATIVE_PATH_ARG); if (!string.IsNullOrEmpty(buildFilePath)) { Build(buildFilePath); } else { UnityEngine.Debug.LogError("Cannot find build setup path, make sure to specify using " + BUILD_FILE_RELATIVE_PATH_ARG); } }
protected override async Task <ExitCode> Run() { var downloads = ((AbsolutePath)DownloadsFolder).EnumerateFiles(false) .Where(x => Consts.SupportedArchives.Contains(x.Extension)) .Select(x => (string)x.FileNameWithoutExtension) .ToList(); var similar = downloads .Select(x => { var pair = new KeyValuePair <string, CompareStruct>(x, downloads .Where(y => y != x) .Select(y => { var lcs = new MetricLCS(); var distance = lcs.Distance(x, y); return(new CompareStruct(y, distance)); }) .Aggregate((smallest, next) => smallest.Distance < next.Distance ? smallest : next)); return(pair); }) .DistinctBy(x => x.Key) .DistinctBy(x => x.Value.Distance) .Where(x => x.Value.Distance <= Threshold) .ToList(); CLIUtils.Log($"Found {similar.Count} similar files:"); similar.Do(f => { var(key, value) = f; CLIUtils.Log($"{key} similar to {value.Name} by {Math.Round(value.Distance, 3)}"); }); return(ExitCode.Ok); }
protected override async Task <ExitCode> Run() { var modListPath = (AbsolutePath)Modlist; if (modListPath.Extension != Consts.ModListExtension && modListPath.FileName != (RelativePath)"modlist.txt") { return(CLIUtils.Exit($"The file {Modlist} is not a valid modlist file!", ExitCode.BadArguments)); } if (Copy && Move) { return(CLIUtils.Exit("You can't set both copy and move flags!", ExitCode.BadArguments)); } var isModlist = modListPath.Extension == Consts.ModListExtension; var list = new List <TransferFile>(); if (isModlist) { ModList modlist; try { modlist = AInstaller.LoadFromFile(modListPath); } catch (Exception e) { return(CLIUtils.Exit($"Error while loading the Modlist!\n{e}", ExitCode.Error)); } if (modlist == null) { return(CLIUtils.Exit("The Modlist could not be loaded!", ExitCode.Error)); } CLIUtils.Log($"Modlist contains {modlist.Archives.Count} archives."); modlist.Archives.Do(a => { var inputPath = Path.Combine(Input, a.Name); var outputPath = Path.Combine(Output, a.Name); if (!File.Exists(inputPath)) { CLIUtils.Log($"File {inputPath} does not exist, skipping."); return; } CLIUtils.Log($"Adding {inputPath} to the transfer list."); list.Add(new TransferFile(inputPath, outputPath)); var metaInputPath = Path.Combine(inputPath, ".meta"); var metaOutputPath = Path.Combine(outputPath, ".meta"); if (File.Exists(metaInputPath)) { CLIUtils.Log($"Found meta file {metaInputPath}"); if (IncludeMeta) { CLIUtils.Log($"Adding {metaInputPath} to the transfer list."); list.Add(new TransferFile(metaInputPath, metaOutputPath)); } else { CLIUtils.Log($"Meta file {metaInputPath} will be ignored."); } } else { CLIUtils.Log($"Found no meta file for {inputPath}"); if (IncludeMeta) { if (string.IsNullOrWhiteSpace(a.Meta)) { CLIUtils.Log($"Meta for {a.Name} is empty, this should not be possible but whatever."); return; } CLIUtils.Log("Adding meta from archive info the transfer list"); list.Add(new TransferFile(a.Meta, metaOutputPath, true)); } else { CLIUtils.Log($"Meta will be ignored for {a.Name}"); } } }); } else { if (!Directory.Exists(Mods)) { return(CLIUtils.Exit($"Mods directory {Mods} does not exist!", ExitCode.BadArguments)); } CLIUtils.Log($"Reading modlist.txt from {Modlist}"); string[] modlist = File.ReadAllLines(Modlist); if (modlist == null || modlist.Length == 0) { return(CLIUtils.Exit($"Provided modlist.txt file at {Modlist} is empty or could not be read!", ExitCode.BadArguments)); } var mods = modlist.Where(s => s.StartsWith("+")).Select(s => s.Substring(1)).ToHashSet(); if (mods.Count == 0) { return(CLIUtils.Exit("Counted mods from modlist.txt are 0!", ExitCode.BadArguments)); } CLIUtils.Log($"Found {mods.Count} mods in modlist.txt"); var downloads = new HashSet <string>(); Directory.EnumerateDirectories(Mods, "*", SearchOption.TopDirectoryOnly) .Where(d => mods.Contains(Path.GetRelativePath(Path.GetDirectoryName(d), d))) .Do(d => { var meta = Path.Combine(d, "meta.ini"); if (!File.Exists(meta)) { CLIUtils.Log($"Mod meta file {meta} does not exist, skipping"); return; } string[] ini = File.ReadAllLines(meta); if (ini == null || ini.Length == 0) { CLIUtils.Log($"Mod meta file {meta} could not be read or is empty!"); return; } ini.Where(i => !string.IsNullOrWhiteSpace(i) && i.StartsWith("installationFile=")) .Select(i => i.Replace("installationFile=", "")) .Do(i => { CLIUtils.Log($"Found installationFile {i}"); downloads.Add(i); }); }); CLIUtils.Log($"Found {downloads.Count} installationFiles from mod metas."); Directory.EnumerateFiles(Input, "*", SearchOption.TopDirectoryOnly) .Where(f => downloads.Contains(Path.GetFileNameWithoutExtension(f))) .Do(f => { CLIUtils.Log($"Found archive {f}"); var outputPath = Path.Combine(Output, Path.GetFileName(f)); CLIUtils.Log($"Adding {f} to the transfer list"); list.Add(new TransferFile(f, outputPath)); var metaInputPath = Path.Combine(f, ".meta"); if (File.Exists(metaInputPath)) { CLIUtils.Log($"Found meta file for {f} at {metaInputPath}"); if (IncludeMeta) { var metaOutputPath = Path.Combine(outputPath, ".meta"); CLIUtils.Log($"Adding {metaInputPath} to the transfer list."); list.Add(new TransferFile(metaInputPath, metaOutputPath)); } else { CLIUtils.Log("Meta file will be ignored"); } } else { CLIUtils.Log($"Found no meta file for {f}"); } }); } CLIUtils.Log($"Transfer list contains {list.Count} items"); var success = 0; var failed = 0; var skipped = 0; list.Do(f => { if (File.Exists(f.Output)) { if (Overwrite) { CLIUtils.Log($"Output file {f.Output} already exists, it will be overwritten"); if (f.IsMeta || Move) { CLIUtils.Log($"Deleting file at {f.Output}"); try { File.Delete(f.Output); } catch (Exception e) { CLIUtils.Log($"Could not delete file {f.Output}!\n{e}"); failed++; } } } else { CLIUtils.Log($"Output file {f.Output} already exists, skipping"); skipped++; return; } } if (f.IsMeta) { CLIUtils.Log($"Writing meta data to {f.Output}"); try { File.WriteAllText(f.Output, f.Input, Encoding.UTF8); success++; } catch (Exception e) { CLIUtils.Log($"Error while writing meta data to {f.Output}!\n{e}"); failed++; } } else { if (Copy) { CLIUtils.Log($"Copying file {f.Input} to {f.Output}"); try { File.Copy(f.Input, f.Output, Overwrite ? CopyOptions.None : CopyOptions.FailIfExists, CopyMoveProgressHandler, null); success++; } catch (Exception e) { CLIUtils.Log($"Error while copying file {f.Input} to {f.Output}!\n{e}"); failed++; } } else if (Move) { CLIUtils.Log($"Moving file {f.Input} to {f.Output}"); try { File.Move(f.Input, f.Output, Overwrite ? MoveOptions.ReplaceExisting : MoveOptions.None, CopyMoveProgressHandler, null); success++; } catch (Exception e) { CLIUtils.Log($"Error while moving file {f.Input} to {f.Output}!\n{e}"); failed++; } } } }); CLIUtils.Log($"Skipped transfers: {skipped}"); CLIUtils.Log($"Failed transfers: {failed}"); CLIUtils.Log($"Successful transfers: {success}"); return(0); }
protected override async Task <ExitCode> Run() { CLIUtils.Log($"Job ID: {await AuthorAPI.UpdateServerModLists()}"); return(0); }
public void GetExpandedAndValidatedFilePaths_Returns_Expected_Result(string[] input, bool recursive, string[] expectedOutput) { var output = CLIUtils.GetExpandedAndValidatedFilePaths(_fakeFileSystemService, input, recursive).ToList(); CollectionAssert.AreEquivalent(expectedOutput, output); }
protected override async Task <ExitCode> Run() { var originalPath = (AbsolutePath)Original; var updatePath = (AbsolutePath)Update; if (Original == null) { return(ExitCode.BadArguments); } if (Update == null) { return(ExitCode.BadArguments); } ModList original, update; try { original = AInstaller.LoadFromFile(originalPath); } catch (Exception e) { return(CLIUtils.Exit($"Error while loading the original Modlist from {Original}!\n{e}", ExitCode.Error)); } if (original == null) { return(CLIUtils.Exit($"The Modlist from {Original} could not be loaded!", ExitCode.Error)); } try { update = AInstaller.LoadFromFile(updatePath); } catch (Exception e) { return(CLIUtils.Exit($"Error while loading the updated Modlist from {Update}!\n{e}", ExitCode.Error)); } if (update == null) { return(CLIUtils.Exit($"The Modlist from {Update} could not be loaded!", ExitCode.Error)); } var downloadSizeChanges = original.DownloadSize - update.DownloadSize; var installSizeChanges = original.InstallSize - update.InstallSize; var mdText = $"## {update.Version}\n\n" + $"**Build at:** `{File.GetCreationTime(Update)}`\n\n" + "**Info**:\n\n" + $"- Download Size change: {downloadSizeChanges.ToFileSizeString()} (Total: {update.DownloadSize.ToFileSizeString()})\n" + $"- Install Size change: {installSizeChanges.ToFileSizeString()} (Total: {update.InstallSize.ToFileSizeString()})\n\n"; if (IncludeDownloadChanges) { var updatedArchives = update.Archives .Where(a => original.Archives.All(x => x.Name != a.Name)) .Where(a => { if (!(a.State is NexusDownloader.State nexusState)) { return(false); } return(original.Archives.Any(x => { if (!(x.State is NexusDownloader.State originalState)) { return false; } if (nexusState.Name != originalState.Name) { return false; } if (nexusState.ModID != originalState.ModID) { return false; } return nexusState.FileID > originalState.FileID; })); }).ToList(); var newArchives = update.Archives .Where(a => original.Archives.All(x => x.Name != a.Name)) .Where(a => updatedArchives.All(x => x != a)) .ToList(); var removedArchives = original.Archives .Where(a => update.Archives.All(x => x.Name != a.Name)) .Where(a => updatedArchives.All(x => x != a)) .ToList(); if (newArchives.Any() || removedArchives.Any()) { mdText += "**Download Changes**:\n\n"; } updatedArchives.Do(a => { mdText += $"- Updated [{GetModName(a)}]({a.State.GetManifestURL(a)})\n"; }); removedArchives.Do(a => { mdText += $"- Removed [{GetModName(a)}]({a.State.GetManifestURL(a)})\n"; }); newArchives.Do(a => { mdText += $"- Added [{GetModName(a)}]({a.State.GetManifestURL(a)})\n"; }); mdText += "\n"; } if (IncludeLoadOrderChanges) { var loadorderTxt = (RelativePath)"loadorder.txt"; var originalLoadOrderFile = original.Directives .Where(d => d is InlineFile) .Where(d => d.To.FileName == loadorderTxt) .Cast <InlineFile>() .First(); var updatedLoadOrderFile = update.Directives .Where(d => d is InlineFile) .Where(d => d.To.FileName == loadorderTxt) .Cast <InlineFile>() .First(); var originalLoadOrder = GetTextFileFromModlist(originalPath, original, originalLoadOrderFile.SourceDataID).Result.Split("\n"); var updatedLoadOrder = GetTextFileFromModlist(updatePath, update, updatedLoadOrderFile.SourceDataID).Result.Split("\n"); var addedPlugins = updatedLoadOrder .Where(p => originalLoadOrder.All(x => p != x)) .ToList(); var removedPlugins = originalLoadOrder .Where(p => updatedLoadOrder.All(x => p != x)) .ToList(); if (addedPlugins.Any() || removedPlugins.Any()) { mdText += "**Load Order Changes**:\n\n"; } addedPlugins.Do(p => { mdText += $"- Added {p}\n"; }); removedPlugins.Do(p => { mdText += $"- Removed {p}\n"; }); mdText += "\n"; } if (IncludeModChanges) { var modlistTxt = (RelativePath)"modlist.txt"; var originalModlistFile = original.Directives .Where(d => d is InlineFile) .Where(d => d.To.FileName == modlistTxt) .Cast <InlineFile>() .First(); var updatedModlistFile = update.Directives .Where(d => d is InlineFile) .Where(d => d.To.FileName == modlistTxt) .Cast <InlineFile>() .First(); var originalModlist = GetTextFileFromModlist(originalPath, original, originalModlistFile.SourceDataID).Result.Split("\n"); var updatedModlist = GetTextFileFromModlist(updatePath, update, updatedModlistFile.SourceDataID).Result.Split("\n"); var removedMods = originalModlist .Where(m => m.StartsWith("+")) .Where(m => updatedModlist.All(x => m != x)) .Select(m => m.Substring(1)) .ToList(); var addedMods = updatedModlist .Where(m => m.StartsWith("+")) .Where(m => originalModlist.All(x => m != x)) .Select(m => m.Substring(1)) .ToList(); if (removedMods.Any() || addedMods.Any()) { mdText += "**Mod Changes**:\n\n"; } addedMods.Do(m => { mdText += $"- Added {m}\n"; }); removedMods.Do(m => { mdText += $"- Removed {m}\n"; }); } var output = string.IsNullOrWhiteSpace(Output) ? "changelog.md" : Output; if (File.Exists(output) && output.EndsWith("md")) { CLIUtils.Log($"Output file {output} already exists and is a markdown file. It will be updated with the newest version"); var markdown = File.ReadAllLines(output).ToList(); var lines = mdText.Split("\n"); if (lines.All(l => markdown.Contains(l))) { return(CLIUtils.Exit("The output file is already up-to-date", ExitCode.Ok)); } var doc = Markdown.Parse(File.ReadAllText(output)); var hasToc = false; var tocLine = 0; var headers = doc .Where(b => b is HeadingBlock) .Cast <HeadingBlock>() .ToList(); if (headers.Count < 2) { return(CLIUtils.Exit("The provided output file has less than 2 headers!", ExitCode.Error)); } if (headers[0].Level == 1 && headers[1].Level == 2) { if (headers[1].Line - headers[0].Line > headers.Count - 1) { var listBlocks = doc .Where(b => b.Line > headers[0].Line && b.Line < headers[1].Line) .OfType <ListBlock>() .ToList(); if (listBlocks.Count == 1) { hasToc = true; tocLine = listBlocks[0].Line; CLIUtils.Log($"Toc found at {tocLine}"); } } } var firstHeader = headers .First(h => h.Level >= 2); var line = firstHeader.Line - 1; if (hasToc) { markdown.Insert(tocLine, $"- [{update.Version}](#{ToTocLink(update.Version.ToString())})"); line++; } markdown.InsertRange(line + 1, lines); File.WriteAllLines(output, markdown); CLIUtils.Log($"Wrote {markdown.Count} lines to {output}"); return(ExitCode.Ok); } var text = "# Changelog\n\n" + $"- [{update.Version}](#{ToTocLink(update.Version.ToString())})\n\n" + $"{mdText}"; File.WriteAllText(output, text); CLIUtils.Log($"Wrote changelog to {output}"); return(ExitCode.Ok); }
protected override async Task <ExitCode> Run() { CLIUtils.Log($"Job ID: {await AuthorAPI.UpdateNexusCache()}"); return(0); }
public async Task PerformCopy() { CLIUtils.Log($"Copying {_src} to {_dest}"); await _src.CopyToAsync(_dest); }
public async Task PerformCopy() { CLIUtils.Log($"Writing data to {_src}"); await _dest.WriteAllTextAsync(_src); }
protected override async Task <ExitCode> Run() { string?current; try { current = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine); } catch (Exception e) { CLIUtils.LogException(e, "Unable to read PATH variable!"); return(ExitCode.Error); } if (current == null) { CLIUtils.Log("PATH variable is null!"); return(ExitCode.Error); } CLIUtils.Log("Creating Backup..."); BackupsHandler.SaveBackup(current); CLIUtils.Log("Cleaning variable..."); List <string> values = current.Split(";") .Select(x => { var r = x.Replace("/", "\\"); if (r.EndsWith("\\")) { r = r.Substring(0, r.Length - 1); } return(r); }) .ToList(); if (RemoveDuplicates) { var count = values.Count; values = values.Distinct().ToList(); CLIUtils.Log($"Removed {count-values.Count} duplicates"); } if (RemoveNotExisting) { var removed = values.RemoveAll(x => !Directory.Exists(x)); CLIUtils.Log($"Removed {removed} not existing paths"); } CLIUtils.Log($"Finished cleaning, before: {current.Split(";").Length}, after: {values.Count}"); try { Environment.SetEnvironmentVariable("Path", values.Aggregate((x, y) => $"{x};{y}"), EnvironmentVariableTarget.Machine); return(ExitCode.Ok); } catch (SecurityException securityException) { CLIUtils.LogException(securityException, "Unable to set PATH due to Security Exception, try running the program as Admin"); return(ExitCode.Error); } catch (Exception e) { CLIUtils.LogException(e, "Unable to set PATH variable!"); return(ExitCode.Error); } }