From 15e228f28793778a2182127845d44f16a223a152 Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Wed, 28 Jun 2023 13:33:16 -0500 Subject: [PATCH] Adds GameSave.sha1 to sync hash between devices Fixes redundant record uploads post-sync due to comparing hashes against locally-cached hash via extended attributes. --- Delta.xcodeproj/project.pbxproj | 6 +-- .../Delta 6.xcdatamodel/contents | 12 +---- Delta/Database/Model/Human/GameSave.swift | 2 +- Delta/Database/Model/Machine/_GameSave.swift | 2 + Delta/Emulation/GameViewController.swift | 6 ++- Delta/Extensions/URL+ExtendedAttributes.swift | 45 ------------------- 6 files changed, 10 insertions(+), 63 deletions(-) delete mode 100644 Delta/Extensions/URL+ExtendedAttributes.swift diff --git a/Delta.xcodeproj/project.pbxproj b/Delta.xcodeproj/project.pbxproj index bba44bf..8b2d7b2 100644 --- a/Delta.xcodeproj/project.pbxproj +++ b/Delta.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -160,7 +160,6 @@ BFFA4C091E8A24D600D87934 /* GameTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFFA4C081E8A24D600D87934 /* GameTableViewCell.swift */; }; BFFA71DD1AAC406100EE9DD1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFFA71DC1AAC406100EE9DD1 /* AppDelegate.swift */; }; BFFA71E21AAC406100EE9DD1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFFA71E01AAC406100EE9DD1 /* Main.storyboard */; }; - BFFBD3D9224A0756002EFC79 /* URL+ExtendedAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFFBD3D8224A0756002EFC79 /* URL+ExtendedAttributes.swift */; }; BFFC461E1D59823500AF2CC6 /* GamesPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFFC461B1D59823500AF2CC6 /* GamesPresentationController.swift */; }; BFFC461F1D59823500AF2CC6 /* GamesStoryboardSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFFC461C1D59823500AF2CC6 /* GamesStoryboardSegue.swift */; }; BFFC46201D59823500AF2CC6 /* InitialGamesStoryboardSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFFC461D1D59823500AF2CC6 /* InitialGamesStoryboardSegue.swift */; }; @@ -422,7 +421,6 @@ BFFA71DB1AAC406100EE9DD1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; BFFA71DC1AAC406100EE9DD1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; BFFA71E11AAC406100EE9DD1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - BFFBD3D8224A0756002EFC79 /* URL+ExtendedAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+ExtendedAttributes.swift"; sourceTree = ""; }; BFFC461B1D59823500AF2CC6 /* GamesPresentationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GamesPresentationController.swift; sourceTree = ""; }; BFFC461C1D59823500AF2CC6 /* GamesStoryboardSegue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GamesStoryboardSegue.swift; sourceTree = ""; }; BFFC461D1D59823500AF2CC6 /* InitialGamesStoryboardSegue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InitialGamesStoryboardSegue.swift; sourceTree = ""; }; @@ -536,7 +534,6 @@ BF6424841F5CBDC900D6AB44 /* UIView+ParentViewController.swift */, BFC3627F21ADE2BA00EF2BE6 /* UIAlertController+Error.swift */, BF1F45AC21AF57BA00EF9895 /* HarmonyMetadataKey+Keys.swift */, - BFFBD3D8224A0756002EFC79 /* URL+ExtendedAttributes.swift */, BF647A6922FB8FCE0061D76D /* Bundle+SwizzleBundleID.swift */, BFD1EF3F2336BD8800D197CF /* UIDevice+Processor.swift */, BFE56E1823EB7BE00014FECD /* UIImage+SymbolFallback.swift */, @@ -1611,7 +1608,6 @@ BF4828861F9028F500028B97 /* System.swift in Sources */, BF13A7561D5D29B0000BB055 /* PreviewGameViewController.swift in Sources */, BF6866171DCAC8B900BF2D06 /* ControllerSkin+Configuring.swift in Sources */, - BFFBD3D9224A0756002EFC79 /* URL+ExtendedAttributes.swift in Sources */, BF713C0822499ED4004A1A2B /* PreviousHarmony.xcdatamodeld in Sources */, BF59427D1E09BC830051894B /* ControllerSkin.swift in Sources */, BFAB9F7D219A43380080EC7D /* SyncManager.swift in Sources */, diff --git a/Delta/Database/Model/Delta.xcdatamodeld/Delta 6.xcdatamodel/contents b/Delta/Database/Model/Delta.xcdatamodeld/Delta 6.xcdatamodel/contents index 5f52f6b..348520d 100644 --- a/Delta/Database/Model/Delta.xcdatamodeld/Delta 6.xcdatamodel/contents +++ b/Delta/Database/Model/Delta.xcdatamodeld/Delta 6.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -117,6 +117,7 @@ + @@ -148,13 +149,4 @@ - - - - - - - - - \ No newline at end of file diff --git a/Delta/Database/Model/Human/GameSave.swift b/Delta/Database/Model/Human/GameSave.swift index 2f3ee32..9e9f41d 100644 --- a/Delta/Database/Model/Human/GameSave.swift +++ b/Delta/Database/Model/Human/GameSave.swift @@ -30,7 +30,7 @@ extension GameSave: Syncable } public var syncableKeys: Set { - return [\GameSave.modifiedDate] + return [\GameSave.modifiedDate, \GameSave.sha1] } public var syncableRelationships: Set { diff --git a/Delta/Database/Model/Machine/_GameSave.swift b/Delta/Database/Model/Machine/_GameSave.swift index 04dfe45..adba6a3 100644 --- a/Delta/Database/Model/Machine/_GameSave.swift +++ b/Delta/Database/Model/Machine/_GameSave.swift @@ -18,6 +18,8 @@ public class _GameSave: NSManagedObject @NSManaged public var modifiedDate: Date + @NSManaged public var sha1: String? + // MARK: - Relationships @NSManaged public var game: Game? diff --git a/Delta/Emulation/GameViewController.swift b/Delta/Emulation/GameViewController.swift index 1e456ff..39ed472 100644 --- a/Delta/Emulation/GameViewController.swift +++ b/Delta/Emulation/GameViewController.swift @@ -755,23 +755,25 @@ private extension GameViewController let game = context.object(with: game.objectID) as! Game let hash = try RSTHasher.sha1HashOfFile(at: game.gameSaveURL) - let previousHash = game.gameSaveURL.extendedAttribute(name: "com.rileytestut.delta.sha1Hash") + let previousHash = game.gameSave?.sha1 guard hash != previousHash else { return } if let gameSave = game.gameSave { gameSave.modifiedDate = Date() + gameSave.sha1 = hash } else { let gameSave = GameSave(context: context) gameSave.identifier = game.identifier + gameSave.sha1 = hash + game.gameSave = gameSave } try context.save() - try game.gameSaveURL.setExtendedAttribute(name: "com.rileytestut.delta.sha1Hash", value: hash) if ExperimentalFeatures.shared.toastNotifications.gameSaveEnabled { diff --git a/Delta/Extensions/URL+ExtendedAttributes.swift b/Delta/Extensions/URL+ExtendedAttributes.swift deleted file mode 100644 index 596ef1c..0000000 --- a/Delta/Extensions/URL+ExtendedAttributes.swift +++ /dev/null @@ -1,45 +0,0 @@ -// -// URL+ExtendedAttributes.swift -// Delta -// -// Created by Riley Testut on 3/26/19. -// Copyright © 2019 Riley Testut. All rights reserved. -// - -import Foundation - -extension URL -{ - func setExtendedAttribute(name: String, value: String) throws - { - try self.withUnsafeFileSystemRepresentation { (path) in - let data = value.data(using: .utf8) - let result = data?.withUnsafeBytes { (buffer) in - setxattr(path, name, buffer.baseAddress, buffer.count, 0, 0) - } - - if let result = result, result < 0 - { - throw POSIXError(POSIXErrorCode(rawValue: errno) ?? .ENOENT) - } - } - } - - func extendedAttribute(name: String) -> String? - { - let value = self.withUnsafeFileSystemRepresentation { (path) -> String? in - let size = getxattr(path, name, nil, 0, 0, 0) - guard size >= 0 else { return nil } - - var data = Data(count: size) - let result = data.withUnsafeMutableBytes { getxattr(path, name, $0.baseAddress, $0.count, 0, 0) } - - guard result >= 0 else { return nil } - - let value = String(data: data, encoding: .utf8)! - return value - } - - return value - } -}