internal static JObject HTTP(JObject orig_metadata, string remote_id, NetFileCache cache, IUser user) { var metadata = orig_metadata; // Check if we should auto-inflate. string kref = (string)metadata[expand_token]; if (kref == (string)orig_metadata[expand_token] || kref == "#/ckan/http") { log.InfoFormat("Inflating from HTTP download... {0}", metadata[expand_token]); metadata["download"] = remote_id; metadata["version"] = "0.0.0"; // add a dummy version that will be replaced by the KSP-AVC parser later metadata.Remove(expand_token); var remote_uri = new Uri(remote_id); var downloaded_file = Net.Download(remote_uri); var module = CkanModule.FromJson(metadata.ToString()); if (metadata[version_token] != null && (metadata[version_token].ToString()).StartsWith("#/ckan/ksp-avc")) { // TODO pass the correct vref here... var versionRemote = FindVersionRemote(metadata, metadata[version_token].ToString()); metadata.Remove(version_token); try { AVC avc = AVC.FromZipFile(module, downloaded_file, versionRemote.id); avc.InflateMetadata(metadata, null, null); metadata["version"] = avc.version.ToString(); module.version = avc.version; } catch (JsonReaderException) { user.RaiseMessage("Bad embedded KSP-AVC file for {0}, halting.", module); return(null); } // If we've done this, we need to re-inflate our mod, too. module = CkanModule.FromJson(metadata.ToString()); } else { throw new Kraken("No $vref specified, $kref HTTP method requires it, bailing out.."); } ModuleInstaller.CachedOrDownload(module.identifier, module.version, module.download, cache); } else { log.WarnFormat("Not inflating metadata for {0}", orig_metadata["identifier"]); } // metadata["download"] = metadata["download"].ToString() + '#' + metadata["version"].ToString(); return(metadata); }
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; }
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); }