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

KSP-CKAN / CKAN / 16536011796

26 Jul 2025 04:19AM UTC coverage: 56.351% (+8.5%) from 47.804%
16536011796

Pull #4408

github

web-flow
Merge b51164c06 into 99ebf468c
Pull Request #4408: Add tests for CmdLine

4558 of 8422 branches covered (54.12%)

Branch coverage included in aggregate %.

148 of 273 new or added lines in 28 files covered. (54.21%)

18 existing lines in 5 files now uncovered.

9719 of 16914 relevant lines covered (57.46%)

1.18 hits per line

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

0.0
/Netkan/Processors/Inflator.cs
1
using System;
2
using System.Collections.Generic;
3
using System.IO;
4
using System.Linq;
5

6
using Autofac;
7
using log4net;
8

9
using CKAN.Configuration;
10
using CKAN.NetKAN.Model;
11
using CKAN.NetKAN.Services;
12
using CKAN.NetKAN.Transformers;
13
using CKAN.NetKAN.Validators;
14
using CKAN.Games;
15
using CKAN.Extensions;
16

17
namespace CKAN.NetKAN.Processors
18
{
19
    public class Inflator
20
    {
21
        public Inflator(string? cacheDir,
×
22
                        bool    overwriteCache,
23
                        string? githubToken,
24
                        string? gitlabToken,
25
                        string? userAgent,
26
                        bool?   prerelease,
27
                        IGame   game)
28
        {
×
29
            log.Debug("Initializing inflator");
×
30
            cache = FindCache(ServiceLocator.Container.Resolve<IConfiguration>(),
×
31
                              cacheDir);
32

33
            IModuleService moduleService = new ModuleService(game);
×
34
            IFileService   fileService   = new FileService(cache);
×
35
            http          = new CachingHttpService(cache, overwriteCache, userAgent);
×
36
            ckanValidator = new CkanValidator(http, moduleService, game, githubToken);
×
37
            transformer   = new NetkanTransformer(http, fileService, moduleService,
×
38
                                                  githubToken, gitlabToken, userAgent, prerelease, game, netkanValidator);
39
        }
×
40

41
        internal IEnumerable<Metadata> Inflate(string           filename,
42
                                               Metadata[]       netkans,
43
                                               TransformOptions opts)
44
        {
×
45
            log.DebugFormat("Inflating {0}", filename);
×
46
            try
47
            {
×
48
                // Tell the downloader that we're starting a new request
49
                http.ClearRequestedURLs();
×
50

51
                if (netkans.Length > 1)
×
52
                {
×
53
                    // Mix properties between sections if they don't start with x_netkan
54
                    var stripped = netkans.Select(nk => nk.Json())
×
55
                                          .Select(StripNetkanMetadataTransformer.Strip)
56
                                          .ToArray();
57
                    netkans = netkans.Select(nk => nk.MergeFrom(stripped))
×
58
                                     .ToArray();
59
                }
×
60

61
                foreach (var netkan in netkans)
×
62
                {
×
63
                    netkanValidator.ValidateNetkan(netkan, filename);
×
64
                }
×
65
                log.Debug("Input successfully passed pre-validation");
×
66

67
                var ckans = netkans.SelectManyTasks(netkan => transformer.Transform(netkan, opts))
×
68
                                   .GroupBy(module => module.Version)
×
69
                                   .Select(grp => Metadata.Merge(grp.ToArray()))
×
70
                                   .SelectMany(merged => specVersionTransformer.Transform(merged, opts))
×
71
                                   .SelectMany(withSpecVersion => sortTransformer.Transform(withSpecVersion, opts))
×
72
                                   .OrderByDescending(m => m.Prerelease)
×
73
                                   .ToList();
74
                log.Debug("Finished transformation");
×
75

76
                // null means "all"
77
                if (opts.Releases is int relsRequested)
×
78
                {
×
79
                    if (ckans.Count(m => !m.Prerelease) > relsRequested)
×
80
                    {
×
81
                        throw new Kraken(string.Format("Generated {0} modules but only {1} requested: {2}",
×
82
                                                       ckans.Count,
83
                                                       relsRequested,
84
                                                       string.Join("; ", ckans.Select(DescribeHosting))));
85
                    }
86
                    ckans = ckans.Take(relsRequested).ToList();
×
87
                }
×
88

89
                foreach (Metadata ckan in ckans)
×
90
                {
×
91
                    ckanValidator.ValidateCkan(ckan, netkans.First());
×
92
                }
×
93
                log.Debug("Output successfully passed post-validation");
×
94
                return ckans;
×
95
            }
96
            catch (Exception)
×
97
            {
×
98
                try
99
                {
×
100
                    // Purge anything we download for a failed indexing attempt from the cache to allow re-downloads
101
                    PurgeDownloads(http, cache);
×
102
                }
×
103
                catch
×
104
                {
×
105
                    // Don't freak out if we can't delete
106
                }
×
107
                throw;
×
108
            }
109
        }
×
110

111
        internal void ValidateCkan(Metadata ckan)
112
        {
×
113
            netkanValidator.Validate(ckan);
×
114
            ckanValidator.Validate(ckan);
×
115
        }
×
116

117
        private static NetFileCache FindCache(IConfiguration cfg, string? cacheDir)
118
        {
×
119
            if (cacheDir != null)
×
120
            {
×
121
                log.InfoFormat("Using user-supplied cache at {0}", cacheDir);
×
122
                return new NetFileCache(cacheDir);
×
123
            }
124

125
            try
126
            {
×
127
                log.InfoFormat("Using main CKAN meta-cache at {0}", cfg.DownloadCacheDir);
×
128
                // Create a new file cache in the same location so NetKAN can download pure URLs not sourced from CkanModules
NEW
129
                return new NetFileCache(cfg.DownloadCacheDir ?? GameInstanceManager.DefaultDownloadCacheDir);
×
130
            }
131
            catch
×
132
            {
×
133
                // Meh, can't find KSP. 'Scool, bro.
134
            }
×
135

136
            var tempdir = Path.GetTempPath();
×
137
            log.InfoFormat("Using tempdir for cache: {0}", tempdir);
×
138

139
            return new NetFileCache(tempdir);
×
140
        }
×
141

142
        private static void PurgeDownloads(IHttpService http, NetFileCache cache)
143
        {
×
144
            log.Debug("Deleting downloads for failed inflation");
×
145
            if (http != null && cache != null)
×
146
            {
×
147
                cache.Remove(http.RequestedURLs);
×
148
            }
×
149
        }
×
150

151
        private string DescribeHosting(Metadata metadata)
152
            => metadata.Prerelease
×
153
                   ? $"{metadata.Version} (pre-release) on {string.Join(", ", metadata.Hosts)}"
154
                   : $"{metadata.Version} on {string.Join(", ", metadata.Hosts)}";
155

156
        private readonly NetFileCache cache;
157
        private readonly IHttpService http;
158

159
        private readonly NetkanTransformer       transformer;
160
        private readonly SpecVersionTransformer  specVersionTransformer = new SpecVersionTransformer();
×
161
        private readonly PropertySortTransformer sortTransformer        = new PropertySortTransformer();
×
162

163
        private readonly NetkanValidator netkanValidator = new NetkanValidator();
×
164
        private readonly CkanValidator   ckanValidator;
165

166
        private static readonly ILog log = LogManager.GetLogger(typeof(Inflator));
×
167
    }
168
}
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