From c1eede8384554a30bbf812be05da68bf46efe973 Mon Sep 17 00:00:00 2001 From: Evan Hahn Date: Mon, 29 Aug 2022 13:03:45 -0500 Subject: [PATCH] Rewrite `[Pastelog collectLogsWithErrorString]` in Swift This change should have no direct user impact. --- Signal/src/util/Pastelog.m | 47 +++++-------------------- Signal/src/util/Pastelog.swift | 64 ++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 39 deletions(-) diff --git a/Signal/src/util/Pastelog.m b/Signal/src/util/Pastelog.m index 14c293d035..7e2549f2e7 100644 --- a/Signal/src/util/Pastelog.m +++ b/Signal/src/util/Pastelog.m @@ -201,51 +201,19 @@ typedef NS_ERROR_ENUM(PastelogErrorDomain, PastelogError) { { OWSAssertIsOnMainThread(); - NSString *errorString; - NSString *logsDirPath = [self collectLogsWithErrorString:&errorString]; - if (!logsDirPath) { + CollectedLogsResult *collectedLogsResult = [self collectLogs]; + if (!collectedLogsResult.succeeded) { + NSString *errorString = collectedLogsResult.errorString; [Pastelog showFailureAlertWithMessage:errorString ?: @"(unknown error)" logArchiveOrDirectoryPath:nil]; return; } + NSString *logsDirPath = collectedLogsResult.logsDirPath; [AttachmentSharing showShareUIForURL:[NSURL fileURLWithPath:logsDirPath] sender:nil completion:^{ (void)[OWSFileSystem deleteFile:logsDirPath]; }]; } -- (nullable NSString *)collectLogsWithErrorString:(NSString *_Nullable *_Nonnull)errorString -{ - NSDateFormatter *dateFormatter = [NSDateFormatter new]; - [dateFormatter setLocale:[NSLocale currentLocale]]; - [dateFormatter setDateFormat:@"yyyy.MM.dd hh.mm.ss"]; - NSString *dateString = [dateFormatter stringFromDate:[NSDate new]]; - NSString *logsName = [[dateString stringByAppendingString:@" "] stringByAppendingString:NSUUID.UUID.UUIDString]; - - NSString *zipDirPath = [OWSTemporaryDirectory() stringByAppendingPathComponent:logsName]; - [OWSFileSystem ensureDirectoryExists:zipDirPath]; - - NSArray *logFilePaths = DebugLogger.shared.allLogFilePaths; - if (logFilePaths.count < 1) { - *errorString - = NSLocalizedString(@"DEBUG_LOG_ALERT_NO_LOGS", @"Error indicating that no debug logs could be found."); - return nil; - } - - for (NSString *logFilePath in logFilePaths) { - NSString *copyFilePath = [zipDirPath stringByAppendingPathComponent:logFilePath.lastPathComponent]; - NSError *error; - if (![[NSFileManager defaultManager] copyItemAtPath:logFilePath toPath:copyFilePath error:&error]) { - OWSLogError(@"could not copy log file at %@: %@", logFilePath, error); - // Write the error to the file that would have been copied. - [[error description] writeToFile:copyFilePath atomically:YES encoding:NSUTF8StringEncoding error:NULL]; - // We still want to get *some* of the logs. - continue; - } - [OWSFileSystem protectFileOrFolderAtPath:copyFilePath]; - } - return zipDirPath; -} - - (void)uploadLogsWithSuccess:(UploadDebugLogsSuccess)successParam failure:(UploadDebugLogsFailure)failureParam { OWSAssertDebug(successParam); @@ -258,12 +226,13 @@ typedef NS_ERROR_ENUM(PastelogErrorDomain, PastelogError) { }; // Phase 1. Make a local copy of all of the log files. - NSString *errorString; - NSString *zipDirPath = [self collectLogsWithErrorString:&errorString]; - if (!zipDirPath) { + CollectedLogsResult *collectedLogsResult = [self collectLogs]; + if (!collectedLogsResult.succeeded) { + NSString *errorString = collectedLogsResult.errorString; failure(errorString, nil); return; } + NSString *zipDirPath = collectedLogsResult.logsDirPath; // Phase 2. Zip up the log files. NSString *zipFilePath = [zipDirPath stringByAppendingPathExtension:@"zip"]; diff --git a/Signal/src/util/Pastelog.swift b/Signal/src/util/Pastelog.swift index 9097583b8e..e3c30d9c2f 100644 --- a/Signal/src/util/Pastelog.swift +++ b/Signal/src/util/Pastelog.swift @@ -135,3 +135,67 @@ public class DebugLogUploader: NSObject { } } } + +extension Pastelog { + /// The result of the `collectLogs` method. Here because Objective-C can't represent `Result`s. + /// If we migrate its callers to Swift, we should be able to remove this class. + @objc + public class CollectedLogsResult: NSObject { + @objc + public let errorString: String? + + @objc + public let logsDirPath: String? + + @objc + public var succeeded: Bool { errorString == nil } + + init(errorString: String) { + self.errorString = errorString + self.logsDirPath = nil + super.init() + } + + init(logsDirPath: String) { + self.errorString = nil + self.logsDirPath = logsDirPath + super.init() + } + } + + @objc + func collectLogs() -> CollectedLogsResult { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy.MM.dd hh.mm.ss" + let dateString = dateFormatter.string(from: Date()) + let logsName = "\(dateString) \(UUID().uuidString)" + + let zipDirUrl = URL(fileURLWithPath: OWSTemporaryDirectory()).appendingPathComponent(logsName) + let zipDirPath = zipDirUrl.path + OWSFileSystem.ensureDirectoryExists(zipDirPath) + + let logFilePaths = DebugLogger.shared().allLogFilePaths() + if logFilePaths.isEmpty { + let errorString = NSLocalizedString( + "DEBUG_LOG_ALERT_NO_LOGS", + comment: "Error indicating that no debug logs could be found." + ) + return CollectedLogsResult(errorString: errorString) + } + + for logFilePath in logFilePaths { + let lastLogFilePathComponent = URL(fileURLWithPath: logFilePath).lastPathComponent + let copyFilePath = zipDirUrl.appendingPathComponent(lastLogFilePathComponent).path + do { + try FileManager.default.copyItem(atPath: logFilePath, toPath: copyFilePath) + } catch { + Logger.error("could not copy log file at \(logFilePath): \(error)") + // Write the error to the file that would have been copied. + try? error.localizedDescription.write(toFile: copyFilePath, atomically: true, encoding: .utf8) + } + OWSFileSystem.protectFileOrFolder(atPath: copyFilePath) + } + + return CollectedLogsResult(logsDirPath: zipDirPath) + } +}