Skip to content

Commit db7c1ba

Browse files
committed
Fix #531
1 parent 21d3784 commit db7c1ba

File tree

7 files changed

+427
-250
lines changed

7 files changed

+427
-250
lines changed

src/IronyModManager.IO/Mods/ModWriter.cs

Lines changed: 61 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-

2-
// ***********************************************************************
1+
// ***********************************************************************
32
// Assembly : IronyModManager.IO
43
// Author : Mario
54
// Created : 03-31-2020
65
//
76
// Last Modified By : Mario
8-
// Last Modified On : 01-23-2024
7+
// Last Modified On : 12-23-2024
98
// ***********************************************************************
109
// <copyright file="ModWriter.cs" company="Mario">
1110
// Mario
@@ -31,7 +30,6 @@
3130

3231
namespace IronyModManager.IO.Mods
3332
{
34-
3533
/// <summary>
3634
/// Class ModWriter.
3735
/// Implements the <see cref="IronyModManager.IO.Common.Mods.IModWriter" />
@@ -113,16 +111,17 @@ public async Task<bool> ApplyModsAsync(ModWriterParameters parameters)
113111
{
114112
throw new ArgumentException("Invalid descriptor type.");
115113
}
114+
116115
Task<bool>[] tasks;
117116

118-
using (var mutex = await writeLock.LockAsync())
117+
using (await writeLock.LockAsync())
119118
{
120-
tasks = new Task<bool>[]
121-
{
122-
Task.Run(async() => await sqliteExporter.ExportAsync(parameters)),
123-
Task.Run(async() => await sqliteExporterBeta.ExportAsync(parameters)),
124-
Task.Run(async() => await jsonExporter.ExportModsAsync(parameters))
125-
};
119+
tasks =
120+
[
121+
Task.Run(async () => await sqliteExporter.ExportAsync(parameters)),
122+
Task.Run(async () => await sqliteExporterBeta.ExportAsync(parameters)),
123+
Task.Run(async () => await jsonExporter.ExportModsAsync(parameters))
124+
];
126125
await Task.WhenAll(tasks);
127126
}
128127

@@ -158,6 +157,7 @@ public Task<bool> CanWriteToModDirectoryAsync(ModWriterParameters parameters)
158157
// Real genious you picked C, D or whatever drive
159158
return Task.FromResult(false);
160159
}
160+
161161
var root = Path.Combine(el[0], el[1]);
162162
if (!Directory.Exists(root) && !IsAdmin())
163163
{
@@ -177,12 +177,15 @@ public Task<bool> CanWriteToModDirectoryAsync(ModWriterParameters parameters)
177177
{
178178
return Task.FromResult(false);
179179
}
180+
180181
return Task.FromResult(true);
181182
}
182183
}
183184
}
185+
184186
return Task.FromResult(true);
185187
}
188+
186189
return Task.FromResult(false);
187190
}
188191

@@ -199,6 +202,7 @@ public Task<bool> CreateModDirectoryAsync(ModWriterParameters parameters)
199202
Directory.CreateDirectory(fullPath);
200203
return Task.FromResult(true);
201204
}
205+
202206
return Task.FromResult(false);
203207
}
204208

@@ -217,8 +221,10 @@ Task<bool> delete()
217221
DiskOperations.DeleteFile(fullPath);
218222
return Task.FromResult(true);
219223
}
224+
220225
return Task.FromResult(false);
221226
}
227+
222228
var retry = new RetryStrategy();
223229
return retry.RetryActionAsync(() => delete());
224230
}
@@ -235,6 +241,7 @@ public Task<bool> DescriptorExistsAsync(ModWriterParameters parameters)
235241
{
236242
return Task.FromResult(true);
237243
}
244+
238245
return Task.FromResult(false);
239246
}
240247

@@ -250,6 +257,7 @@ public string FormatPrefixModName(string prefix, string name)
250257
{
251258
return $"{prefix}{name}";
252259
}
260+
253261
return name;
254262
}
255263

@@ -265,6 +273,7 @@ public virtual bool ModDirectoryExists(ModWriterParameters parameters)
265273
{
266274
return false;
267275
}
276+
268277
return Directory.EnumerateFiles(fullPath, "*", SearchOption.AllDirectories).Any();
269278
}
270279

@@ -303,21 +312,25 @@ Task<bool> purge()
303312
{
304313
DiskOperations.DeleteDirectory(fullPath, true);
305314
}
315+
306316
return Task.FromResult(true);
307317
}
308318
else if (File.Exists(fullPath))
309319
{
310320
DiskOperations.DeleteFile(fullPath);
311321
var directory = Path.GetDirectoryName(fullPath);
312-
var files = Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories);
322+
var files = Directory.EnumerateFiles(directory!, "*", SearchOption.AllDirectories);
313323
if (!files.Any())
314324
{
315325
DiskOperations.DeleteDirectory(directory, true);
316326
}
327+
317328
return Task.FromResult(true);
318329
}
330+
319331
return Task.FromResult(false);
320332
}
333+
321334
var retry = new RetryStrategy();
322335
return retry.RetryActionAsync(() => purge());
323336
}
@@ -333,12 +346,10 @@ public Task<bool> SetDescriptorLockAsync(ModWriterParameters parameters, bool is
333346
var fullPath = Path.Combine(parameters.RootDirectory ?? string.Empty, parameters.Mod.DescriptorFile ?? string.Empty);
334347
if (File.Exists(fullPath))
335348
{
336-
_ = new System.IO.FileInfo(fullPath)
337-
{
338-
IsReadOnly = isLocked
339-
};
349+
_ = new System.IO.FileInfo(fullPath) { IsReadOnly = isLocked };
340350
return Task.FromResult(true);
341351
}
352+
342353
return Task.FromResult(false);
343354
}
344355

@@ -356,6 +367,7 @@ public async Task<bool> WriteDescriptorAsync(ModWriterParameters parameters, boo
356367
{
357368
throw new ArgumentException("Invalid descriptor type.");
358369
}
370+
359371
async Task<bool> writeDescriptors()
360372
{
361373
// If needed I've got a much more complex serializer, it is written for Kerbal Space Program but the structure seems to be the same though this is much more simpler
@@ -367,12 +379,10 @@ async Task<bool> writeDescriptors()
367379
{
368380
if (File.Exists(fullPath))
369381
{
370-
_ = new System.IO.FileInfo(fullPath)
371-
{
372-
IsReadOnly = true
373-
};
382+
_ = new System.IO.FileInfo(fullPath) { IsReadOnly = true };
374383
}
375384
}
385+
376386
if (writeDescriptorInModDirectory)
377387
{
378388
var modPath = Path.Combine(parameters.Mod.FileName ?? string.Empty, parameters.DescriptorType == DescriptorType.DescriptorMod ? Shared.Constants.DescriptorFile : Shared.Constants.DescriptorJsonMetadata);
@@ -381,13 +391,17 @@ async Task<bool> writeDescriptors()
381391
var dir = Path.GetDirectoryName(modPath);
382392
if (!Directory.Exists(dir))
383393
{
384-
Directory.CreateDirectory(dir);
394+
Directory.CreateDirectory(dir!);
385395
}
386396
}
397+
387398
await writeDescriptor(modPath, true);
388399
}
400+
389401
return true;
390402
}
403+
404+
// ReSharper disable once UnusedLocalFunctionReturnValue
391405
async Task<bool> writeDescriptor(string fullPath, bool truncatePath)
392406
{
393407
bool? state = null;
@@ -397,15 +411,14 @@ async Task<bool> writeDescriptor(string fullPath, bool truncatePath)
397411
state = fileInfo.IsReadOnly;
398412
fileInfo.IsReadOnly = false;
399413
}
400-
using var fs = new FileStream(fullPath, FileMode.Create, FileAccess.Write, FileShare.Read);
414+
415+
await using var fs = new FileStream(fullPath!, FileMode.Create, FileAccess.Write, FileShare.Read);
401416
var result = await WriteDescriptorToStreamAsync(parameters, fs, truncatePath);
402417
if (state.HasValue)
403418
{
404-
var fileInfo = new System.IO.FileInfo(fullPath)
405-
{
406-
IsReadOnly = state.GetValueOrDefault()
407-
};
419+
_ = new System.IO.FileInfo(fullPath) { IsReadOnly = state.GetValueOrDefault() };
408420
}
421+
409422
return result;
410423
}
411424

@@ -428,6 +441,7 @@ public Task<bool> WriteDescriptorToStreamAsync(ModWriterParameters parameters, S
428441
{
429442
throw new ArgumentException("Invalid descriptor type.");
430443
}
444+
431445
return WriteDescriptorToStreamInternalAsync(parameters.Mod, stream, parameters.DescriptorType, truncatePath);
432446
}
433447

@@ -452,7 +466,7 @@ static async Task serializeDescriptorMod(IMod content, StreamWriter sw)
452466
{
453467
if (col.Any())
454468
{
455-
if (attr.KeyedArray)
469+
if (attr!.KeyedArray)
456470
{
457471
foreach (var item in col)
458472
{
@@ -466,6 +480,7 @@ static async Task serializeDescriptorMod(IMod content, StreamWriter sw)
466480
{
467481
await sw.WriteLineAsync($"\t\"{item.Replace("\"", "\\\"")}\"");
468482
}
483+
469484
await sw.WriteLineAsync("}");
470485
}
471486
}
@@ -474,36 +489,44 @@ static async Task serializeDescriptorMod(IMod content, StreamWriter sw)
474489
{
475490
if (!string.IsNullOrWhiteSpace(val != null ? val.ToString() : string.Empty))
476491
{
477-
if (attr.AlternateNameEndsWithCondition?.Count() > 0 && attr.AlternateNameEndsWithCondition.Any(p => val.ToString().EndsWith(p, StringComparison.OrdinalIgnoreCase)))
492+
if (attr!.AlternateNameEndsWithCondition?.Count() > 0 && attr.AlternateNameEndsWithCondition.Any(p => val!.ToString()!.EndsWith(p, StringComparison.OrdinalIgnoreCase)))
478493
{
479-
await sw.WriteLineAsync($"{attr.AlternatePropertyName}=\"{val.ToString().Replace("\"", "\\\"")}\"");
494+
await sw.WriteLineAsync($"{attr.AlternatePropertyName}=\"{val?.ToString()?.Replace("\"", "\\\"")}\"");
480495
}
481496
else
482497
{
483-
await sw.WriteLineAsync($"{attr.PropertyName}=\"{val.ToString().Replace("\"", "\\\"")}\"");
498+
await sw.WriteLineAsync($"{attr.PropertyName}=\"{val?.ToString()?.Replace("\"", "\\\"")}\"");
484499
}
485500
}
486501
}
487502
}
488503
}
504+
489505
static async Task serializeJsonDescriptorMod(IMod content, StreamWriter sw)
490506
{
491507
var customData = content.AdditionalData != null ? new Dictionary<string, object>(content.AdditionalData) : new Dictionary<string, object>();
492508
if (content.ReplacePath != null && content.ReplacePath.Any())
493509
{
494510
customData[Shared.Constants.JsonMetadataReplacePaths] = content.ReplacePath;
495511
}
512+
496513
if (content.UserDir != null && content.UserDir.Any())
497514
{
498515
customData[Shared.Constants.DescriptorUserDir] = content.UserDir;
499516
}
500517

501-
var metaData = new JsonMetadata()
518+
var relationshipData = new List<Dictionary<string, object>>();
519+
if (content.RelationshipData != null)
520+
{
521+
relationshipData.AddRange(content.RelationshipData.Select(relData => new Dictionary<string, object>(relData)));
522+
}
523+
524+
var metaData = new JsonMetadata
502525
{
503-
Id = content.RemoteId.HasValue ? content.RemoteId.ToString() : string.Empty,
526+
Id = !string.IsNullOrWhiteSpace(content.JsonId) ? content.JsonId : content.RemoteId.HasValue ? content.RemoteId.ToString() : string.Empty,
504527
Name = content.Name,
505528
Path = content.FileName,
506-
Relationships = content.Dependencies != null ? content.Dependencies.ToList() : new List<string>(),
529+
Relationships = relationshipData,
507530
SupportedGameVersion = content.Version,
508531
Tags = content.Tags != null ? content.Tags.ToList() : new List<string>(),
509532
ShortDescription = string.Empty,
@@ -519,7 +542,8 @@ static async Task serializeJsonDescriptorMod(IMod content, StreamWriter sw)
519542
mod = mapper.Map<IMod>(mod);
520543
mod.FileName = descriptorType == DescriptorType.JsonMetadata ? null : string.Empty;
521544
}
522-
using var sw = new StreamWriter(stream, leaveOpen: true);
545+
546+
await using var sw = new StreamWriter(stream, leaveOpen: true);
523547
if (descriptorType == DescriptorType.DescriptorMod)
524548
{
525549
await serializeDescriptorMod(mod, sw);
@@ -528,6 +552,7 @@ static async Task serializeJsonDescriptorMod(IMod content, StreamWriter sw)
528552
{
529553
await serializeJsonDescriptorMod(mod, sw);
530554
}
555+
531556
await sw.FlushAsync();
532557
return true;
533558
}
@@ -545,6 +570,7 @@ private bool IsAdmin()
545570
using var identity = WindowsIdentity.GetCurrent();
546571
return new WindowsPrincipal(identity).IsInRole(WindowsBuiltInRole.Administrator);
547572
}
573+
548574
return false;
549575
}
550576
catch
@@ -597,7 +623,7 @@ private class JsonMetadata
597623
/// </summary>
598624
/// <value>The relationships.</value>
599625
[JsonProperty("relationships", NullValueHandling = NullValueHandling.Include)]
600-
public List<string> Relationships { get; set; }
626+
public List<Dictionary<string, object>> Relationships { get; set; }
601627

602628
/// <summary>
603629
/// Gets or sets the short description.

0 commit comments

Comments
 (0)