static void Main(string[] args) { IUser user = new ConsoleUser(false); repoPath = args[0]; repoUrlPrefix = args[1]; githubAccessToken = args[2]; Directory.CreateDirectory(Path.Combine(repoPath, "cache")); NetFileCache netFileCache = new NetFileCache(Path.Combine(repoPath, "cache")); CombinedModFileNormalizer modFileNormalizer = new CombinedModFileNormalizer(new IModFileNormalizer[] { new RarToZipNormalizer(), new SevenZipToZipNormalizer(), new ModZipRootNormalizer() }); ModDirectoryManager manualModDirectoryManager = new ModDirectoryManager(repoUrlPrefix, repoPath, "mods", modFileNormalizer, netFileCache); ModDirectoryManager githubModsDirectoryManager = new ModDirectoryManager(repoUrlPrefix, repoPath, "mods-github", modFileNormalizer, netFileCache); CombinedCfanAggregator combinedAggregator = new CombinedCfanAggregator(new ICfanAggregator[] { new LocalRepositoryAggregator(manualModDirectoryManager), new GithubAggregator(githubModsDirectoryManager, new GithubRepositoriesDataProvider(), githubAccessToken), new FactorioComAggregator(), }); var cfanJsons = combinedAggregator.getAllCfanJsons(user).ToList(); cfanJsons.Where(p => !CfanJson.requiresFactorioComAuthorization(p)).ToList().ForEach(p => saveCfanJson(user, p)); cfanJsons.ForEach(p => saveCfanJson(user, p, v2: true)); createFinalRepositoryTarGz(user); createFinalRepositoryTarGz(user, v2: true); user.RaiseMessage("Done."); }
public int RunSubCommand(GameInstanceManager manager, CommonOptions opts, SubCommandOptions options) { var exitCode = Exit.OK; Parser.Default.ParseArgumentsStrict(options.options.ToArray(), new CompatOptions(), (string option, object suboptions) => { // ParseArgumentsStrict calls us unconditionally, even with bad arguments if (!string.IsNullOrEmpty(option) && suboptions != null) { CommonOptions comOpts = (CommonOptions)suboptions; comOpts.Merge(opts); _user = new ConsoleUser(comOpts.Headless); _kspManager = manager ?? new GameInstanceManager(_user); exitCode = comOpts.Handle(_kspManager, _user); if (exitCode != Exit.OK) { return; } switch (option) { case "list": { var ksp = MainClass.GetGameInstance(_kspManager); const string versionHeader = "Version"; const string actualHeader = "Actual"; var output = ksp .GetCompatibleVersions() .Select(i => new { Version = i, Actual = false }) .ToList(); output.Add(new { Version = ksp.Version(), Actual = true }); output = output .OrderByDescending(i => i.Actual) .ThenByDescending(i => i.Version) .ToList(); var versionWidth = Enumerable .Repeat(versionHeader, 1) .Concat(output.Select(i => i.Version.ToString())) .Max(i => i.Length); var actualWidth = Enumerable .Repeat(actualHeader, 1) .Concat(output.Select(i => i.Actual.ToString())) .Max(i => i.Length); const string columnFormat = "{0} {1}"; _user.RaiseMessage(string.Format(columnFormat, versionHeader.PadRight(versionWidth), actualHeader.PadRight(actualWidth) )); _user.RaiseMessage(string.Format(columnFormat, new string('-', versionWidth), new string('-', actualWidth) )); foreach (var line in output) { _user.RaiseMessage(string.Format(columnFormat, line.Version.ToString().PadRight(versionWidth), line.Actual.ToString().PadRight(actualWidth) )); } } break; case "add": { var ksp = MainClass.GetGameInstance(_kspManager); var addOptions = (CompatAddOptions)suboptions; GameVersion GameVersion; if (GameVersion.TryParse(addOptions.Version, out GameVersion)) { var newCompatibleVersion = ksp.GetCompatibleVersions(); newCompatibleVersion.Add(GameVersion); ksp.SetCompatibleVersions(newCompatibleVersion); } else { _user.RaiseError("ERROR: Invalid KSP version."); exitCode = Exit.ERROR; } } break; case "forget": { var ksp = MainClass.GetGameInstance(_kspManager); var addOptions = (CompatForgetOptions)suboptions; GameVersion GameVersion; if (GameVersion.TryParse(addOptions.Version, out GameVersion)) { if (GameVersion != ksp.Version()) { var newCompatibleVersion = ksp.GetCompatibleVersions(); newCompatibleVersion.RemoveAll(i => i == GameVersion); ksp.SetCompatibleVersions(newCompatibleVersion); } else { _user.RaiseError("ERROR: Cannot forget actual KSP version."); exitCode = Exit.ERROR; } } else { _user.RaiseError("ERROR: Invalid KSP version."); exitCode = Exit.ERROR; } } break; default: exitCode = Exit.BADOPT; break; } } }, () => { exitCode = MainClass.AfterHelp(); }); return(exitCode); }
private const string version_token = "$vref"; // It'd be nice if we could have repeated $krefs. public static int Main(string[] args) { BasicConfigurator.Configure(); LogManager.GetRepository().Threshold = Level.Error; var user = new ConsoleUser(); var options = new CmdLineOptions(); Parser.Default.ParseArgumentsStrict(args, options); if (options.Verbose) { LogManager.GetRepository().Threshold = Level.Info; } else if (options.Debug) { LogManager.GetRepository().Threshold = Level.Debug; } if (options.File == null) { log.Fatal("Usage: netkan [--verbose|--debug] [--outputdir=...] <filename>"); return EXIT_BADOPT; } NetFileCache cache = FindCache(options, new KSPManager(user), user); log.InfoFormat("Processing {0}", options.File); JObject json = JsonFromFile(options.File); NetKanRemote remote = FindRemote(json); JObject metadata; switch (remote.source) { case "kerbalstuff": metadata = KerbalStuff(json, remote.id, cache); break; case "github": if (options.GitHubToken != null) { GithubAPI.SetCredentials(options.GitHubToken); } metadata = GitHub(json, remote.id, cache); break; default: log.FatalFormat("Unknown remote source: {0}", remote.source); return EXIT_ERROR; } if (metadata == null) { log.Error("There was an error, aborting"); return EXIT_ERROR; } // Make sure that at the very least this validates against our own // internal model. CkanModule mod = CkanModule.FromJson(metadata.ToString()); // Make sure our identifiers match. if (mod.identifier != (string)json["identifier"]) { log.FatalFormat("Error: Have metadata for {0}, but wanted {1}", mod.identifier, json["identifier"]); return EXIT_ERROR; } // Find our cached file, we'll need it later. string file = cache.GetCachedZip(mod.download); if (file == null) { log.FatalFormat("Error: Unable to find {0} in the cache", mod.identifier); return EXIT_ERROR; } // Make sure this would actually generate an install try { ModuleInstaller.FindInstallableFiles(mod, file, null); } catch (BadMetadataKraken kraken) { log.FatalFormat("Error: Bad metadata for {0}: {1}", kraken.module, kraken.Message); return EXIT_ERROR; } // Now inflate our original metadata from AVC, if we have it. // The reason we inflate our metadata and not the module is that in the module we can't // tell if there's been an override of the version fields or not. // TODO: Remove magic string "#/ckan/ksp-avc" if (metadata[version_token] != null && (string) metadata[version_token] == "#/ckan/ksp-avc") { metadata.Remove(version_token); try { AVC avc = AVC.FromZipFile(mod, file); avc.InflateMetadata(metadata, null, null); } catch (JsonReaderException) { user.RaiseMessage("Bad embedded KSP-AVC file for {0}, halting.", mod); return EXIT_ERROR; } // If we've done this, we need to re-inflate our mod, too. mod = CkanModule.FromJson(metadata.ToString()); } // All done! Write it out! string final_path = Path.Combine(options.OutputDir, String.Format ("{0}-{1}.ckan", mod.identifier, mod.version)); log.InfoFormat("Writing final metadata to {0}", final_path); File.WriteAllText(final_path, metadata.ToString()); return EXIT_OK; }
public static int Main(string[] args) { BasicConfigurator.Configure(); LogManager.GetRepository().Threshold = Level.Error; var user = new ConsoleUser(false); var options = new CmdLineOptions(); Parser.Default.ParseArgumentsStrict(args, options); if (options.Verbose) { LogManager.GetRepository().Threshold = Level.Info; } else if (options.Debug) { LogManager.GetRepository().Threshold = Level.Debug; } if (options.NetUserAgent != null) { Net.UserAgentString = options.NetUserAgent; } if (options.File == null) { log.Fatal("Usage: netkan [--verbose|--debug] [--prerelease] [--outputdir=...] <filename>"); return EXIT_BADOPT; } NetFileCache cache = FindCache(options, new KSPManager(user), user); log.InfoFormat("Processing {0}", options.File); JObject json = JsonFromFile(options.File); NetKanRemote remote = FindRemote(json); JObject metadata; switch (remote.source) { case "kerbalstuff": metadata = KerbalStuff(json, remote.id, cache); break; case "jenkins": metadata = Jenkins(json, remote.id, cache); break; case "github": if (options.GitHubToken != null) { GithubAPI.SetCredentials(options.GitHubToken); } metadata = GitHub(json, remote.id, options.PreRelease, cache); break; case "http": metadata = HTTP(json, remote.id, cache, user); break; default: log.FatalFormat("Unknown remote source: {0}", remote.source); return EXIT_ERROR; } if (metadata == null) { log.Error("There was an error, aborting"); return EXIT_ERROR; } // Make sure that at the very least this validates against our own // internal model. // TODO: Given all the other post-processing we do, we should really // be doing these checks at the end (after overrides, vrefs, etc). CkanModule mod = CkanModule.FromJson(metadata.ToString()); // Make sure our identifiers match. if (mod.identifier != (string)json["identifier"]) { log.FatalFormat("Error: Have metadata for {0}, but wanted {1}", mod.identifier, json["identifier"]); return EXIT_ERROR; } // Find our cached file, we'll need it later. string file = cache.GetCachedZip(mod.download); if (file == null) { log.FatalFormat("Error: Unable to find {0} in the cache", mod.identifier); return EXIT_ERROR; } // Make sure this would actually generate an install. try { ModuleInstaller.FindInstallableFiles(mod, file, null); } catch (BadMetadataKraken kraken) { log.FatalFormat("Error: Bad metadata for {0}: {1}", kraken.module, kraken.Message); return EXIT_ERROR; } // Now inflate our original metadata from AVC, if we have it. // The reason we inflate our metadata and not the module is that in the module we can't // tell if there's been an override of the version fields or not. foreach (string vref in vrefs(metadata)) { log.DebugFormat ("Expanding vref {0}", vref); if (vref.StartsWith ("#/ckan/ksp-avc")) { // HTTP has already included the KSP-AVC data as it needs it earlier in the process if (remote.source != "http") { var versionRemote = FindVersionRemote (metadata, vref); try { AVC avc = AVC.FromZipFile (mod, file, versionRemote.id); // TODO check why the AVC file can be null... if (avc != null) { avc.InflateMetadata (metadata, null, null); } } catch (JsonReaderException) { user.RaiseMessage ("Bad embedded KSP-AVC file for {0}, halting.", mod); return EXIT_ERROR; } } } if (vref.StartsWith ("#/ckan/kerbalstuff")) { log.DebugFormat("Kerbalstuff vref: {0}", vref); Match match = Regex.Match(vref, @"^#/ckan/([^/]+)/(.+)"); if (!match.Success) { // TODO: Have a proper kraken class! user.RaiseMessage ("Cannot find remote and ID in vref: {0}, halting.", vref); return EXIT_ERROR; } string remote_id = match.Groups [2].ToString (); log.DebugFormat("Kerbalstuff id : {0}", remote_id); try { KSMod ks = KSAPI.Mod(Convert.ToInt32(remote_id)); if (ks != null) { KSVersion version = new KSVersion(); version.friendly_version = mod.version; ks.InflateMetadata (metadata, file, version); } } catch (JsonReaderException) { user.RaiseMessage ("Cannot find remote and ID in vref: {0}, halting.", vref); return EXIT_ERROR; } } } // Fix our version string, if required. metadata = FixVersionStrings(metadata); // Apply overrides, if applicable. metadata = new NetkanOverride(metadata).ProcessOverrides(); // Finally, strip all our `x_netkan` flags. metadata = StripNetkanMetadata(metadata); // Re-inflate our mod, in case our vref or FixVersionString routines have // altered it at all. mod = CkanModule.FromJson (metadata.ToString ()); // All done! Write it out! var version_filename = mod.version.ToString().Replace(':','-'); string final_path = Path.Combine(options.OutputDir, string.Format("{0}-{1}.ckan", mod.identifier, version_filename)); log.InfoFormat("Writing final metadata to {0}", final_path); StringBuilder sb = new StringBuilder(); StringWriter sw = new StringWriter(sb); using (JsonTextWriter writer = new JsonTextWriter (sw)) { writer.Formatting = Formatting.Indented; writer.Indentation = 4; writer.IndentChar = ' '; JsonSerializer serializer = new JsonSerializer(); serializer.Serialize(writer, metadata); } File.WriteAllText(final_path, sw + Environment.NewLine); return EXIT_OK; }
private const string version_token = "$vref"; // It'd be nice if we could have repeated $krefs. public static int Main(string[] args) { BasicConfigurator.Configure(); LogManager.GetRepository().Threshold = Level.Error; var user = new ConsoleUser(false); var options = new CmdLineOptions(); Parser.Default.ParseArgumentsStrict(args, options); if (options.Verbose) { LogManager.GetRepository().Threshold = Level.Info; } else if (options.Debug) { LogManager.GetRepository().Threshold = Level.Debug; } if (options.NetUserAgent != null) { Net.UserAgentString = options.NetUserAgent; } if (options.File == null) { log.Fatal("Usage: netkan [--verbose|--debug] [--prerelease] [--outputdir=...] <filename>"); return(EXIT_BADOPT); } NetFileCache cache = FindCache(options, new KSPManager(user), user); log.InfoFormat("Processing {0}", options.File); JObject json = JsonFromFile(options.File); NetKanRemote remote = FindRemote(json); JObject metadata; switch (remote.source) { case "kerbalstuff": metadata = KerbalStuff(json, remote.id, cache); break; case "jenkins": metadata = Jenkins(json, remote.id, cache); break; case "github": if (options.GitHubToken != null) { GithubAPI.SetCredentials(options.GitHubToken); } metadata = GitHub(json, remote.id, options.PreRelease, cache); break; case "http": metadata = HTTP(json, remote.id, cache, user); break; default: log.FatalFormat("Unknown remote source: {0}", remote.source); return(EXIT_ERROR); } if (metadata == null) { log.Error("There was an error, aborting"); return(EXIT_ERROR); } // Make sure that at the very least this validates against our own // internal model. CkanModule mod = CkanModule.FromJson(metadata.ToString()); // Make sure our identifiers match. if (mod.identifier != (string)json["identifier"]) { log.FatalFormat("Error: Have metadata for {0}, but wanted {1}", mod.identifier, json["identifier"]); return(EXIT_ERROR); } // Find our cached file, we'll need it later. string file = cache.GetCachedZip(mod.download); if (file == null) { log.FatalFormat("Error: Unable to find {0} in the cache", mod.identifier); return(EXIT_ERROR); } // Make sure this would actually generate an install try { ModuleInstaller.FindInstallableFiles(mod, file, null); } catch (BadMetadataKraken kraken) { log.FatalFormat("Error: Bad metadata for {0}: {1}", kraken.module, kraken.Message); return(EXIT_ERROR); } // Now inflate our original metadata from AVC, if we have it. // The reason we inflate our metadata and not the module is that in the module we can't // tell if there's been an override of the version fields or not. foreach (string vref in vrefs(metadata)) { log.DebugFormat("Expanding vref {0}", vref); if (vref.StartsWith("#/ckan/ksp-avc")) { // HTTP has already included the KSP-AVC data as it needs it earlier in the process if (remote.source != "http") { var versionRemote = FindVersionRemote(metadata, vref); try { AVC avc = AVC.FromZipFile(mod, file, versionRemote.id); // TODO check why the AVC file can be null... if (avc != null) { avc.InflateMetadata(metadata, null, null); } } catch (JsonReaderException) { user.RaiseMessage("Bad embedded KSP-AVC file for {0}, halting.", mod); return(EXIT_ERROR); } } } if (vref.StartsWith("#/ckan/kerbalstuff")) { log.DebugFormat("Kerbalstuff vref: {0}", vref); Match match = Regex.Match(vref, @"^#/ckan/([^/]+)/(.+)"); if (!match.Success) { // TODO: Have a proper kraken class! user.RaiseMessage("Cannot find remote and ID in vref: {0}, halting.", vref); return(EXIT_ERROR); } string remote_id = match.Groups [2].ToString(); log.DebugFormat("Kerbalstuff id : {0}", remote_id); try { KSMod ks = KSAPI.Mod(Convert.ToInt32(remote_id)); if (ks != null) { KSVersion version = new KSVersion(); version.friendly_version = mod.version; ks.InflateMetadata(metadata, file, version); } } catch (JsonReaderException) { user.RaiseMessage("Cannot find remote and ID in vref: {0}, halting.", vref); return(EXIT_ERROR); } } } // Fix our version string, if required. metadata = FixVersionStrings(metadata); // Re-inflate our mod, in case our vref or FixVersionString routines have // altered it at all. mod = CkanModule.FromJson(metadata.ToString()); // All done! Write it out! var version_filename = mod.version.ToString().Replace(':', '-'); string final_path = Path.Combine(options.OutputDir, string.Format("{0}-{1}.ckan", mod.identifier, version_filename)); log.InfoFormat("Writing final metadata to {0}", final_path); StringBuilder sb = new StringBuilder(); StringWriter sw = new StringWriter(sb); using (JsonTextWriter writer = new JsonTextWriter(sw)) { writer.Formatting = Formatting.Indented; writer.Indentation = 4; writer.IndentChar = ' '; JsonSerializer serializer = new JsonSerializer(); serializer.Serialize(writer, metadata); } File.WriteAllText(final_path, sw + Environment.NewLine); return(EXIT_OK); }