• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

KSP-CKAN / CKAN / 15655379223

14 Jun 2025 07:26PM UTC coverage: 27.151% (-3.2%) from 30.327%
15655379223

push

github

HebaruSan
Merge #4392 Writethrough when saving files, add Netkan tests

3702 of 12085 branches covered (30.63%)

Branch coverage included in aggregate %.

19 of 32 new or added lines in 18 files covered. (59.38%)

6 existing lines in 6 files now uncovered.

8041 of 31165 relevant lines covered (25.8%)

0.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/Netkan/Program.cs
1
using System;
2
using System.Diagnostics;
3
using System.IO;
4
using System.Linq;
5
using System.Net;
6
using System.Text;
7

8
using CommandLine;
9
using log4net;
10
using Newtonsoft.Json;
11
using Newtonsoft.Json.Linq;
12
using YamlDotNet.RepresentationModel;
13

14
using CKAN.Games;
15
using CKAN.Versioning;
16
using CKAN.NetKAN.Model;
17
using CKAN.NetKAN.Processors;
18
using CKAN.NetKAN.Transformers;
19
using CKAN.Extensions;
20

21
namespace CKAN.NetKAN
22
{
23
    public static class Program
24
    {
25
        public static int Main(string[] args)
26
        {
×
27
            var Options = ProcessArgs(args);
×
28
            try
29
            {
×
30
                // Force-allow TLS 1.2 for HTTPS URLs, because GitHub requires it.
31
                // This is on by default in .NET 4.6, but not in 4.5.
32
                ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12
×
33
                                                      | SecurityProtocolType.Tls13;
34

35
                // If we see the --version flag, then display our build info
36
                // and exit.
37
                if (Options.Version)
×
38
                {
×
39
                    Console.WriteLine(Meta.GetVersion(VersionFormat.Full));
×
40
                    return ExitOk;
×
41
                }
42

43
                var game = KnownGames.GameByShortName(Options.Game);
×
44
                if (game == null)
×
45
                {
×
46
                    return ExitBadOpt;
×
47
                }
48

49
                if (!string.IsNullOrEmpty(Options.ValidateCkan))
×
50
                {
×
51
                    var ckan = new Metadata(JObject.Parse(File.ReadAllText(Options.ValidateCkan)));
×
52
                    var inf = new Inflator(Options.CacheDir,
×
53
                                           Options.OverwriteCache,
54
                                           Options.GitHubToken,
55
                                           Options.GitLabToken,
56
                                           Options.NetUserAgent,
57
                                           Options.PreRelease,
58
                                           game);
59
                    inf.ValidateCkan(ckan);
×
60
                    Console.WriteLine(QueueHandler.serializeCkan(
×
61
                        PropertySortTransformer.SortProperties(ckan)));
62
                    return ExitOk;
×
63
                }
64

65
                if (Options.Queues is string { Length: > 0 }
×
66
                    && Options.Queues.Split(new char[] { ',' }, 2)
67
                       //is [var input, var output]
68
                       is string[] array
69
                    && array.Length == 2
70
                    && array[0] is var input
71
                    && array[1] is var output)
72
                {
×
73
                    var qh = new QueueHandler(input,
×
74
                                              output,
75
                                              Options.CacheDir,
76
                                              Options.OutputDir,
77
                                              Options.OverwriteCache,
78
                                              Options.GitHubToken,
79
                                              Options.GitLabToken,
80
                                              Options.NetUserAgent,
81
                                              Options.PreRelease,
82
                                              game);
83
                    qh.Process();
×
84
                    return ExitOk;
×
85
                }
86

87
                if (Options.Files != null)
×
88
                {
×
89
                    var inf = new Inflator(Options.CacheDir,
×
90
                                           Options.OverwriteCache,
91
                                           Options.GitHubToken,
92
                                           Options.GitLabToken,
93
                                           Options.NetUserAgent,
94
                                           Options.PreRelease,
95
                                           game);
96
                    var useragent = Options.NetUserAgent ?? Net.UserAgentString;
×
97
                    foreach (var file in Options.Files)
×
98
                    {
×
99
                        Log.InfoFormat("Transforming {0}", file);
×
100
                        var netkans = ReadNetkans(file, useragent);
×
101
                        var ckans = inf.Inflate(
×
102
                                file,
103
                                netkans,
104
                                new TransformOptions(
105
                                    Options.ParseReleases(),
106
                                    Options.ParseSkipReleases(),
107
                                    Options.ParseHighestVersion(),
108
                                    Options.ParseHighestVersion(),
109
                                    netkans.Any(nk => nk.Staged),
×
110
                                    string.Join(Environment.NewLine,
111
                                                netkans.Select(nk => nk.StagingReason)
×
112
                                                       .OfType<string>())))
113
                            .ToArray();
114
                        foreach (Metadata ckan in ckans)
×
115
                        {
×
116
                            WriteCkan(Options.OutputDir, ckan.AllJson);
×
117
                        }
×
118
                    }
×
119
                }
×
120
                else
121
                {
×
122
                    Log.Fatal(
×
123
                        "Usage: netkan [--verbose|--debug] [--debugger] [--prerelease] [--outputdir=...] <filename|URL>"
124
                    );
125
                    return ExitBadOpt;
×
126
                }
127
            }
×
128
            catch (Exception e)
×
129
            {
×
130
                e = e.GetBaseException();
×
131

132
                Log.Fatal(e.Message);
×
133

134
                if (Options == null || Options.Debug)
×
135
                {
×
136
                    Log.Fatal(e.StackTrace);
×
137
                }
×
138

139
                return ExitError;
×
140
            }
141

142
            return ExitOk;
×
143
        }
×
144

145
        private static CmdLineOptions ProcessArgs(string[] args)
146
        {
×
147
            if (args.Contains("--debugger"))
×
148
            {
×
149
                Debugger.Launch();
×
150
            }
×
151

152
            var Options = new CmdLineOptions();
×
153
            Parser.Default.ParseArgumentsStrict(args, Options);
×
154

155
            Logging.Initialize();
×
156

157
            LogManager.GetRepository().Threshold = Options.GetLogLevel();
×
158

159
            return Options;
×
160
        }
×
161

162
        private static Metadata[] ReadNetkans(string file, string useragent)
163
        {
×
164
            if (!file.EndsWith(".netkan", StringComparison.OrdinalIgnoreCase))
×
165
            {
×
166
                Log.WarnFormat("Input {0} is not a .netkan file", file);
×
167
            }
×
168

169
            return ArgContents(useragent, file)
×
170
                       .Select(ymap => new Metadata(ymap))
×
171
                       .ToArray();
172
        }
×
173

174
        private static YamlMappingNode[] ArgContents(string userAgent, string? arg)
175
            => arg == null
×
176
                ? Array.Empty<YamlMappingNode>()
177
                : Uri.IsWellFormedUriString(arg, UriKind.Absolute)
178
                   && Net.DownloadText(new Uri(arg), userAgent) is string s
179
                    ? YamlExtensions.Parse(s)
180
                    : YamlExtensions.Parse(File.OpenText(arg));
181

182
        internal static string CkanFileName(string? dirPath, JObject json)
183
            => Path.Combine(
×
184
                dirPath ?? ".",
185
                string.Format(
186
                    "{0}-{1}.ckan",
187
                    (string?)json["identifier"] ?? "",
188
                    ((string?)json["version"])?.Replace(':', '-') ?? ""));
189

190
        private static void WriteCkan(string? outputDir, JObject json)
191
        {
×
192
            var finalPath = CkanFileName(outputDir, json);
×
193

194
            using (var swriter = new StringWriter(new StringBuilder()))
×
195
            using (var jwriter = new JsonTextWriter(swriter))
×
196
            {
×
197
                jwriter.Formatting = Formatting.Indented;
×
198
                jwriter.Indentation = 4;
×
199
                jwriter.IndentChar = ' ';
×
200

201
                var serializer = new JsonSerializer();
×
202
                serializer.Serialize(jwriter, json);
×
203

NEW
204
                (swriter + Environment.NewLine).WriteThroughTo(finalPath);
×
205
            }
×
206
            Log.InfoFormat("Transformation written to {0}", finalPath);
×
207
        }
×
208

209
        private const int ExitOk = 0;
210
        private const int ExitBadOpt = 1;
211
        private const int ExitError = 2;
212

213
        private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
×
214
    }
215
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc