Skip to content

Commit 1e57b74

Browse files
committed
Handle file writing errors for movies and all tools.
1 parent 5559b48 commit 1e57b74

File tree

14 files changed

+297
-173
lines changed

14 files changed

+297
-173
lines changed

src/BizHawk.Client.Common/DialogControllerExtensions.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55

66
namespace BizHawk.Client.Common
77
{
8+
public enum TryAgainResult
9+
{
10+
Saved,
11+
IgnoredFailure,
12+
Canceled,
13+
}
14+
815
public static class DialogControllerExtensions
916
{
1017
public static void AddOnScreenMessage(this IDialogParent dialogParent, string message, int? duration = null)
@@ -80,7 +87,7 @@ public static void ErrorMessageBox(
8087
/// The user will be repeatedly asked if they want to try again until either success or the user says no.
8188
/// </summary>
8289
/// <returns>Returns true on success or if the user said no. Returns false if the user said cancel.</returns>
83-
public static bool DoWithTryAgainBox(
90+
public static TryAgainResult DoWithTryAgainBox(
8491
this IDialogParent dialogParent,
8592
Func<FileWriteResult> action,
8693
string message)
@@ -94,12 +101,12 @@ public static bool DoWithTryAgainBox(
94101
$"{fileResult.UserFriendlyErrorMessage()}\n{fileResult.Exception!.Message}",
95102
caption: "Error",
96103
icon: EMsgBoxIcon.Error);
97-
if (askResult == null) return false;
98-
if (askResult == false) return true;
104+
if (askResult == null) return TryAgainResult.Canceled;
105+
if (askResult == false) return TryAgainResult.IgnoredFailure;
99106
if (askResult == true) fileResult = action();
100107
}
101108

102-
return true;
109+
return TryAgainResult.Saved;
103110
}
104111

105112
/// <summary>Creates and shows a <c>System.Windows.Forms.OpenFileDialog</c> or equivalent with the receiver (<paramref name="dialogParent"/>) as its parent</summary>

src/BizHawk.Client.Common/FileWriter.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,22 @@ public static FileWriteResult Write(string path, byte[] bytes, string? backupPat
5656
return createResult.Value.CloseAndDispose(backupPath);
5757
}
5858

59+
public static FileWriteResult Write(string path, Action<Stream> writeCallback, string? backupPath = null)
60+
{
61+
FileWriteResult<FileWriter> createResult = Create(path);
62+
if (createResult.IsError) return createResult;
63+
64+
try
65+
{
66+
writeCallback(createResult.Value!.Stream);
67+
}
68+
catch (Exception ex)
69+
{
70+
return new(FileWriteEnum.FailedDuringWrite, createResult.Value!.Paths, ex);
71+
}
72+
73+
return createResult.Value.CloseAndDispose(backupPath);
74+
}
5975

6076
/// <summary>
6177
/// Create a FileWriter instance, or return an error if unable to access the file.
@@ -76,6 +92,7 @@ public static FileWriteResult<FileWriter> Create(string path)
7692
FileWritePaths paths = new(path, writePath);
7793
try
7894
{
95+
Directory.CreateDirectory(Path.GetDirectoryName(path));
7996
FileStream fs = new(writePath, FileMode.Create, FileAccess.Write);
8097
return new(new FileWriter(paths, fs), paths);
8198
}

src/BizHawk.Client.Common/lua/LuaFileList.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,8 @@ public bool Load(string path, bool disableOnLoad)
102102
return true;
103103
}
104104

105-
public void Save(string path)
105+
public FileWriteResult Save(string path)
106106
{
107-
using var sw = new StreamWriter(path);
108107
var sb = new StringBuilder();
109108
var saveDirectory = Path.GetDirectoryName(Path.GetFullPath(path));
110109
foreach (var file in this)
@@ -123,10 +122,19 @@ public void Save(string path)
123122
}
124123
}
125124

126-
sw.Write(sb.ToString());
125+
FileWriteResult result = FileWriter.Write(path, (fs) =>
126+
{
127+
using var sw = new StreamWriter(fs);
128+
sw.Write(sb.ToString());
129+
});
127130

128-
Filename = path;
129-
Changes = false;
131+
if (!result.IsError)
132+
{
133+
Filename = path;
134+
Changes = false;
135+
}
136+
137+
return result;
130138
}
131139
}
132140
}

src/BizHawk.Client.Common/movie/MovieSession.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,8 @@ private void HandlePlaybackEnd()
385385
switch (Settings.MovieEndAction)
386386
{
387387
case MovieEndAction.Stop:
388+
// Technically this can save the movie, but it'd be weird to be in that situation.
389+
// Do we want that?
388390
StopMovie();
389391
break;
390392
case MovieEndAction.Record:

src/BizHawk.Client.Common/tools/CheatList.cs

Lines changed: 52 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -88,20 +88,10 @@ public bool AttemptToLoadCheatFile(IMemoryDomains domains)
8888
return file.Exists && Load(domains, file.FullName, false);
8989
}
9090

91-
public void NewList(string defaultFileName, bool autosave = false)
91+
public void NewList(string defaultFileName)
9292
{
9393
_defaultFileName = defaultFileName;
9494

95-
if (autosave && _changes && _cheatList.Count is not 0)
96-
{
97-
if (string.IsNullOrEmpty(CurrentFileName))
98-
{
99-
CurrentFileName = _defaultFileName;
100-
}
101-
102-
Save();
103-
}
104-
10595
_cheatList.Clear();
10696
CurrentFileName = "";
10797
Changes = false;
@@ -220,7 +210,7 @@ public void DisableAll()
220210
public bool IsActive(MemoryDomain domain, long address)
221211
=> _cheatList.Exists(cheat => !cheat.IsSeparator && cheat.Enabled && cheat.Domain == domain && cheat.Contains(address));
222212

223-
public void SaveOnClose()
213+
public FileWriteResult SaveOnClose()
224214
{
225215
if (_config.AutoSaveOnClose)
226216
{
@@ -231,17 +221,27 @@ public void SaveOnClose()
231221
CurrentFileName = _defaultFileName;
232222
}
233223

234-
SaveFile(CurrentFileName);
224+
return SaveFile(CurrentFileName);
235225
}
236226
else if (_cheatList.Count is 0 && !string.IsNullOrWhiteSpace(CurrentFileName))
237227
{
238-
File.Delete(CurrentFileName);
228+
try
229+
{
230+
File.Delete(CurrentFileName);
231+
}
232+
catch (Exception ex)
233+
{
234+
return new(FileWriteEnum.FailedToDeleteGeneric, new(CurrentFileName, ""), ex);
235+
}
239236
_config.Recent.Remove(CurrentFileName);
237+
return new();
240238
}
241239
}
240+
241+
return new();
242242
}
243243

244-
public bool Save()
244+
public FileWriteResult Save()
245245
{
246246
if (string.IsNullOrWhiteSpace(CurrentFileName))
247247
{
@@ -251,54 +251,51 @@ public bool Save()
251251
return SaveFile(CurrentFileName);
252252
}
253253

254-
public bool SaveFile(string path)
254+
public FileWriteResult SaveFile(string path)
255255
{
256-
try
257-
{
258-
new FileInfo(path).Directory?.Create();
259-
var sb = new StringBuilder();
256+
var sb = new StringBuilder();
260257

261-
foreach (var cheat in _cheatList)
258+
foreach (var cheat in _cheatList)
259+
{
260+
if (cheat.IsSeparator)
262261
{
263-
if (cheat.IsSeparator)
264-
{
265-
sb.AppendLine("----");
266-
}
267-
else
268-
{
269-
// Set to hex for saving
270-
var tempCheatType = cheat.Type;
271-
272-
cheat.SetType(WatchDisplayType.Hex);
273-
274-
sb
275-
.Append(cheat.AddressStr).Append('\t')
276-
.Append(cheat.ValueStr).Append('\t')
277-
.Append(cheat.Compare is null ? "N" : cheat.CompareStr).Append('\t')
278-
.Append(cheat.Domain != null ? cheat.Domain.Name : "").Append('\t')
279-
.Append(cheat.Enabled ? '1' : '0').Append('\t')
280-
.Append(cheat.Name).Append('\t')
281-
.Append(cheat.SizeAsChar).Append('\t')
282-
.Append(cheat.TypeAsChar).Append('\t')
283-
.Append(cheat.BigEndian is true ? '1' : '0').Append('\t')
284-
.Append(cheat.ComparisonType).Append('\t')
285-
.AppendLine();
286-
287-
cheat.SetType(tempCheatType);
288-
}
262+
sb.AppendLine("----");
289263
}
290-
291-
File.WriteAllText(path, sb.ToString());
292-
264+
else
265+
{
266+
// Set to hex for saving
267+
var tempCheatType = cheat.Type;
268+
269+
cheat.SetType(WatchDisplayType.Hex);
270+
271+
sb
272+
.Append(cheat.AddressStr).Append('\t')
273+
.Append(cheat.ValueStr).Append('\t')
274+
.Append(cheat.Compare is null ? "N" : cheat.CompareStr).Append('\t')
275+
.Append(cheat.Domain != null ? cheat.Domain.Name : "").Append('\t')
276+
.Append(cheat.Enabled ? '1' : '0').Append('\t')
277+
.Append(cheat.Name).Append('\t')
278+
.Append(cheat.SizeAsChar).Append('\t')
279+
.Append(cheat.TypeAsChar).Append('\t')
280+
.Append(cheat.BigEndian is true ? '1' : '0').Append('\t')
281+
.Append(cheat.ComparisonType).Append('\t')
282+
.AppendLine();
283+
284+
cheat.SetType(tempCheatType);
285+
}
286+
}
287+
FileWriteResult result = FileWriter.Write(path, (fs) =>
288+
{
289+
StreamWriter sw = new(fs);
290+
sw.Write(sb.ToString());
291+
});
292+
if (!result.IsError)
293+
{
293294
CurrentFileName = path;
294295
_config.Recent.Add(CurrentFileName);
295296
Changes = false;
296-
return true;
297-
}
298-
catch
299-
{
300-
return false;
301297
}
298+
return result;
302299
}
303300

304301
public bool Load(IMemoryDomains domains, string path, bool append)

src/BizHawk.Client.Common/tools/Watch/WatchList/WatchList.cs

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections;
22
using System.Collections.Generic;
3+
using System.Diagnostics;
34
using System.Globalization;
45
using System.IO;
56
using System.Linq;
@@ -338,39 +339,37 @@ public void Reload()
338339
}
339340
}
340341

341-
public bool Save()
342+
public FileWriteResult Save()
342343
{
343344
if (string.IsNullOrWhiteSpace(CurrentFileName))
344345
{
345-
return false;
346+
return new();
346347
}
347348

348-
using (var sw = new StreamWriter(CurrentFileName))
349-
{
350-
var sb = new StringBuilder();
351-
sb.Append("SystemID ").AppendLine(_systemId);
349+
var sb = new StringBuilder();
350+
sb.Append("SystemID ").AppendLine(_systemId);
352351

353-
foreach (var watch in _watchList)
354-
{
355-
sb.AppendLine(watch.ToString());
356-
}
352+
foreach (var watch in _watchList)
353+
{
354+
sb.AppendLine(watch.ToString());
355+
}
357356

357+
FileWriteResult result = FileWriter.Write(CurrentFileName, (fs) =>
358+
{
359+
using var sw = new StreamWriter(fs);
358360
sw.WriteLine(sb.ToString());
359-
}
361+
});
360362

361-
Changes = false;
362-
return true;
363+
if (!result.IsError) Changes = false;
364+
return result;
363365
}
364366

365-
public bool SaveAs(FileInfo file)
367+
public FileWriteResult SaveAs(FileInfo file)
366368
{
367-
if (file != null)
368-
{
369-
CurrentFileName = file.FullName;
370-
return Save();
371-
}
369+
Debug.Assert(file != null, "Cannot save as without a file name.");
372370

373-
return false;
371+
CurrentFileName = file.FullName;
372+
return Save();
374373
}
375374

376375
private bool LoadFile(string path, bool append)

0 commit comments

Comments
 (0)