Skip to content

Commit be632b4

Browse files
committed
Merge branch 'main' of github.com:Unity-Technologies/UnityDataTools
2 parents d1e5570 + 23b8b8d commit be632b4

File tree

3 files changed

+73
-51
lines changed

3 files changed

+73
-51
lines changed

UnityDataTool.Tests/UnityDataToolTests.cs

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.IO;
44
using System.Linq;
55
using System.Text.RegularExpressions;
6+
using System.Threading.Tasks;
67
using NUnit.Framework;
78
using UnityDataTools.TestCommon;
89
using UnityDataTools.FileSystem;
@@ -18,7 +19,7 @@ public class UnityDataToolTests : AssetBundleTestFixture
1819
public UnityDataToolTests(Context context) : base(context)
1920
{
2021
}
21-
22+
2223
protected override void OnLoadExpectedData(Context context)
2324
{
2425
// Uncomment to regenerate expected data.
@@ -36,25 +37,40 @@ public void OneTimeSetup()
3637
[TearDown]
3738
public void Teardown()
3839
{
39-
foreach (var file in new DirectoryInfo(m_TestOutputFolder).EnumerateFiles())
40-
{
41-
file.Delete();
42-
}
40+
var testDir = new DirectoryInfo(m_TestOutputFolder);
41+
testDir.EnumerateFiles()
42+
.ToList().ForEach(f => f.Delete());
43+
testDir.EnumerateDirectories()
44+
.ToList().ForEach(d => d.Delete(true));
4345
}
44-
46+
4547
[Test]
46-
public void ArchiveExtract_FilesExtractedSuccessfully()
48+
public async Task InvalidFile(
49+
[Values(
50+
new string[] {"archive", "extract"},
51+
new string[] {"archive", "list"},
52+
new string[] {"dump"}
53+
)] string[] args)
54+
{
55+
var path = Path.Combine(Context.TestDataFolder, "invalidfile");
56+
var command = args.Append(path);
57+
Assert.AreNotEqual(0, await Program.Main(command.ToArray()));
58+
}
59+
60+
[Test]
61+
public async Task ArchiveExtract_FilesExtractedSuccessfully(
62+
[Values("", "-o archive", "--output-path archive")] string options)
4763
{
4864
var path = Path.Combine(Context.UnityDataFolder, "assetbundle");
4965

50-
Assert.AreEqual(0, Program.Main(new string[] { "archive", "extract", path }));
51-
Assert.IsTrue(File.Exists(Path.Combine(m_TestOutputFolder, "CAB-5d40f7cad7c871cf2ad2af19ac542994")));
52-
Assert.IsTrue(File.Exists(Path.Combine(m_TestOutputFolder, "CAB-5d40f7cad7c871cf2ad2af19ac542994.resS")));
53-
Assert.IsTrue(File.Exists(Path.Combine(m_TestOutputFolder, "CAB-5d40f7cad7c871cf2ad2af19ac542994.resource")));
66+
Assert.AreEqual(0, await Program.Main(new string[] { "archive", "extract", path }.Concat(options.Split(" ", StringSplitOptions.RemoveEmptyEntries)).ToArray()));
67+
Assert.IsTrue(File.Exists(Path.Combine(m_TestOutputFolder, "archive", "CAB-5d40f7cad7c871cf2ad2af19ac542994")));
68+
Assert.IsTrue(File.Exists(Path.Combine(m_TestOutputFolder, "archive", "CAB-5d40f7cad7c871cf2ad2af19ac542994.resS")));
69+
Assert.IsTrue(File.Exists(Path.Combine(m_TestOutputFolder, "archive", "CAB-5d40f7cad7c871cf2ad2af19ac542994.resource")));
5470
}
5571

5672
[Test]
57-
public void ArchiveList_ListFilesCorrectly()
73+
public async Task ArchiveList_ListFilesCorrectly()
5874
{
5975
var path = Path.Combine(Context.UnityDataFolder, "assetbundle");
6076

@@ -63,7 +79,7 @@ public void ArchiveList_ListFilesCorrectly()
6379
var currentOut = Console.Out;
6480
Console.SetOut(sw);
6581

66-
Assert.AreEqual(0, Program.Main(new string[] { "archive", "list", path }));
82+
Assert.AreEqual(0, await Program.Main(new string[] { "archive", "list", path }));
6783

6884
var lines = sw.ToString().Split(sw.NewLine);
6985

@@ -83,13 +99,13 @@ public void ArchiveList_ListFilesCorrectly()
8399
}
84100

85101
[Test]
86-
public void DumpText_DefaultArgs_TextFileCreatedCorrectly(
102+
public async Task DumpText_DefaultArgs_TextFileCreatedCorrectly(
87103
[Values("", "-f text", "--output-format text")] string options)
88104
{
89105
var path = Path.Combine(Context.UnityDataFolder, "assetbundle");
90106
var outputFile = Path.Combine(m_TestOutputFolder, "CAB-5d40f7cad7c871cf2ad2af19ac542994.txt");
91107

92-
Assert.AreEqual(0, Program.Main(new string[] { "dump", path }.Concat(options.Split(" ", StringSplitOptions.RemoveEmptyEntries)).ToArray()));
108+
Assert.AreEqual(0, await Program.Main(new string[] { "dump", path }.Concat(options.Split(" ", StringSplitOptions.RemoveEmptyEntries)).ToArray()));
93109
Assert.IsTrue(File.Exists(outputFile));
94110

95111
var content = File.ReadAllText(outputFile);
@@ -103,13 +119,13 @@ public void DumpText_DefaultArgs_TextFileCreatedCorrectly(
103119
}
104120

105121
[Test]
106-
public void DumpText_SkipLargeArrays_TextFileCreatedCorrectly(
122+
public async Task DumpText_SkipLargeArrays_TextFileCreatedCorrectly(
107123
[Values("-s", "--skip-large-arrays")] string options)
108124
{
109125
var path = Path.Combine(Context.UnityDataFolder, "assetbundle");
110126
var outputFile = Path.Combine(m_TestOutputFolder, "CAB-5d40f7cad7c871cf2ad2af19ac542994.txt");
111127

112-
Assert.AreEqual(0, Program.Main(new string[] { "dump", path }.Concat(options.Split(" ", StringSplitOptions.RemoveEmptyEntries)).ToArray()));
128+
Assert.AreEqual(0, await Program.Main(new string[] { "dump", path }.Concat(options.Split(" ", StringSplitOptions.RemoveEmptyEntries)).ToArray()));
113129
Assert.IsTrue(File.Exists(outputFile));
114130

115131
var content = File.ReadAllText(outputFile);
@@ -123,48 +139,48 @@ public void DumpText_SkipLargeArrays_TextFileCreatedCorrectly(
123139
}
124140

125141
[Test]
126-
public void Analyze_DefaultArgs_DatabaseCorrect()
142+
public async Task Analyze_DefaultArgs_DatabaseCorrect()
127143
{
128144
var databasePath = Path.Combine(m_TestOutputFolder, "database.db");
129145
var analyzePath = Path.Combine(Context.UnityDataFolder);
130146

131-
Assert.AreEqual(0, Program.Main(new string[] { "analyze", analyzePath }));
147+
Assert.AreEqual(0, await Program.Main(new string[] { "analyze", analyzePath }));
132148

133149
ValidateDatabase(databasePath, false);
134150
}
135151

136152
[Test]
137-
public void Analyze_WithRefs_DatabaseCorrect(
153+
public async Task Analyze_WithRefs_DatabaseCorrect(
138154
[Values("-r", "--extract-references")] string options)
139155
{
140156
var databasePath = Path.Combine(m_TestOutputFolder, "database.db");
141157
var analyzePath = Path.Combine(Context.UnityDataFolder);
142158

143-
Assert.AreEqual(0, Program.Main(new string[] { "analyze", analyzePath }.Concat(options.Split(" ")).ToArray()));
159+
Assert.AreEqual(0, await Program.Main(new string[] { "analyze", analyzePath }.Concat(options.Split(" ")).ToArray()));
144160

145161
ValidateDatabase(databasePath, true);
146162
}
147163

148164
[Test]
149-
public void Analyze_WithPattern_DatabaseCorrect(
165+
public async Task Analyze_WithPattern_DatabaseCorrect(
150166
[Values("-p *.", "--search-pattern *.")] string options)
151167
{
152168
var databasePath = Path.Combine(m_TestOutputFolder, "database.db");
153169
var analyzePath = Path.Combine(Context.UnityDataFolder);
154170

155-
Assert.AreEqual(0, Program.Main(new string[] { "analyze", analyzePath }.Concat(options.Split(" ")).ToArray()));
171+
Assert.AreEqual(0, await Program.Main(new string[] { "analyze", analyzePath }.Concat(options.Split(" ")).ToArray()));
156172

157173
ValidateDatabase(databasePath, false);
158174
}
159175

160176
[Test]
161-
public void Analyze_WithPatternNoMatch_DatabaseEmpty(
177+
public async Task Analyze_WithPatternNoMatch_DatabaseEmpty(
162178
[Values("-p *.x", "--search-pattern *.x")] string options)
163179
{
164180
var databasePath = Path.Combine(m_TestOutputFolder, "database.db");
165181
var analyzePath = Path.Combine(Context.UnityDataFolder);
166182

167-
Assert.AreEqual(0, Program.Main(new string[] { "analyze", analyzePath }.Concat(options.Split(" ")).ToArray()));
183+
Assert.AreEqual(0, await Program.Main(new string[] { "analyze", analyzePath }.Concat(options.Split(" ")).ToArray()));
168184

169185
using var db = new SQLiteConnection($"Data Source={databasePath};Version=3;New=True;Foreign Keys=False;");
170186
db.Open();
@@ -178,13 +194,13 @@ public void Analyze_WithPatternNoMatch_DatabaseEmpty(
178194
}
179195

180196
[Test]
181-
public void Analyze_WithOutputFile_DatabaseCorrect(
197+
public async Task Analyze_WithOutputFile_DatabaseCorrect(
182198
[Values("-o my_database", "--output-file my_database")] string options)
183199
{
184200
var databasePath = Path.Combine(m_TestOutputFolder, "my_database");
185201
var analyzePath = Path.Combine(Context.UnityDataFolder);
186202

187-
Assert.AreEqual(0, Program.Main(new string[] { "analyze", analyzePath }.Concat(options.Split(" ")).ToArray()));
203+
Assert.AreEqual(0, await Program.Main(new string[] { "analyze", analyzePath }.Concat(options.Split(" ")).ToArray()));
188204

189205
ValidateDatabase(databasePath, false);
190206
}
@@ -197,7 +213,7 @@ private void ValidateDatabase(string databasePath, bool withRefs)
197213
using (var cmd = db.CreateCommand())
198214
{
199215
cmd.CommandText =
200-
@"SELECT
216+
@"SELECT
201217
(SELECT COUNT(*) FROM animation_clips),
202218
(SELECT COUNT(*) FROM asset_bundles),
203219
(SELECT COUNT(*) FROM assets),
@@ -259,21 +275,21 @@ public void Teardown()
259275
file.Delete();
260276
}
261277
}
262-
278+
263279
[Test]
264-
public void Analyze_PlayerData_DatabaseCorrect()
280+
public async Task Analyze_PlayerData_DatabaseCorrect()
265281
{
266282
var databasePath = Path.Combine(m_TestOutputFolder, "database.db");
267283
var analyzePath = Path.Combine(Context.UnityDataFolder);
268284

269-
Assert.AreEqual(0, Program.Main(new string[] { "analyze", analyzePath, "-r" }));
270-
285+
Assert.AreEqual(0, await Program.Main(new string[] { "analyze", analyzePath, "-r" }));
286+
271287
using var db = new SQLiteConnection($"Data Source={databasePath};Version=3;New=True;Foreign Keys=False;");
272288
db.Open();
273289
using var cmd = db.CreateCommand();
274290

275291
cmd.CommandText =
276-
@"SELECT
292+
@"SELECT
277293
(SELECT COUNT(*) FROM asset_bundles),
278294
(SELECT COUNT(*) FROM assets),
279295
(SELECT COUNT(*) FROM objects),
@@ -290,14 +306,14 @@ public void Analyze_PlayerData_DatabaseCorrect()
290306
Assert.Greater(reader.GetInt32(3), 0);
291307
Assert.AreEqual(1, reader.GetInt32(4));
292308
}
293-
309+
294310
[Test]
295-
public void DumpText_PlayerData_TextFileCreatedCorrectly()
311+
public async Task DumpText_PlayerData_TextFileCreatedCorrectly()
296312
{
297313
var path = Path.Combine(Context.UnityDataFolder, "level0");
298314
var outputFile = Path.Combine(m_TestOutputFolder, "level0.txt");
299315

300-
Assert.AreEqual(0, Program.Main(new string[] { "dump", path }));
316+
Assert.AreEqual(0, await Program.Main(new string[] { "dump", path }));
301317
Assert.IsTrue(File.Exists(outputFile));
302318

303319
var content = File.ReadAllText(outputFile);

UnityDataTool/Program.cs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.CommandLine;
33
using System.IO;
4+
using System.Threading.Tasks;
45
using UnityDataTools.Analyzer;
56
using UnityDataTools.Analyzer.SQLite.Handlers;
67
using UnityDataTools.ReferenceFinder;
@@ -11,10 +12,10 @@ namespace UnityDataTools.UnityDataTool;
1112

1213
public static class Program
1314
{
14-
public static int Main(string[] args)
15+
public static async Task<int> Main(string[] args)
1516
{
1617
UnityFileSystem.Init();
17-
18+
1819
var rootCommand = new RootCommand();
1920

2021
{
@@ -33,7 +34,7 @@ public static int Main(string[] args)
3334

3435
analyzeCommand.AddAlias("analyse");
3536
analyzeCommand.SetHandler(
36-
(DirectoryInfo di, string o, bool r, string p) => HandleAnalyze(di, o, r, p),
37+
(DirectoryInfo di, string o, bool r, string p) => Task.FromResult(HandleAnalyze(di, o, r, p)),
3738
pathArg, oOpt, rOpt, pOpt);
3839

3940
rootCommand.AddCommand(analyzeCommand);
@@ -58,7 +59,7 @@ public static int Main(string[] args)
5859
};
5960

6061
findRefsCommand.SetHandler(
61-
(FileInfo fi, string o, long? i, string n, string t, bool a) => HandleFindReferences(fi, o, i, n, t, a),
62+
(FileInfo fi, string o, long? i, string n, string t, bool a) => Task.FromResult(HandleFindReferences(fi, o, i, n, t, a)),
6263
pathArg, oOpt, iOpt, nOpt, tOpt, aOpt);
6364

6465
rootCommand.Add(findRefsCommand);
@@ -78,31 +79,33 @@ public static int Main(string[] args)
7879
oOpt,
7980
};
8081
dumpCommand.SetHandler(
81-
(FileInfo fi, DumpFormat f, bool s, DirectoryInfo o) => HandleDump(fi, f, s, o),
82+
(FileInfo fi, DumpFormat f, bool s, DirectoryInfo o) => Task.FromResult(HandleDump(fi, f, s, o)),
8283
pathArg, fOpt, sOpt, oOpt);
8384

8485
rootCommand.AddCommand(dumpCommand);
8586
}
8687

8788
{
8889
var pathArg = new Argument<FileInfo>("filename", "The path of the archive file").ExistingOnly();
90+
var oOpt = new Option<DirectoryInfo>(aliases: new[] { "--output-path", "-o" }, description: "Output directory of the extracted archive", getDefaultValue: () => new DirectoryInfo("archive"));
8991

9092
var extractArchiveCommand = new Command("extract", "Extract the archive.")
9193
{
9294
pathArg,
95+
oOpt,
9396
};
9497

9598
extractArchiveCommand.SetHandler(
96-
(FileInfo fi) => HandleExtractArchive(fi),
97-
pathArg);
99+
(FileInfo fi, DirectoryInfo o) => Task.FromResult(HandleExtractArchive(fi, o)),
100+
pathArg, oOpt);
98101

99102
var listArchiveCommand = new Command("list", "List the content of an archive.")
100103
{
101104
pathArg,
102105
};
103106

104107
listArchiveCommand.SetHandler(
105-
(FileInfo fi) => HandleListArchive(fi),
108+
(FileInfo fi) => Task.FromResult(HandleListArchive(fi)),
106109
pathArg);
107110

108111
var archiveCommand = new Command("archive", "Unity Archive (AssetBundle) functions.")
@@ -114,8 +117,8 @@ public static int Main(string[] args)
114117
rootCommand.AddCommand(archiveCommand);
115118
}
116119

117-
var r = rootCommand.Invoke(args);
118-
120+
var r = await rootCommand.InvokeAsync(args);
121+
119122
UnityFileSystem.Cleanup();
120123

121124
return r;
@@ -129,7 +132,7 @@ enum DumpFormat
129132
static int HandleAnalyze(DirectoryInfo path, string outputFile, bool extractReferences, string searchPattern)
130133
{
131134
var analyzer = new AnalyzerTool();
132-
135+
133136
return analyzer.Analyze(path.FullName, outputFile, searchPattern, extractReferences);
134137
}
135138

@@ -167,15 +170,15 @@ static int HandleDump(FileInfo filename, DumpFormat format, bool skipLargeArrays
167170
return 1;
168171
}
169172

170-
static int HandleExtractArchive(FileInfo filename)
173+
static int HandleExtractArchive(FileInfo filename, DirectoryInfo outputFolder)
171174
{
172175
try
173176
{
174177
using var archive = UnityFileSystem.MountArchive(filename.FullName, "/");
175178
foreach (var node in archive.Nodes)
176179
{
177180
Console.WriteLine($"Extracting {node.Path}...");
178-
CopyFile("/" + node.Path, Path.GetFileName(node.Path));
181+
CopyFile("/" + node.Path, Path.Combine(outputFolder.FullName, node.Path));
179182
}
180183
}
181184
catch (NotSupportedException)
@@ -212,6 +215,8 @@ static int HandleListArchive(FileInfo filename)
212215
static void CopyFile(string source, string dest)
213216
{
214217
using var sourceFile = UnityFileSystem.OpenFile(source);
218+
// Create the containing directory if it doesn't exist.
219+
Directory.CreateDirectory(Path.GetDirectoryName(dest));
215220
using var destFile = new FileStream(dest, FileMode.Create);
216221

217222
const int blockSize = 256 * 1024;
@@ -225,4 +230,4 @@ static void CopyFile(string source, string dest)
225230
}
226231
while (actualSize == blockSize);
227232
}
228-
}
233+
}

UnityDataTool/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ information about the content of the output file.**
8888
The archive command offers a set of archive-related sub-commands.
8989

9090
**extract** This sub-command extracts the content of an archive. It takes the archive path as
91-
argument.
91+
argument and also provides the following option:
92+
* -o, --output-path \<path\>: Output directory of the extracted archive (default: archive)
9293

9394
**list** This sub-command lists the content of an archive. It takes the archive path as argument.

0 commit comments

Comments
 (0)