Skip to content

Commit ce51d90

Browse files
[#117] Warn when analyze overwrites an existing database
Analyze replaces the output database rather than merging into it, which could silently destroy a previous build's database when comparing builds. Print a notice when the output file already exists. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent b93d627 commit ce51d90

3 files changed

Lines changed: 98 additions & 0 deletions

File tree

‎Analyzer/AnalyzerTool.cs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ public int Analyze(AnalyzeOptions options)
6363
return 1;
6464
}
6565

66+
// A single database holds a single build, so replacing it is the expected behaviour, but it
67+
// has to be announced: overwriting the database of a previous build is easy to do by
68+
// accident when comparing builds (issue #117).
69+
if (File.Exists(m_Options.DatabaseName))
70+
{
71+
Console.Error.WriteLine($"Overwriting existing database \"{m_Options.DatabaseName}\" (previous contents are discarded).");
72+
}
73+
6674
using SQLiteWriter writer = new(m_Options.DatabaseName);
6775

6876
try

‎Documentation/command-analyze.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ There is no way to append to an existing database, so every file you want in the
2424
included in a single `analyze` invocation. Pass multiple paths to combine files from more than one
2525
location into the same database.
2626

27+
If the output file already exists it is replaced, and a notice is printed to say so:
28+
29+
```
30+
Overwriting existing database "build1.db" (previous contents are discarded).
31+
```
32+
33+
When comparing builds, give each one its own `-o` path so an earlier build's database is not lost.
34+
See [Comparing builds](comparing-builds.md).
35+
2736
## Examples
2837

2938
Analyze all files in a directory:
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using System.IO;
2+
using System.Linq;
3+
using System.Threading.Tasks;
4+
using Microsoft.Data.Sqlite;
5+
using NUnit.Framework;
6+
7+
namespace UnityDataTools.UnityDataTool.Tests;
8+
9+
#pragma warning disable NUnit2005, NUnit2006
10+
11+
// Analyze replaces an existing output database instead of merging into it. That is the intended
12+
// behaviour, but it must be announced so the database of a previous build is not destroyed
13+
// unnoticed (issue #117).
14+
public class AnalyzeOverwriteTests
15+
{
16+
private const string OverwriteMessage = "Overwriting existing database";
17+
18+
private string m_TestOutputFolder;
19+
private string m_AssetBundlesFolder;
20+
21+
[OneTimeSetUp]
22+
public void OneTimeSetup()
23+
{
24+
m_TestOutputFolder = Path.Combine(TestContext.CurrentContext.TestDirectory, "overwrite_test_folder");
25+
m_AssetBundlesFolder = Path.Combine(TestContext.CurrentContext.TestDirectory, "Data", "AssetBundles", "2019.4.0f1");
26+
Directory.CreateDirectory(m_TestOutputFolder);
27+
Directory.SetCurrentDirectory(m_TestOutputFolder);
28+
}
29+
30+
[TearDown]
31+
public void Teardown()
32+
{
33+
SqliteConnection.ClearAllPools();
34+
var testDir = new DirectoryInfo(m_TestOutputFolder);
35+
testDir.EnumerateFiles().ToList().ForEach(f => f.Delete());
36+
testDir.EnumerateDirectories().ToList().ForEach(d => d.Delete(true));
37+
}
38+
39+
private static async Task<(int exitCode, string stderr)> RunAnalyze(params string[] args)
40+
{
41+
var originalError = System.Console.Error;
42+
using var sw = new StringWriter();
43+
try
44+
{
45+
System.Console.SetError(sw);
46+
var exitCode = await Program.Main(new[] { "analyze" }.Concat(args).ToArray());
47+
return (exitCode, sw.ToString());
48+
}
49+
finally
50+
{
51+
System.Console.SetError(originalError);
52+
}
53+
}
54+
55+
[Test]
56+
public async Task Analyze_NewDatabase_NoOverwriteMessage()
57+
{
58+
var databasePath = SQLTestHelper.GetDatabasePath(m_TestOutputFolder);
59+
60+
var (exitCode, stderr) = await RunAnalyze(m_AssetBundlesFolder, "-o", databasePath);
61+
62+
Assert.AreEqual(0, exitCode);
63+
StringAssert.DoesNotContain(OverwriteMessage, stderr);
64+
}
65+
66+
[Test]
67+
public async Task Analyze_ExistingDatabase_WarnsAboutOverwrite()
68+
{
69+
var databasePath = SQLTestHelper.GetDatabasePath(m_TestOutputFolder);
70+
71+
var (firstExitCode, _) = await RunAnalyze(m_AssetBundlesFolder, "-o", databasePath);
72+
Assert.AreEqual(0, firstExitCode);
73+
SqliteConnection.ClearAllPools();
74+
75+
var (exitCode, stderr) = await RunAnalyze(m_AssetBundlesFolder, "-o", databasePath);
76+
77+
Assert.AreEqual(0, exitCode);
78+
StringAssert.Contains(OverwriteMessage, stderr);
79+
StringAssert.Contains(databasePath, stderr);
80+
}
81+
}

0 commit comments

Comments
 (0)