Esempio n. 1
0
        /// <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));
        }
Esempio n. 2
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();
Esempio n. 3
0
        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);
            }
        }
Esempio n. 4
0
        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);
            }
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
0
        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);
        }
Esempio n. 8
0
 protected override async Task <ExitCode> Run()
 {
     CLIUtils.Log($"Job ID: {await AuthorAPI.UpdateServerModLists()}");
     return(0);
 }
Esempio n. 9
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);
    }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
 protected override async Task <ExitCode> Run()
 {
     CLIUtils.Log($"Job ID: {await AuthorAPI.UpdateNexusCache()}");
     return(0);
 }
Esempio n. 12
0
 public async Task PerformCopy()
 {
     CLIUtils.Log($"Copying {_src} to {_dest}");
     await _src.CopyToAsync(_dest);
 }
Esempio n. 13
0
 public async Task PerformCopy()
 {
     CLIUtils.Log($"Writing data to {_src}");
     await _dest.WriteAllTextAsync(_src);
 }
Esempio n. 14
0
        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);
            }
        }