Skip to content

Commit fd93287

Browse files
authored
Merge pull request #6 from BurnoutHints/decouple-commands-into-separate-operations
2 parents eab2fe1 + c708b30 commit fd93287

13 files changed

Lines changed: 1048 additions & 931 deletions
Lines changed: 87 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,150 +1,125 @@
1-
using System.Runtime.Serialization;
2-
1+
using Volatility.Operations.Resources;
32
using Volatility.Resources;
43
using Volatility.Utilities;
54

65
using static Volatility.Utilities.EnvironmentUtilities;
76

87
namespace Volatility.CLI.Commands;
98

10-
internal partial class ExportResourceCommand : ICommand
9+
internal class ExportResourceCommand : ICommand
1110
{
12-
public static string CommandToken => "ExportResource";
13-
public static string CommandDescription => "Exports information and relevant data from an imported/created resource into a platform's format.";
14-
public static string CommandParameters => "--recurse --overwrite --type=<resource type OR index> --format=<tub,bpr,x360,ps3> --respath=<data path> --outpath=<file path>";
15-
16-
public string? Format { get; set; }
17-
public string? ResourcePath { get; set; }
18-
public string? OutputPath { get; set; }
19-
public bool Overwrite { get; set; }
20-
public bool Recursive { get; set; }
21-
22-
public async Task Execute()
23-
{
11+
public static string CommandToken => "ExportResource";
12+
public static string CommandDescription => "Exports information and relevant data from an imported/created resource into a platform's format.";
13+
public static string CommandParameters => "--recurse --overwrite --type=<resource type OR index> --format=<tub,bpr,x360,ps3> --respath=<data path> --outpath=<file path>";
14+
15+
public string? Format { get; set; }
16+
public string? ResourcePath { get; set; }
17+
public string? OutputPath { get; set; }
18+
public bool Overwrite { get; set; }
19+
public bool Recursive { get; set; }
20+
21+
public async Task Execute()
22+
{
2423
if (string.IsNullOrEmpty(Format))
2524
{
2625
Console.WriteLine("Error: No resource path specified! (--respath)");
2726
return;
2827
}
2928
if (string.IsNullOrEmpty(ResourcePath))
30-
{
31-
Console.WriteLine("Error: No resource path specified! (--respath)");
32-
return;
33-
}
34-
if (string.IsNullOrEmpty(OutputPath))
35-
{
36-
Console.WriteLine("Error: No output path specified! (--outpath)");
37-
return;
38-
}
29+
{
30+
Console.WriteLine("Error: No resource path specified! (--respath)");
31+
return;
32+
}
33+
if (string.IsNullOrEmpty(OutputPath))
34+
{
35+
Console.WriteLine("Error: No output path specified! (--outpath)");
36+
return;
37+
}
3938

4039
string filePath = $"" +
41-
$"{ Path.Combine
42-
(
43-
GetEnvironmentDirectory(EnvironmentDirectory.Resources),
44-
ResourcePath
45-
)
46-
}";
40+
$"{ Path.Combine
41+
(
42+
GetEnvironmentDirectory(EnvironmentDirectory.Resources),
43+
ResourcePath
44+
)
45+
}";
4746

4847
string[] sourceFiles = ICommand.GetFilePathsInDirectory(filePath, ICommand.TargetFileType.Any, Recursive);
4948

50-
if (sourceFiles.Length == 0)
51-
{
52-
Console.WriteLine($"Error: No valid file(s) found at the specified path ({ResourcePath}). Ensure the path exists and spaces are properly enclosed. (--path)");
53-
return;
54-
}
55-
56-
List<Task> tasks = new List<Task>();
57-
foreach (string sourceFile in sourceFiles)
58-
{
59-
Console.WriteLine(sourceFile);
60-
61-
tasks.Add(Task.Run(async () =>
62-
{
63-
FileAttributes fileAttributes;
64-
try
65-
{
66-
fileAttributes = File.GetAttributes(sourceFile);
67-
}
68-
catch (FileNotFoundException)
69-
{
70-
Console.WriteLine("Error: Invalid file import path specified!");
71-
return;
72-
}
73-
catch (DirectoryNotFoundException)
74-
{
75-
Console.WriteLine("Error: Can not find directory for specified import path!");
76-
return;
77-
}
78-
catch (Exception e)
79-
{
80-
Console.WriteLine($"Error: Caught file exception: {e.Message}");
81-
return;
82-
}
49+
if (sourceFiles.Length == 0)
50+
{
51+
Console.WriteLine($"Error: No valid file(s) found at the specified path ({ResourcePath}). Ensure the path exists and spaces are properly enclosed. (--path)");
52+
return;
53+
}
8354

8455
if (!TypeUtilities.TryParseEnum(Format, out Platform platform))
8556
{
8657
throw new InvalidPlatformException("Error: Invalid file format specified!");
8758
}
8859

89-
if (!TypeUtilities.TryParseEnum(Path.GetExtension(filePath).TrimStart('.'), out ResourceType resourceType))
60+
var loadOperation = new LoadResourceOperation();
61+
var exportOperation = new ExportResourceOperation();
62+
63+
List<Task> tasks = new List<Task>();
64+
foreach (string sourceFile in sourceFiles)
65+
{
66+
Console.WriteLine(sourceFile);
67+
68+
tasks.Add(Task.Run(async () =>
69+
{
70+
try
71+
{
72+
File.GetAttributes(sourceFile);
73+
}
74+
catch (FileNotFoundException)
75+
{
76+
Console.WriteLine("Error: Invalid file import path specified!");
77+
return;
78+
}
79+
catch (DirectoryNotFoundException)
80+
{
81+
Console.WriteLine("Error: Can not find directory for specified import path!");
82+
return;
83+
}
84+
catch (Exception e)
85+
{
86+
Console.WriteLine($"Error: Caught file exception: {e.Message}");
87+
return;
88+
}
89+
90+
if (!TypeUtilities.TryParseEnum(Path.GetExtension(sourceFile).TrimStart('.'), out ResourceType resourceType))
9091
{
9192
Console.WriteLine("Error: Resource type is invalid!");
9293
return;
9394
}
9495

95-
string yaml = File.ReadAllText(sourceFile);
96-
97-
Resource resource = ResourceFactory.CreateResource(resourceType, platform, "");
98-
try
99-
{
100-
resource = (Resource?)ResourceYamlDeserializer.DeserializeResource(resource.GetType(), yaml);
101-
if (resource is not Resource)
102-
{
103-
throw new SerializationException();
104-
}
96+
Resource resource;
97+
try
98+
{
99+
resource = await loadOperation.ExecuteAsync(sourceFile, resourceType, platform);
105100
}
106-
catch (Exception e)
107-
{
101+
catch (Exception e)
102+
{
108103
Console.WriteLine($"ERROR: Unable to deserialize {Path.GetFileName(sourceFile)} as {resourceType}!\nMessage from {e.TargetSite}: {e.Message}.\nStack Trace:\n{e.StackTrace}");
104+
return;
109105
}
110106

111-
Directory.CreateDirectory(Path.GetDirectoryName(OutputPath));
112-
113-
using (FileStream fs = new(OutputPath, FileMode.Create))
114-
{
115-
Endian endian = resource.GetResourceEndian() != Endian.Agnostic
116-
? resource.GetResourceEndian()
117-
: EndianMapping.GetDefaultEndian(platform);
118-
119-
using (EndianAwareBinaryWriter writer = new(fs, endian))
120-
{
121-
// The way this is handled is pending a pipeline rewrite
122-
switch (resource)
123-
{
124-
case TextureBase texture:
125-
texture.PushAll();
126-
goto default;
127-
default:
128-
resource.WriteToStream(writer);
129-
break;
130-
}
131-
}
132-
}
107+
await exportOperation.ExecuteAsync(resource, OutputPath, platform);
133108

134109
Console.WriteLine($"Exported {Path.GetFileName(ResourcePath)} as {Path.GetFullPath(OutputPath)}.");
135-
}));
136-
}
137-
await Task.WhenAll(tasks);
138-
}
110+
}));
111+
}
112+
await Task.WhenAll(tasks);
113+
}
139114

140115
public void SetArgs(Dictionary<string, object> args)
141-
{
142-
Format = (args.TryGetValue("format", out object? format) ? format as string : "")?.ToUpper();
143-
ResourcePath = args.TryGetValue("respath", out object? respath) ? respath as string : "";
144-
OutputPath = args.TryGetValue("outpath", out object? outpath) ? outpath as string : "";
145-
Overwrite = args.TryGetValue("overwrite", out var ow) && (bool)ow;
146-
Recursive = args.TryGetValue("recurse", out var re) && (bool)re;
147-
}
148-
149-
public ExportResourceCommand() { }
150-
}
116+
{
117+
Format = (args.TryGetValue("format", out object? format) ? format as string : "")?.ToUpper();
118+
ResourcePath = args.TryGetValue("respath", out object? respath) ? respath as string : "";
119+
OutputPath = args.TryGetValue("outpath", out object? outpath) ? outpath as string : "";
120+
Overwrite = args.TryGetValue("overwrite", out var ow) && (bool)ow;
121+
Recursive = args.TryGetValue("recurse", out var re) && (bool)re;
122+
}
123+
124+
public ExportResourceCommand() { }
125+
}

0 commit comments

Comments
 (0)