Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip corrupted .acf files in Steam library #4200

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Core/Extensions/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,22 @@ public static IEnumerable<Match> WithMatches(this IEnumerable<string> source, Re
=> source.Select(val => pattern.TryMatch(val, out Match? match) ? match : null)
.OfType<Match>();

/// <summary>
/// Apply a function to a sequence and handle any exceptions that are thrown
/// </summary>
/// <typeparam name="TSrc">Type of source sequence</typeparam>
/// <typeparam name="TDest">Type of destination sequence</typeparam>
/// <param name="source">Source sequence</param>
/// <param name="func">Function to apply to each item</param>
/// <param name="onThrow">Function to call if there's an exception</param>
/// <returns>Sequence of return values of given function</returns>
public static IEnumerable<TDest?> SelectWithCatch<TSrc, TDest>(this IEnumerable<TSrc> source,
Func<TSrc, TDest> func,
Func<TSrc, Exception, TDest?> onThrow)
where TDest : class
=> source.Select(item => Utilities.DefaultIfThrows(() => func(item),
exc => onThrow(item, exc)));

}

/// <summary>
Expand Down
11 changes: 9 additions & 2 deletions Core/SteamLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using log4net;
using ValveKeyValue;
using CKAN.Extensions;

namespace CKAN
{
Expand Down Expand Up @@ -57,8 +58,14 @@ public IEnumerable<Uri> GameAppURLs(DirectoryInfo gameDir)
private static IEnumerable<GameBase> LibraryPathGames(KVSerializer acfParser,
string appPath)
=> Directory.EnumerateFiles(appPath, "*.acf")
.Select(acfFile => acfParser.Deserialize<SteamGame>(File.OpenRead(acfFile))
.NormalizeDir(Path.Combine(appPath, "common")));
.SelectWithCatch(acfFile => acfParser.Deserialize<SteamGame>(File.OpenRead(acfFile))
.NormalizeDir(Path.Combine(appPath, "common")),
(acfFile, exc) =>
{
log.Warn($"Failed to parse {acfFile}:", exc);
return default;
})
.OfType<GameBase>();

private static IEnumerable<GameBase> ShortcutsFileGames(KVSerializer vdfParser,
string path)
Expand Down
14 changes: 11 additions & 3 deletions Core/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,23 @@ public static class Utilities
"nl-NL",
};

public static T? DefaultIfThrows<T>(Func<T?> func) where T : class
/// <summary>
/// Call a function and take a default action if it throws an exception
/// </summary>
/// <typeparam name="T">Return type of the function</typeparam>
/// <param name="func">Function to call</param>
/// <param name="onThrow">Function to call if an exception is thrown</param>
/// <returns>Return value of the function</returns>
public static T? DefaultIfThrows<T>(Func<T?> func,
Func<Exception, T?>? onThrow = null) where T : class
{
try
{
return func();
}
catch
catch (Exception exc)
{
return default;
return onThrow?.Invoke(exc) ?? default;
}
}

Expand Down