From cd3735cd71dfcb14aa09a112ba49f562684915b6 Mon Sep 17 00:00:00 2001 From: Matt Rubin Date: Sun, 14 Apr 2019 19:45:52 -0400 Subject: [PATCH] Fix error handling when aggregating an array of Results The previous implementation never handled failure properly and would crash when attempting to force-unwrap a nonexistent success value. --- SwiftGit2/Repository.swift | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/SwiftGit2/Repository.swift b/SwiftGit2/Repository.swift index 9aa0fc8..11feb25 100644 --- a/SwiftGit2/Repository.swift +++ b/SwiftGit2/Repository.swift @@ -361,11 +361,7 @@ public final class Repository { git_strarray_free(pointer) pointer.deallocate() - let error = remotes.reduce(nil) { $0 == nil ? $0 : $1.error } - if let error = error { - return Result.failure(error) - } - return Result.success(remotes.map { $0.value! }) + return remotes.aggregateResult() } private func remoteLookup(named name: String, _ callback: (Result) -> A) -> A { @@ -431,11 +427,7 @@ public final class Repository { git_strarray_free(pointer) pointer.deallocate() - let error = references.reduce(nil) { $0 == nil ? $0 : $1.error } - if let error = error { - return Result.failure(error) - } - return Result.success(references.map { $0.value! }) + return references.aggregateResult() } /// Load the reference with the given long name (e.g. "refs/heads/master") @@ -951,3 +943,18 @@ public final class Repository { } } } + +private extension Array { + func aggregateResult() -> Result<[Value], Error> where Element == Result { + var values: [Value] = [] + for result in self { + switch result { + case .success(let value): + values.append(value) + case .failure(let error): + return .failure(error) + } + } + return .success(values) + } +}