diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fc20bf54b65..eef7ac3adc0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -309,11 +309,11 @@ jobs: # If the SentryAsyncSafeLog doesn't contain the SENTRY_ASYNC_SAFE_LOG_LEVEL_ERROR this fails. - name: Async Safe Log Level is Error - run: grep -c "SENTRY_ASYNC_SAFE_LOG_LEVEL SENTRY_ASYNC_SAFE_LOG_LEVEL_ERROR" Sources/Sentry/SentryAsyncSafeLog.h + run: grep -c "SENTRY_ASYNC_SAFE_LOG_LEVEL SENTRY_ASYNC_SAFE_LOG_LEVEL_ERROR" Sources/Sentry/_SentryPrivate/include/SentryAsyncSafeLog.h - name: Set Async Safe Log Level to Debug run: | - sed -i '' 's/#define SENTRY_ASYNC_SAFE_LOG_LEVEL SENTRY_ASYNC_SAFE_LOG_LEVEL_ERROR/#define SENTRY_ASYNC_SAFE_LOG_LEVEL SENTRY_ASYNC_SAFE_LOG_LEVEL_TRACE/' Sources/Sentry/SentryAsyncSafeLog.h + sed -i '' 's/#define SENTRY_ASYNC_SAFE_LOG_LEVEL SENTRY_ASYNC_SAFE_LOG_LEVEL_ERROR/#define SENTRY_ASYNC_SAFE_LOG_LEVEL SENTRY_ASYNC_SAFE_LOG_LEVEL_TRACE/' Sources/Sentry/_SentryPrivate/include/SentryAsyncSafeLog.h shell: bash - run: ./scripts/ci-select-xcode.sh 16.3 diff --git a/Package.swift b/Package.swift index d3d94a6b134..3cc076bae2e 100644 --- a/Package.swift +++ b/Package.swift @@ -35,7 +35,9 @@ let package = Package( ], publicHeadersPath: "SentryInternal/" ), - .target(name: "SentryCoreSwift", path: "Sources/Swift/Core") + .target(name: "SentryCoreSwift", path: "Sources/Swift/Core"), + // The name of this package is _SentryPrivate so that it matches the imports already used in Swift code to access ObjC. + .target(name: "_SentryPrivate", dependencies: ["SentryCoreSwift"], path: "Sources/Sentry/_SentryPrivate", cSettings: [.headerSearchPath("Public")]) ], cxxLanguageStandard: .cxx14 ) diff --git a/Samples/iOS-SwiftUI/iOS-SwiftUI.yml b/Samples/iOS-SwiftUI/iOS-SwiftUI.yml index 565dd54887d..99f276b3152 100644 --- a/Samples/iOS-SwiftUI/iOS-SwiftUI.yml +++ b/Samples/iOS-SwiftUI/iOS-SwiftUI.yml @@ -28,7 +28,7 @@ targets: - ../Shared/SampleAssets.xcassets - ../../Sources/Sentry/include/SentryTracer.h - ../../Sources/Sentry/include/SentryPerformanceTracker.h - - ../../Sources/Sentry/Public/SentryProfilingConditionals.h + - ../../Sources/Sentry/_SentryPrivate/Public/SentryProfilingConditionals.h dependencies: - target: Sentry/Sentry - target: Sentry/SentrySwiftUI diff --git a/Sentry.podspec b/Sentry.podspec index b9f02bd4372..d1da898083a 100644 --- a/Sentry.podspec +++ b/Sentry.podspec @@ -38,7 +38,7 @@ Pod::Spec.new do |s| "Sources/SentryCrash/**/*.{h,hpp,m,mm,c,cpp}", "Sources/Swift/**/*.{swift,h,hpp,m,mm,c,cpp}" sp.preserve_path = "Sources/Sentry/include/module.modulemap" sp.public_header_files = - "Sources/Sentry/Public/*.h" + "Sources/Sentry/Public/*.h", "Sources/Sentry/_SentryPrivate/Public/*.h" sp.preserve_path = "Sources/Sentry/include/module.modulemap" sp.resource_bundles = { "Sentry" => "Sources/Resources/PrivacyInfo.xcprivacy" } @@ -50,7 +50,7 @@ Pod::Spec.new do |s| sp.preserve_path = "Sources/Sentry/include/module.modulemap" sp.public_header_files = - "Sources/Sentry/Public/*.h", "Sources/Sentry/include/HybridPublic/*.h" + "Sources/Sentry/Public/*.h", "Sources/Sentry/_SentryPrivate/Public/*.h", "Sources/Sentry/include/HybridPublic/*.h" sp.preserve_path = "Sources/Sentry/include/module.modulemap" sp.resource_bundles = { "Sentry" => "Sources/Resources/PrivacyInfo.xcprivacy" } diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 153edb09c7d..ceb6c71a54c 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -1032,6 +1032,8 @@ FA67DD172DDBD4EA00896B02 /* SentryLogOutput.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCEC2DDBD4EA00896B02 /* SentryLogOutput.swift */; }; FA67DD182DDBD4EA00896B02 /* UIImageHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCED2DDBD4EA00896B02 /* UIImageHelper.swift */; }; FA67DD192DDBD4EA00896B02 /* SwizzleClassNameExclude.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCD52DDBD4EA00896B02 /* SwizzleClassNameExclude.swift */; }; + FA922C342DDD1C730026D187 /* FileUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = FA922C332DDD1C710026D187 /* FileUtils.h */; }; + FA922C362DDD1C790026D187 /* FileUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = FA922C352DDD1C770026D187 /* FileUtils.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1112,7 +1114,7 @@ 035E73CD27D5790A005EEB11 /* SentryThreadMetadataCacheTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SentryThreadMetadataCacheTests.mm; sourceTree = ""; }; 03BCC38927E1BF49003232C7 /* SentryTime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryTime.h; path = Sources/Sentry/include/SentryTime.h; sourceTree = SOURCE_ROOT; }; 03BCC38B27E1C01A003232C7 /* SentryTime.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = SentryTime.mm; path = Sources/Sentry/SentryTime.mm; sourceTree = SOURCE_ROOT; }; - 03BCC38D27E2A377003232C7 /* SentryProfilingConditionals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryProfilingConditionals.h; path = ../Public/SentryProfilingConditionals.h; sourceTree = ""; }; + 03BCC38D27E2A377003232C7 /* SentryProfilingConditionals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryProfilingConditionals.h; path = ../_SentryPrivate/Public/SentryProfilingConditionals.h; sourceTree = ""; }; 03F84D1227DD414C008FE43F /* SentryBacktrace.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentryBacktrace.hpp; path = Sources/Sentry/include/SentryBacktrace.hpp; sourceTree = SOURCE_ROOT; }; 03F84D1427DD414C008FE43F /* SentryStackBounds.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentryStackBounds.hpp; path = Sources/Sentry/include/SentryStackBounds.hpp; sourceTree = SOURCE_ROOT; }; 03F84D1527DD414C008FE43F /* SentrySamplingProfiler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentrySamplingProfiler.hpp; path = Sources/Sentry/include/SentrySamplingProfiler.hpp; sourceTree = SOURCE_ROOT; }; @@ -1121,10 +1123,10 @@ 03F84D1827DD414C008FE43F /* SentryCompiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCompiler.h; path = Sources/Sentry/include/SentryCompiler.h; sourceTree = SOURCE_ROOT; }; 03F84D1927DD414C008FE43F /* SentryThreadState.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentryThreadState.hpp; path = Sources/Sentry/include/SentryThreadState.hpp; sourceTree = SOURCE_ROOT; }; 03F84D1A27DD414C008FE43F /* SentryThreadMetadataCache.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentryThreadMetadataCache.hpp; path = Sources/Sentry/include/SentryThreadMetadataCache.hpp; sourceTree = SOURCE_ROOT; }; - 03F84D1B27DD414C008FE43F /* SentryMachLogging.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentryMachLogging.hpp; path = Sources/Sentry/include/SentryMachLogging.hpp; sourceTree = SOURCE_ROOT; }; + 03F84D1B27DD414C008FE43F /* SentryMachLogging.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentryMachLogging.hpp; path = Sources/Sentry/_SentryPrivate/include/SentryMachLogging.hpp; sourceTree = SOURCE_ROOT; }; 03F84D1C27DD414C008FE43F /* SentryCPU.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCPU.h; path = Sources/Sentry/include/SentryCPU.h; sourceTree = SOURCE_ROOT; }; 03F84D2B27DD4191008FE43F /* SentryProfiler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = SentryProfiler.mm; path = Sources/Sentry/SentryProfiler.mm; sourceTree = SOURCE_ROOT; }; - 03F84D2C27DD4191008FE43F /* SentryMachLogging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SentryMachLogging.cpp; path = Sources/Sentry/SentryMachLogging.cpp; sourceTree = SOURCE_ROOT; }; + 03F84D2C27DD4191008FE43F /* SentryMachLogging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SentryMachLogging.cpp; path = Sources/Sentry/_SentryPrivate/SentryMachLogging.cpp; sourceTree = SOURCE_ROOT; }; 03F84D2D27DD4191008FE43F /* SentryThreadMetadataCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SentryThreadMetadataCache.cpp; path = Sources/Sentry/SentryThreadMetadataCache.cpp; sourceTree = SOURCE_ROOT; }; 03F84D2E27DD4191008FE43F /* SentryThreadHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SentryThreadHandle.cpp; path = Sources/Sentry/SentryThreadHandle.cpp; sourceTree = SOURCE_ROOT; }; 03F84D3027DD4191008FE43F /* SentrySamplingProfiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SentrySamplingProfiler.cpp; path = Sources/Sentry/SentrySamplingProfiler.cpp; sourceTree = SOURCE_ROOT; }; @@ -1150,7 +1152,7 @@ 0A9BF4E328A114B50068D266 /* SentryViewHierarchyIntegration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryViewHierarchyIntegration.h; path = include/SentryViewHierarchyIntegration.h; sourceTree = ""; }; 0A9BF4E628A123270068D266 /* TestSentryViewHierarchy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryViewHierarchy.swift; sourceTree = ""; }; 0A9BF4EA28A127120068D266 /* SentryViewHierarchyIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryViewHierarchyIntegrationTests.swift; sourceTree = ""; }; - 0A9E917028DC7E7000FB4182 /* SentryInternalCDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryInternalCDefines.h; path = include/SentryInternalCDefines.h; sourceTree = ""; }; + 0A9E917028DC7E7000FB4182 /* SentryInternalCDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryInternalCDefines.h; path = _SentryPrivate/include/SentryInternalCDefines.h; sourceTree = ""; }; 0AAE201D28ED9B9400D0CD80 /* SentryReachability.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryReachability.m; sourceTree = ""; }; 0AAE202028ED9BCC00D0CD80 /* SentryReachability.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryReachability.h; path = include/SentryReachability.h; sourceTree = ""; }; 0ADC33EB28D9BB780078D980 /* SentryUIDeviceWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryUIDeviceWrapper.m; sourceTree = ""; }; @@ -1314,13 +1316,13 @@ 63AA75C71EB8B06100D153DE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../Resources/Info.plist; sourceTree = ""; }; 63AA75ED1EB8B3C400D153DE /* SentryClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryClient.m; sourceTree = ""; }; 63AA76651EB8CB2F00D153DE /* SentryTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SentryTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 63AA76781EB8D20500D153DE /* SentryLogC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryLogC.m; sourceTree = ""; }; + 63AA76781EB8D20500D153DE /* SentryLogC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SentryLogC.m; path = _SentryPrivate/SentryLogC.m; sourceTree = ""; }; 63AA76931EB9C1C200D153DE /* Sentry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sentry.h; path = Public/Sentry.h; sourceTree = ""; }; 63AA76941EB9C1C200D153DE /* SentryClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryClient.h; path = Public/SentryClient.h; sourceTree = ""; }; - 63AA76951EB9C1C200D153DE /* SentryDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryDefines.h; path = Public/SentryDefines.h; sourceTree = ""; }; - 63AA76961EB9C1C200D153DE /* SentryLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryLog.h; path = include/SentryLog.h; sourceTree = ""; }; - 63AA769B1EB9C57A00D153DE /* SentryError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryError.h; path = Public/SentryError.h; sourceTree = ""; }; - 63AA769C1EB9C57A00D153DE /* SentryError.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SentryError.mm; sourceTree = ""; }; + 63AA76951EB9C1C200D153DE /* SentryDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryDefines.h; path = _SentryPrivate/Public/SentryDefines.h; sourceTree = ""; }; + 63AA76961EB9C1C200D153DE /* SentryLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryLog.h; path = _SentryPrivate/include/SentryLog.h; sourceTree = ""; }; + 63AA769B1EB9C57A00D153DE /* SentryError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryError.h; path = _SentryPrivate/Public/SentryError.h; sourceTree = ""; }; + 63AA769C1EB9C57A00D153DE /* SentryError.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = SentryError.mm; path = _SentryPrivate/SentryError.mm; sourceTree = ""; }; 63AA76A11EB9CBAA00D153DE /* SentryDsn.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryDsn.m; sourceTree = ""; }; 63AA76A41EB9CBC200D153DE /* SentryDsn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryDsn.h; path = Public/SentryDsn.h; sourceTree = ""; }; 63AA76AE1EB9D5CD00D153DE /* SentryTests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SentryTests.xcconfig; sourceTree = ""; }; @@ -1360,13 +1362,13 @@ 63FE700420DA4C1000CDBAE8 /* SentryCrashCachedData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashCachedData.c; sourceTree = ""; }; 63FE700720DA4C1000CDBAE8 /* SentryCrashDate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashDate.h; sourceTree = ""; }; 63FE700820DA4C1000CDBAE8 /* SentryCrashMachineContext_Apple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMachineContext_Apple.h; sourceTree = ""; }; - 63FE700920DA4C1000CDBAE8 /* SentryAsyncSafeLog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryAsyncSafeLog.c; sourceTree = ""; }; + 63FE700920DA4C1000CDBAE8 /* SentryAsyncSafeLog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SentryAsyncSafeLog.c; path = _SentryPrivate/SentryAsyncSafeLog.c; sourceTree = ""; }; 63FE700A20DA4C1000CDBAE8 /* SentryCrashStackCursor_SelfThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashStackCursor_SelfThread.m; sourceTree = ""; }; 63FE700B20DA4C1000CDBAE8 /* SentryCrashFileUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashFileUtils.h; sourceTree = ""; }; 63FE700C20DA4C1000CDBAE8 /* SentryCrashMach.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashMach.c; sourceTree = ""; }; 63FE700D20DA4C1000CDBAE8 /* SentryCrashStackCursor_MachineContext.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashStackCursor_MachineContext.c; sourceTree = ""; }; 63FE700E20DA4C1000CDBAE8 /* SentryCrashNSErrorUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashNSErrorUtil.m; sourceTree = ""; }; - 63FE700F20DA4C1000CDBAE8 /* SentryCrashDebug.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashDebug.c; sourceTree = ""; }; + 63FE700F20DA4C1000CDBAE8 /* SentryCrashDebug.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SentryCrashDebug.c; path = ../../../Sentry/_SentryPrivate/SentryCrashDebug.c; sourceTree = ""; }; 63FE701120DA4C1000CDBAE8 /* SentryCrashJSONCodec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashJSONCodec.c; sourceTree = ""; }; 63FE701220DA4C1000CDBAE8 /* SentryCrashStackCursor_Backtrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashStackCursor_Backtrace.c; sourceTree = ""; }; 63FE701320DA4C1000CDBAE8 /* SentryCrashMachineContext.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashMachineContext.c; sourceTree = ""; }; @@ -1387,7 +1389,7 @@ 63FE702220DA4C1000CDBAE8 /* SentryCrashCPU_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashCPU_x86_64.c; sourceTree = ""; }; 63FE702320DA4C1000CDBAE8 /* SentryCrashMach.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMach.h; sourceTree = ""; }; 63FE702420DA4C1000CDBAE8 /* SentryCrashFileUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashFileUtils.c; sourceTree = ""; }; - 63FE702520DA4C1000CDBAE8 /* SentryAsyncSafeLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryAsyncSafeLog.h; sourceTree = ""; }; + 63FE702520DA4C1000CDBAE8 /* SentryAsyncSafeLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryAsyncSafeLog.h; path = _SentryPrivate/include/SentryAsyncSafeLog.h; sourceTree = ""; }; 63FE702620DA4C1000CDBAE8 /* SentryCrashStackCursor_SelfThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashStackCursor_SelfThread.h; sourceTree = ""; }; 63FE702720DA4C1000CDBAE8 /* SentryCrashDate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashDate.c; sourceTree = ""; }; 63FE702920DA4C1000CDBAE8 /* SentryCrashObjC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashObjC.c; sourceTree = ""; }; @@ -1396,7 +1398,7 @@ 63FE702C20DA4C1000CDBAE8 /* SentryCrashString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashString.h; sourceTree = ""; }; 63FE702D20DA4C1000CDBAE8 /* SentryCrashJSONCodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashJSONCodec.h; sourceTree = ""; }; 63FE702E20DA4C1000CDBAE8 /* SentryCrashNSErrorUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashNSErrorUtil.h; sourceTree = ""; }; - 63FE702F20DA4C1000CDBAE8 /* SentryCrashDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashDebug.h; sourceTree = ""; }; + 63FE702F20DA4C1000CDBAE8 /* SentryCrashDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashDebug.h; path = ../../../Sentry/_SentryPrivate/include/SentryCrashDebug.h; sourceTree = ""; }; 63FE703020DA4C1000CDBAE8 /* SentryCrashObjCApple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashObjCApple.h; sourceTree = ""; }; 63FE703120DA4C1000CDBAE8 /* SentryCrashStackCursor_MachineContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashStackCursor_MachineContext.h; sourceTree = ""; }; 63FE703220DA4C1000CDBAE8 /* SentryCrashThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashThread.h; sourceTree = ""; }; @@ -2141,7 +2143,7 @@ D8ACE3CA2762187D00F5A213 /* SentryNSDataSwizzling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryNSDataSwizzling.h; path = include/SentryNSDataSwizzling.h; sourceTree = ""; }; D8ACE3CB2762187D00F5A213 /* SentryFileIOTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryFileIOTracker.h; path = include/SentryFileIOTracker.h; sourceTree = ""; }; D8ACE3CC2762187D00F5A213 /* SentryFileIOTrackingIntegration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryFileIOTrackingIntegration.h; path = include/SentryFileIOTrackingIntegration.h; sourceTree = ""; }; - D8AE48B12C5786AA0092A2A6 /* SentryLogC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryLogC.h; path = include/SentryLogC.h; sourceTree = ""; }; + D8AE48B12C5786AA0092A2A6 /* SentryLogC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryLogC.h; path = _SentryPrivate/include/SentryLogC.h; sourceTree = ""; }; D8AE48BE2C578D540092A2A6 /* SentryLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLog.swift; sourceTree = ""; }; D8AE48C02C57B1550092A2A6 /* SentryLevelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLevelTests.swift; sourceTree = ""; }; D8AFC0002BD252B900118BE1 /* SentryOnDemandReplayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryOnDemandReplayTests.swift; sourceTree = ""; }; @@ -2154,7 +2156,7 @@ D8B665BB2B95F5A100BD0E7B /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = module.modulemap; path = Sources/Sentry/include/module.modulemap; sourceTree = SOURCE_ROOT; }; D8B76B042808060E000A58C4 /* SentryScreenshotIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryScreenshotIntegrationTests.swift; sourceTree = ""; }; D8B76B0728081461000A58C4 /* TestSentryScreenShot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryScreenShot.swift; sourceTree = ""; }; - D8BBD32628FD9FBF0011F850 /* SentrySwift.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentrySwift.h; path = include/SentrySwift.h; sourceTree = ""; }; + D8BBD32628FD9FBF0011F850 /* SentrySwift.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentrySwift.h; path = _SentryPrivate/include/SentrySwift.h; sourceTree = ""; }; D8BC28C72BFF5EBB0054DA4D /* SentryTouchTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryTouchTracker.swift; sourceTree = ""; }; D8BC28CB2BFF78220054DA4D /* SentryRRWebTouchEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryRRWebTouchEvent.swift; sourceTree = ""; }; D8BC28D42C00C6D30054DA4D /* StringExtensionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtensionsTests.swift; sourceTree = ""; }; @@ -2234,6 +2236,8 @@ FA67DCEF2DDBD4EA00896B02 /* URLSessionTaskHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionTaskHelper.swift; sourceTree = ""; }; FA67DCF12DDBD4EA00896B02 /* SentryExperimentalOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryExperimentalOptions.swift; sourceTree = ""; }; FA67DCF22DDBD4EA00896B02 /* SwiftDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftDescriptor.swift; sourceTree = ""; }; + FA922C332DDD1C710026D187 /* FileUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FileUtils.h; path = _SentryPrivate/include/FileUtils.h; sourceTree = ""; }; + FA922C352DDD1C770026D187 /* FileUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = FileUtils.m; path = _SentryPrivate/FileUtils.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -2662,6 +2666,8 @@ 63AA76961EB9C1C200D153DE /* SentryLog.h */, D8AE48B12C5786AA0092A2A6 /* SentryLogC.h */, 63AA76781EB8D20500D153DE /* SentryLogC.m */, + FA922C332DDD1C710026D187 /* FileUtils.h */, + FA922C352DDD1C770026D187 /* FileUtils.m */, 63FE700920DA4C1000CDBAE8 /* SentryAsyncSafeLog.c */, 63FE702520DA4C1000CDBAE8 /* SentryAsyncSafeLog.h */, 7BE1E33124F7E3B6009D3AD0 /* SentryMigrateSessionInit.h */, @@ -4726,6 +4732,7 @@ 63AA76A51EB9CBC200D153DE /* SentryDsn.h in Headers */, 844EDD6C2949387000C86F34 /* SentryMetricProfiler.h in Headers */, 636085131ED47BE600E8599E /* SentryFileManager.h in Headers */, + FA922C342DDD1C730026D187 /* FileUtils.h in Headers */, 7BD729962463E83300EA3610 /* SentryDateUtil.h in Headers */, 63FE707B20DA4C1000CDBAE8 /* SentryDictionaryDeepSearch.h in Headers */, 6344DDB91EC3115C00D9160D /* SentryCrashReportConverter.h in Headers */, @@ -5036,6 +5043,7 @@ D8739D142BEE5049007D2F66 /* SentryRRWebSpanEvent.swift in Sources */, 7B6C5EDE264E8DF00010D138 /* SentryFramesTracker.m in Sources */, D84F833E2A1CC401005828E0 /* SentrySwiftAsyncIntegration.m in Sources */, + FA922C362DDD1C790026D187 /* FileUtils.m in Sources */, 7B6438AB26A70F24000D0F65 /* UIViewController+Sentry.m in Sources */, 84302A812B5767A50027A629 /* SentryLaunchProfiling.m in Sources */, 63AA76A31EB9CBAA00D153DE /* SentryDsn.m in Sources */, diff --git a/SentryTestUtils/SentryLogExtensions.swift b/SentryTestUtils/SentryLogExtensions.swift index 0ccc580d05e..8234c8c5aa3 100644 --- a/SentryTestUtils/SentryLogExtensions.swift +++ b/SentryTestUtils/SentryLogExtensions.swift @@ -1,7 +1,7 @@ import Foundation -@testable import Sentry +@testable @_spi(Private) import Sentry -extension SentryLog { +public enum SentryLog { public static func setTestDefaultLogLevel() { SentryLogSwiftSupport.configure(true, diagnosticLevel: .debug) } diff --git a/Sources/Sentry/SentryFileManager.m b/Sources/Sentry/SentryFileManager.m index 2d361c17764..43cf71acee4 100644 --- a/Sources/Sentry/SentryFileManager.m +++ b/Sources/Sentry/SentryFileManager.m @@ -1,4 +1,5 @@ #import "SentryFileManager.h" +#import "FileUtils.h" #import "SentryAppState.h" #import "SentryDataCategoryMapper.h" #import "SentryDateUtils.h" @@ -22,51 +23,6 @@ #pragma mark - Helper Methods -BOOL -isErrorPathTooLong(NSError *error) -{ - NSError *underlyingError = NULL; - if (@available(macOS 11.3, iOS 14.5, watchOS 7.4, tvOS 14.5, *)) { - underlyingError = error.underlyingErrors.firstObject; - } - if (underlyingError == NULL) { - id errorInUserInfo = [error.userInfo valueForKey:NSUnderlyingErrorKey]; - if (errorInUserInfo && [errorInUserInfo isKindOfClass:[NSError class]]) { - underlyingError = errorInUserInfo; - } - } - if (underlyingError == NULL) { - underlyingError = error; - } - BOOL isEnameTooLong - = underlyingError.domain == NSPOSIXErrorDomain && underlyingError.code == ENAMETOOLONG; - // On older OS versions the error code is NSFileWriteUnknown - // Reference: https://developer.apple.com/forums/thread/128927?answerId=631839022#631839022 - BOOL isUnknownError = underlyingError.domain == NSCocoaErrorDomain - && underlyingError.code == NSFileWriteUnknownError; - - return isEnameTooLong || isUnknownError; -} - -BOOL -createDirectoryIfNotExists(NSString *path, NSError **error) -{ - BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:path - withIntermediateDirectories:YES - attributes:nil - error:error]; - if (success) { - return YES; - } - - if (isErrorPathTooLong(*error)) { - SENTRY_LOG_FATAL(@"Failed to create directory, path is too long: %@", path); - } - *error = NSErrorFromSentryErrorWithUnderlyingError(kSentryErrorFileIO, - [NSString stringWithFormat:@"Failed to create the directory at path %@.", path], *error); - return NO; -} - /** * @warning This is called from a `@synchronized` context in instance methods, but doesn't require * that when calling from other static functions. Make sure you pay attention to where this is used @@ -634,116 +590,6 @@ - (BOOL)isDirectory:(NSString *)path return [NSFileManager.defaultManager fileExistsAtPath:path isDirectory:&isDir] && isDir; } -/** - * @note This method must be statically accessible because it will be called during app launch, - * before any instance of ``SentryFileManager`` exists, and so wouldn't be able to access this path - * from an objc property on it like the other paths. - */ -NSString *_Nullable sentryStaticCachesPath(void) -{ - static NSString *_Nullable sentryStaticCachesPath = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - // We request the users cache directory from Foundation. - // For iOS apps and macOS apps with sandboxing, this path will be scoped for the current - // app. For macOS apps without sandboxing, this path is not scoped and will be shared - // between all apps. - NSString *_Nullable cachesDirectory - = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) - .firstObject; - if (cachesDirectory == nil) { - SENTRY_LOG_WARN(@"No caches directory location reported."); - return; - } - - // We need to ensure our own scoped directory so that this path is not shared between other - // apps on the same system. - NSString *_Nullable scopedCachesDirectory = sentryGetScopedCachesDirectory(cachesDirectory); - if (!scopedCachesDirectory) { - SENTRY_LOG_WARN(@"Failed to get scoped static caches directory."); - return; - } - sentryStaticCachesPath = scopedCachesDirectory; - SENTRY_LOG_DEBUG(@"Using static cache directory: %@", sentryStaticCachesPath); - }); - return sentryStaticCachesPath; -} - -NSString *_Nullable sentryGetScopedCachesDirectory(NSString *cachesDirectory) -{ -#if !TARGET_OS_OSX - // iOS apps are always sandboxed, therefore we can just early-return with the provided caches - // directory. - return cachesDirectory; -#else - - // For macOS apps, we need to ensure our own sandbox so that this path is not shared between - // all apps that ship the SDK. - - // We can not use the SentryNSProcessInfoWrapper here because this method is called before - // the SentryDependencyContainer is initialized. - NSProcessInfo *processInfo = [NSProcessInfo processInfo]; - - // Only apps running in a sandboxed environment have the `APP_SANDBOX_CONTAINER_ID` set as a - // process environment variable. Reference implementation: - // https://github.com/realm/realm-js/blob/a03127726939f08f608edbdb2341605938f25708/packages/realm/binding/apple/platform.mm#L58-L74 - BOOL isSandboxed = processInfo.environment[@"APP_SANDBOX_CONTAINER_ID"] != nil; - - // The bundle identifier is used to create a unique cache directory for the app. - // If the bundle identifier is not available, we use the name of the executable. - // Note: `SentryCrash.getBundleName` is using `CFBundleName` to create a scoped directory. - // That value can be absent, therefore we use a more stable approach here. - NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; - NSString *lastPathComponent = [[[NSBundle mainBundle] executablePath] lastPathComponent]; - - // Due to `NSProcessInfo` and `NSBundle` not being mockable in unit tests, we extract only the - // logic to a separate function. - return sentryBuildScopedCachesDirectoryPath( - cachesDirectory, isSandboxed, bundleIdentifier, lastPathComponent); -#endif -} - -NSString *_Nullable sentryBuildScopedCachesDirectoryPath(NSString *cachesDirectory, - BOOL isSandboxed, NSString *_Nullable bundleIdentifier, NSString *_Nullable lastPathComponent) -{ - // If the app is sandboxed, we can just use the provided caches directory. - if (isSandboxed) { - return cachesDirectory; - } - - // If the macOS app is not sandboxed, we need to manually create a scoped cache - // directory. The cache path must be unique an stable over app launches, therefore we - // can not use any changing identifier. - SENTRY_LOG_DEBUG( - @"App is not sandboxed, extending default cache directory with bundle identifier."); - NSString *_Nullable identifier = bundleIdentifier; - if (identifier == nil) { - SENTRY_LOG_WARN(@"No bundle identifier found, using main bundle executable name."); - identifier = lastPathComponent; - } else if (identifier.length == 0) { - SENTRY_LOG_WARN(@"Bundle identifier exists but is zero length, using main bundle " - @"executable name."); - identifier = lastPathComponent; - } - - // If neither the bundle identifier nor the executable name are available, we can't - // create a unique and stable cache directory. - // We do not fall back to any default path, because it could be shared with other apps - // and cause leaks impacting other apps. - if (identifier == nil) { - SENTRY_LOG_ERROR(@"No bundle identifier found, cannot create cache directory."); - return nil; - } - - // It's unlikely that the executable name will be zero length, but we'll cover this case anyways - if (identifier.length == 0) { - SENTRY_LOG_ERROR(@"Executable name was zero length."); - return nil; - } - - return [cachesDirectory stringByAppendingPathComponent:identifier]; -} - NSString *_Nullable sentryStaticBasePath(void) { static NSString *_Nullable sentryStaticBasePath = nil; diff --git a/Sources/Sentry/_SentryPrivate/FileUtils.m b/Sources/Sentry/_SentryPrivate/FileUtils.m new file mode 100644 index 00000000000..f00b114a63e --- /dev/null +++ b/Sources/Sentry/_SentryPrivate/FileUtils.m @@ -0,0 +1,158 @@ +#import "FileUtils.h" +#import "SentryError.h" +#import "SentryLog.h" + +BOOL +isErrorPathTooLong(NSError *error) +{ + NSError *underlyingError = NULL; + if (@available(macOS 11.3, iOS 14.5, watchOS 7.4, tvOS 14.5, *)) { + underlyingError = error.underlyingErrors.firstObject; + } + if (underlyingError == NULL) { + id errorInUserInfo = [error.userInfo valueForKey:NSUnderlyingErrorKey]; + if (errorInUserInfo && [errorInUserInfo isKindOfClass:[NSError class]]) { + underlyingError = errorInUserInfo; + } + } + if (underlyingError == NULL) { + underlyingError = error; + } + BOOL isEnameTooLong + = underlyingError.domain == NSPOSIXErrorDomain && underlyingError.code == ENAMETOOLONG; + // On older OS versions the error code is NSFileWriteUnknown + // Reference: https://developer.apple.com/forums/thread/128927?answerId=631839022#631839022 + BOOL isUnknownError = underlyingError.domain == NSCocoaErrorDomain + && underlyingError.code == NSFileWriteUnknownError; + + return isEnameTooLong || isUnknownError; +} + +BOOL +createDirectoryIfNotExists(NSString *path, NSError **error) +{ + BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:nil + error:error]; + if (success) { + return YES; + } + + if (isErrorPathTooLong(*error)) { + SENTRY_LOG_FATAL(@"Failed to create directory, path is too long: %@", path); + } + *error = NSErrorFromSentryErrorWithUnderlyingError(kSentryErrorFileIO, + [NSString stringWithFormat:@"Failed to create the directory at path %@.", path], *error); + return NO; +} + +NSString *_Nullable sentryBuildScopedCachesDirectoryPath(NSString *cachesDirectory, + BOOL isSandboxed, NSString *_Nullable bundleIdentifier, NSString *_Nullable lastPathComponent) +{ + // If the app is sandboxed, we can just use the provided caches directory. + if (isSandboxed) { + return cachesDirectory; + } + + // If the macOS app is not sandboxed, we need to manually create a scoped cache + // directory. The cache path must be unique an stable over app launches, therefore we + // can not use any changing identifier. + SENTRY_LOG_DEBUG( + @"App is not sandboxed, extending default cache directory with bundle identifier."); + NSString *_Nullable identifier = bundleIdentifier; + if (identifier == nil) { + SENTRY_LOG_WARN(@"No bundle identifier found, using main bundle executable name."); + identifier = lastPathComponent; + } else if (identifier.length == 0) { + SENTRY_LOG_WARN(@"Bundle identifier exists but is zero length, using main bundle " + @"executable name."); + identifier = lastPathComponent; + } + + // If neither the bundle identifier nor the executable name are available, we can't + // create a unique and stable cache directory. + // We do not fall back to any default path, because it could be shared with other apps + // and cause leaks impacting other apps. + if (identifier == nil) { + SENTRY_LOG_ERROR(@"No bundle identifier found, cannot create cache directory."); + return nil; + } + + // It's unlikely that the executable name will be zero length, but we'll cover this case anyways + if (identifier.length == 0) { + SENTRY_LOG_ERROR(@"Executable name was zero length."); + return nil; + } + + return [cachesDirectory stringByAppendingPathComponent:identifier]; +} + +NSString *_Nullable sentryGetScopedCachesDirectory(NSString *cachesDirectory) +{ +#if !TARGET_OS_OSX + // iOS apps are always sandboxed, therefore we can just early-return with the provided caches + // directory. + return cachesDirectory; +#else + + // For macOS apps, we need to ensure our own sandbox so that this path is not shared between + // all apps that ship the SDK. + + // We can not use the SentryNSProcessInfoWrapper here because this method is called before + // the SentryDependencyContainer is initialized. + NSProcessInfo *processInfo = [NSProcessInfo processInfo]; + + // Only apps running in a sandboxed environment have the `APP_SANDBOX_CONTAINER_ID` set as a + // process environment variable. Reference implementation: + // https://github.com/realm/realm-js/blob/a03127726939f08f608edbdb2341605938f25708/packages/realm/binding/apple/platform.mm#L58-L74 + BOOL isSandboxed = processInfo.environment[@"APP_SANDBOX_CONTAINER_ID"] != nil; + + // The bundle identifier is used to create a unique cache directory for the app. + // If the bundle identifier is not available, we use the name of the executable. + // Note: `SentryCrash.getBundleName` is using `CFBundleName` to create a scoped directory. + // That value can be absent, therefore we use a more stable approach here. + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + NSString *lastPathComponent = [[[NSBundle mainBundle] executablePath] lastPathComponent]; + + // Due to `NSProcessInfo` and `NSBundle` not being mockable in unit tests, we extract only the + // logic to a separate function. + return sentryBuildScopedCachesDirectoryPath( + cachesDirectory, isSandboxed, bundleIdentifier, lastPathComponent); +#endif +} + +/** + * @note This method must be statically accessible because it will be called during app launch, + * before any instance of ``SentryFileManager`` exists, and so wouldn't be able to access this path + * from an objc property on it like the other paths. + */ +NSString *_Nullable sentryStaticCachesPath(void) +{ + static NSString *_Nullable sentryStaticCachesPath = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // We request the users cache directory from Foundation. + // For iOS apps and macOS apps with sandboxing, this path will be scoped for the current + // app. For macOS apps without sandboxing, this path is not scoped and will be shared + // between all apps. + NSString *_Nullable cachesDirectory + = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) + .firstObject; + if (cachesDirectory == nil) { + SENTRY_LOG_WARN(@"No caches directory location reported."); + return; + } + + // We need to ensure our own scoped directory so that this path is not shared between other + // apps on the same system. + NSString *_Nullable scopedCachesDirectory = sentryGetScopedCachesDirectory(cachesDirectory); + if (!scopedCachesDirectory) { + SENTRY_LOG_WARN(@"Failed to get scoped static caches directory."); + return; + } + sentryStaticCachesPath = scopedCachesDirectory; + SENTRY_LOG_DEBUG(@"Using static cache directory: %@", sentryStaticCachesPath); + }); + return sentryStaticCachesPath; +} diff --git a/Sources/Sentry/Public/SentryDefines.h b/Sources/Sentry/_SentryPrivate/Public/SentryDefines.h similarity index 100% rename from Sources/Sentry/Public/SentryDefines.h rename to Sources/Sentry/_SentryPrivate/Public/SentryDefines.h diff --git a/Sources/Sentry/Public/SentryError.h b/Sources/Sentry/_SentryPrivate/Public/SentryError.h similarity index 93% rename from Sources/Sentry/Public/SentryError.h rename to Sources/Sentry/_SentryPrivate/Public/SentryError.h index b9cc4877db0..ce8d325dace 100644 --- a/Sources/Sentry/Public/SentryError.h +++ b/Sources/Sentry/_SentryPrivate/Public/SentryError.h @@ -1,7 +1,9 @@ #if __has_include() # import -#else +#elif __has_include() # import +#else +# import #endif NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/Sentry/Public/SentryProfilingConditionals.h b/Sources/Sentry/_SentryPrivate/Public/SentryProfilingConditionals.h similarity index 100% rename from Sources/Sentry/Public/SentryProfilingConditionals.h rename to Sources/Sentry/_SentryPrivate/Public/SentryProfilingConditionals.h diff --git a/Sources/Sentry/SentryAsyncSafeLog.c b/Sources/Sentry/_SentryPrivate/SentryAsyncSafeLog.c similarity index 100% rename from Sources/Sentry/SentryAsyncSafeLog.c rename to Sources/Sentry/_SentryPrivate/SentryAsyncSafeLog.c diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashDebug.c b/Sources/Sentry/_SentryPrivate/SentryCrashDebug.c similarity index 100% rename from Sources/SentryCrash/Recording/Tools/SentryCrashDebug.c rename to Sources/Sentry/_SentryPrivate/SentryCrashDebug.c diff --git a/Sources/Sentry/SentryError.mm b/Sources/Sentry/_SentryPrivate/SentryError.mm similarity index 100% rename from Sources/Sentry/SentryError.mm rename to Sources/Sentry/_SentryPrivate/SentryError.mm diff --git a/Sources/Sentry/SentryLogC.m b/Sources/Sentry/_SentryPrivate/SentryLogC.m similarity index 97% rename from Sources/Sentry/SentryLogC.m rename to Sources/Sentry/_SentryPrivate/SentryLogC.m index 88f7e825add..0eaf0184e17 100644 --- a/Sources/Sentry/SentryLogC.m +++ b/Sources/Sentry/_SentryPrivate/SentryLogC.m @@ -1,8 +1,7 @@ #import "SentryLogC.h" +#import "FileUtils.h" #import "SentryAsyncSafeLog.h" -#import "SentryFileManager.h" #import "SentryInternalCDefines.h" -#import "SentryLevelMapper.h" #import "SentryLog.h" #import "SentrySwift.h" diff --git a/Sources/Sentry/SentryMachLogging.cpp b/Sources/Sentry/_SentryPrivate/SentryMachLogging.cpp similarity index 100% rename from Sources/Sentry/SentryMachLogging.cpp rename to Sources/Sentry/_SentryPrivate/SentryMachLogging.cpp diff --git a/Sources/Sentry/_SentryPrivate/include/FileUtils.h b/Sources/Sentry/_SentryPrivate/include/FileUtils.h new file mode 100644 index 00000000000..8b249dbb3e3 --- /dev/null +++ b/Sources/Sentry/_SentryPrivate/include/FileUtils.h @@ -0,0 +1,21 @@ +#import "SentryDefines.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +BOOL createDirectoryIfNotExists(NSString *path, NSError **error); + +BOOL isErrorPathTooLong(NSError *error); + +/** + * Path for a default directory Sentry can use in the app sandbox' caches directory. + * @note This method must be statically accessible because it will be called during app launch, + * before any instance of @c SentryFileManager exists, and so wouldn't be able to access this path. + * @note For unsandboxed macOS apps, the path has the form @c ~/Library/Caches/ . + * from an objc property on it like the other paths. It also cannot use + * @c SentryOptions.cacheDirectoryPath since this can be called before + * @c SentrySDK.startWithOptions . + */ +SENTRY_EXTERN NSString *_Nullable sentryStaticCachesPath(void); + +NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryAsyncSafeLog.h b/Sources/Sentry/_SentryPrivate/include/SentryAsyncSafeLog.h similarity index 100% rename from Sources/Sentry/SentryAsyncSafeLog.h rename to Sources/Sentry/_SentryPrivate/include/SentryAsyncSafeLog.h diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashDebug.h b/Sources/Sentry/_SentryPrivate/include/SentryCrashDebug.h similarity index 100% rename from Sources/SentryCrash/Recording/Tools/SentryCrashDebug.h rename to Sources/Sentry/_SentryPrivate/include/SentryCrashDebug.h diff --git a/Sources/Sentry/include/SentryInternalCDefines.h b/Sources/Sentry/_SentryPrivate/include/SentryInternalCDefines.h similarity index 100% rename from Sources/Sentry/include/SentryInternalCDefines.h rename to Sources/Sentry/_SentryPrivate/include/SentryInternalCDefines.h diff --git a/Sources/Sentry/include/SentryLog.h b/Sources/Sentry/_SentryPrivate/include/SentryLog.h similarity index 100% rename from Sources/Sentry/include/SentryLog.h rename to Sources/Sentry/_SentryPrivate/include/SentryLog.h diff --git a/Sources/Sentry/include/SentryLogC.h b/Sources/Sentry/_SentryPrivate/include/SentryLogC.h similarity index 100% rename from Sources/Sentry/include/SentryLogC.h rename to Sources/Sentry/_SentryPrivate/include/SentryLogC.h diff --git a/Sources/Sentry/include/SentryMachLogging.hpp b/Sources/Sentry/_SentryPrivate/include/SentryMachLogging.hpp similarity index 100% rename from Sources/Sentry/include/SentryMachLogging.hpp rename to Sources/Sentry/_SentryPrivate/include/SentryMachLogging.hpp diff --git a/Sources/Sentry/include/SentrySwift.h b/Sources/Sentry/_SentryPrivate/include/SentrySwift.h similarity index 94% rename from Sources/Sentry/include/SentrySwift.h rename to Sources/Sentry/_SentryPrivate/include/SentrySwift.h index db405b418b0..43c2013f33d 100644 --- a/Sources/Sentry/include/SentrySwift.h +++ b/Sources/Sentry/_SentryPrivate/include/SentrySwift.h @@ -31,8 +31,10 @@ # if __has_include("Sentry-Swift.h") # import "Sentry-Swift.h" -# else +# elif __has_include() # import +# else +@import SentryCoreSwift; # endif #endif // __has_include() diff --git a/Sources/Sentry/include/SentryFileManager.h b/Sources/Sentry/include/SentryFileManager.h index 0180fcededd..5c7fdc932c9 100644 --- a/Sources/Sentry/include/SentryFileManager.h +++ b/Sources/Sentry/include/SentryFileManager.h @@ -115,19 +115,6 @@ SENTRY_NO_INIT - (NSArray *)allFilesInFolder:(NSString *)path; - (BOOL)isDirectory:(NSString *)path; -BOOL createDirectoryIfNotExists(NSString *path, NSError **error); - -/** - * Path for a default directory Sentry can use in the app sandbox' caches directory. - * @note This method must be statically accessible because it will be called during app launch, - * before any instance of @c SentryFileManager exists, and so wouldn't be able to access this path. - * @note For unsandboxed macOS apps, the path has the form @c ~/Library/Caches/ . - * from an objc property on it like the other paths. It also cannot use - * @c SentryOptions.cacheDirectoryPath since this can be called before - * @c SentrySDK.startWithOptions . - */ -SENTRY_EXTERN NSString *_Nullable sentryStaticCachesPath(void); - #pragma mark - Profiling #if SENTRY_TARGET_PROFILING_SUPPORTED diff --git a/Sources/Swift/Core/Tools/SentryLog.swift b/Sources/Swift/Core/Tools/SentryLog.swift index 6cbb9118db2..eec35ab5b71 100644 --- a/Sources/Swift/Core/Tools/SentryLog.swift +++ b/Sources/Swift/Core/Tools/SentryLog.swift @@ -1,7 +1,7 @@ import Foundation @objc -class SentryLog: NSObject { +@_spi(Private) public class SentryLog: NSObject { static private(set) var isDebug = true static private(set) var diagnosticLevel = SentryLevel.error @@ -22,7 +22,7 @@ class SentryLog: NSObject { } @objc - static func log(message: String, andLevel level: SentryLevel) { + @_spi(Private) public static func log(message: String, andLevel level: SentryLevel) { guard willLog(atLevel: level) else { return } // We use the timeIntervalSinceReferenceDate because date format is @@ -38,7 +38,7 @@ class SentryLog: NSObject { * @c NO if not. */ @objc - static func willLog(atLevel level: SentryLevel) -> Bool { + @_spi(Private) public static func willLog(atLevel level: SentryLevel) -> Bool { if level == .none { return false } diff --git a/Tests/SentryTests/Helper/SentryLog.swift b/Tests/SentryTests/Helper/SentryLog.swift index 6b49aa9ca06..21247efa8c4 100644 --- a/Tests/SentryTests/Helper/SentryLog.swift +++ b/Tests/SentryTests/Helper/SentryLog.swift @@ -1,4 +1,4 @@ -@testable import Sentry +@testable @_spi(Private) import Sentry typealias SentryLog = Sentry.SentryLog diff --git a/Tests/SentryTests/Helper/SentryLogTests.swift b/Tests/SentryTests/Helper/SentryLogTests.swift index d8f0a1c9d45..ecbb4273cf0 100644 --- a/Tests/SentryTests/Helper/SentryLogTests.swift +++ b/Tests/SentryTests/Helper/SentryLogTests.swift @@ -1,4 +1,4 @@ -@testable import Sentry +@testable @_spi(Private) import Sentry import SentryTestUtils import XCTest diff --git a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1Tests.swift b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1Tests.swift index 765ffbe2c53..62124b35a3b 100644 --- a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1Tests.swift +++ b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1Tests.swift @@ -128,7 +128,7 @@ class SentryANRTrackerV1Tests: XCTestCase, SentryANRTrackerDelegate { wait(for: [anrDetectedExpectation, anrStoppedExpectation], timeout: waitTimeout) - SentryLog.setTestDefaultLogLevel() + SentryTestUtils.SentryLog.setTestDefaultLogLevel() } func testRemoveListener_StopsReportingANRs() { diff --git a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV2Tests.swift b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV2Tests.swift index e67c9f954e3..bfe29d90331 100644 --- a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV2Tests.swift +++ b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV2Tests.swift @@ -310,7 +310,7 @@ class SentryANRTrackerV2Tests: XCTestCase { // This would print thousands of logs so we execute it without // to avoid spamming the test logs. - SentryLog.withoutLogs { + SentryTestUtils.SentryLog.withoutLogs { wait(for: [firstListener.anrDetectedExpectation, firstListener.anrStoppedExpectation, thirdListener.anrStoppedExpectation, thirdListener.anrDetectedExpectation], timeout: waitTimeout) } @@ -366,7 +366,7 @@ class SentryANRTrackerV2Tests: XCTestCase { // This would print thousands of logs so we execute it without // to avoid spamming the test logs. - SentryLog.withoutLogs { + SentryTestUtils.SentryLog.withoutLogs { wait(for: [listener.anrDetectedExpectation, listener.anrStoppedExpectation], timeout: waitTimeout) } } @@ -391,7 +391,7 @@ class SentryANRTrackerV2Tests: XCTestCase { // This would print thousands of logs so we execute it without // to avoid spamming the test logs. - SentryLog.withoutLogs { + SentryTestUtils.SentryLog.withoutLogs { wait(for: [listener.anrDetectedExpectation, listener.anrStoppedExpectation], timeout: waitTimeout) } } @@ -515,7 +515,7 @@ class SentryANRTrackerV2Tests: XCTestCase { // This would print thousands of logs so we execute it without // to avoid spamming the test logs. - SentryLog.withoutLogs { + SentryTestUtils.SentryLog.withoutLogs { wait(for: [listener.anrDetectedExpectation, listener.anrStoppedExpectation], timeout: waitTimeout) } } diff --git a/Tests/SentryTests/Integrations/Feedback/SentryFeedbackTests.swift b/Tests/SentryTests/Integrations/Feedback/SentryFeedbackTests.swift index 35b232f3012..6ecd5b2ef96 100644 --- a/Tests/SentryTests/Integrations/Feedback/SentryFeedbackTests.swift +++ b/Tests/SentryTests/Integrations/Feedback/SentryFeedbackTests.swift @@ -1,6 +1,7 @@ import Foundation #if os(iOS) && !SENTRY_NO_UIKIT @testable import Sentry +import SentryTestUtils import XCTest class SentryFeedbackTests: XCTestCase { @@ -178,7 +179,7 @@ class SentryFeedbackTests: XCTestCase { func testCaseDescription() -> String { "(config: (requiresName: \(input.config.requiresName), requiresEmail: \(input.config.requiresEmail), nameInput: \(input.config.nameInput == nil ? "nil" : "\"\(input.config.nameInput!)\""), emailInput: \(input.config.emailInput == nil ? "nil" : "\"\(input.config.emailInput!)\""), messageInput: \(input.config.messageInput == nil ? "nil" : "\"\(input.config.messageInput!)\""), includeScreenshot: \(input.config.includeScreenshot)), expectedSubmitButtonAccessibilityHint: \(input.expectedSubmitButtonAccessibilityHint)" } - SentryLog.withoutLogs { + SentryTestUtils.SentryLog.withoutLogs { switch viewModel.validate() { case .success(let hint): XCTAssert(input.shouldValidate) diff --git a/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationObjCTests.m b/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationObjCTests.m index 3514d21af68..e22df76514a 100644 --- a/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationObjCTests.m +++ b/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationObjCTests.m @@ -4,9 +4,9 @@ #import "SentrySDK.h" #import "SentrySpan.h" #import "SentrySpanOperation.h" +#import "SentrySwift.h" #import "SentrySwizzle.h" #import "SentryTracer.h" -#import #import @interface SentryFileIOTrackingIntegrationObjCTests : XCTestCase diff --git a/Tests/SentryTests/Integrations/Performance/IO/SentryNSFileManagerSwizzlingTests.m b/Tests/SentryTests/Integrations/Performance/IO/SentryNSFileManagerSwizzlingTests.m index 57091e3d981..adf8e3f4c36 100644 --- a/Tests/SentryTests/Integrations/Performance/IO/SentryNSFileManagerSwizzlingTests.m +++ b/Tests/SentryTests/Integrations/Performance/IO/SentryNSFileManagerSwizzlingTests.m @@ -5,10 +5,10 @@ #import "SentrySDK.h" #import "SentrySpan.h" #import "SentrySpanOperation.h" +#import "SentrySwift.h" #import "SentrySwizzle.h" #import "SentryThreadInspector.h" #import "SentryTracer.h" -#import #import @interface SentryNSFileManagerSwizzlingTests : XCTestCase diff --git a/Tests/SentryTests/Integrations/Performance/SentryPerformanceTrackerTests.swift b/Tests/SentryTests/Integrations/Performance/SentryPerformanceTrackerTests.swift index b1853bac97c..157f36dc5b0 100644 --- a/Tests/SentryTests/Integrations/Performance/SentryPerformanceTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Performance/SentryPerformanceTrackerTests.swift @@ -1,3 +1,4 @@ +@_spi(Private) import Sentry import SentryTestUtils import XCTest @@ -308,7 +309,7 @@ class SentryPerformanceTrackerTests: XCTestCase { sut.finishSpan(span.key) } - SentryLog.setTestDefaultLogLevel() + SentryTestUtils.SentryLog.setTestDefaultLogLevel() } func testStackAsync() { diff --git a/Tests/SentryTests/Integrations/SentryBaseIntegrationTests.swift b/Tests/SentryTests/Integrations/SentryBaseIntegrationTests.swift index 5ae51c7b07f..47075b2d4c6 100644 --- a/Tests/SentryTests/Integrations/SentryBaseIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/SentryBaseIntegrationTests.swift @@ -1,4 +1,4 @@ -@testable import Sentry +@testable @_spi(Private) import Sentry import XCTest class MyTestIntegration: SentryBaseIntegration { diff --git a/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsObjcTests.m b/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsObjcTests.m index 5c606b38ab3..66f0fb18d07 100644 --- a/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsObjcTests.m +++ b/Tests/SentryTests/Integrations/SessionReplay/SentryReplayOptionsObjcTests.m @@ -1,5 +1,5 @@ #import "SentryOptions+Private.h" -#import +#import "SentrySwift.h" #import @interface SentryReplayOptionsObjcTests : XCTestCase diff --git a/Tests/SentryTests/Networking/SentryHttpTransportTests.swift b/Tests/SentryTests/Networking/SentryHttpTransportTests.swift index e9513699d2c..c628dc18c40 100644 --- a/Tests/SentryTests/Networking/SentryHttpTransportTests.swift +++ b/Tests/SentryTests/Networking/SentryHttpTransportTests.swift @@ -832,7 +832,7 @@ class SentryHttpTransportTests: XCTestCase { givenCachedEvents(amount: 30) fixture.requestManager.responseDelay = fixture.flushTimeout + 0.2 - SentryLog.withoutLogs { + SentryTestUtils.SentryLog.withoutLogs { let beforeFlush = SentryDefaultCurrentDateProvider.getAbsoluteTime() let result = sut.flush(fixture.flushTimeout) let blockingDuration = getDurationNs(beforeFlush, SentryDefaultCurrentDateProvider.getAbsoluteTime()).toTimeInterval() @@ -847,7 +847,7 @@ class SentryHttpTransportTests: XCTestCase { func testFlush_BlocksCallingThread_FinishesFlushingWhenSent() { givenCachedEvents(amount: 1) - SentryLog.withoutLogs { + SentryTestUtils.SentryLog.withoutLogs { let beforeFlush = SentryDefaultCurrentDateProvider.getAbsoluteTime() XCTAssertEqual(.success, sut.flush(fixture.flushTimeout), "Flush should not time out.") @@ -860,7 +860,7 @@ class SentryHttpTransportTests: XCTestCase { func testFlush_CalledSequentially_BlocksTwice() { givenCachedEvents() - SentryLog.withoutLogs { + SentryTestUtils.SentryLog.withoutLogs { let beforeFlush = SentryDefaultCurrentDateProvider.getAbsoluteTime() XCTAssertEqual(.success, sut.flush(fixture.flushTimeout), "Flush should not time out.") @@ -878,7 +878,7 @@ class SentryHttpTransportTests: XCTestCase { var blockingDurationSum: TimeInterval = 0.0 let flushInvocations = 100 - SentryLog.withoutLogs { + SentryTestUtils.SentryLog.withoutLogs { for _ in 0.. Void, readWork: @escaping () -> Void = {}) { // To not spam the test logs - SentryLog.configureLog(true, diagnosticLevel: .error) + Sentry.SentryLog.configureLog(true, diagnosticLevel: .error) let queue = DispatchQueue(label: "testConcurrentModifications", qos: .userInteractive, attributes: [.concurrent, .initiallyInactive]) let group = DispatchGroup() @@ -25,5 +26,5 @@ func testConcurrentModifications(asyncWorkItems: Int = 5, writeLoopCount: Int = queue.activate() group.waitWithTimeout(timeout: 500) - SentryLog.setTestDefaultLogLevel() + SentryTestUtils.SentryLog.setTestDefaultLogLevel() } diff --git a/Tests/SentryTests/Transaction/SentryTracerTests.swift b/Tests/SentryTests/Transaction/SentryTracerTests.swift index 6ebf46b62eb..137efbefa85 100644 --- a/Tests/SentryTests/Transaction/SentryTracerTests.swift +++ b/Tests/SentryTests/Transaction/SentryTracerTests.swift @@ -204,7 +204,7 @@ class SentryTracerTests: XCTestCase { /// to a crash when spans keep finishing while finishInternal is executed because /// shouldIgnoreWaitForChildrenCallback could be then nil in hasUnfinishedChildSpansToWaitFor. func testFinish_ShouldIgnoreWaitForChildrenCallback_DoesNotCrash() throws { - SentryLog.withoutLogs { + SentryTestUtils.SentryLog.withoutLogs { for _ in 0..<5 { let sut = fixture.getSut() @@ -1141,7 +1141,7 @@ class SentryTracerTests: XCTestCase { } func testFinishAsync() throws { - try SentryLog.withoutLogs { + try SentryTestUtils.SentryLog.withoutLogs { let sut = fixture.getSut() let child = sut.startChild(operation: fixture.transactionOperation) sut.finish() @@ -1212,7 +1212,7 @@ class SentryTracerTests: XCTestCase { #endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) func testAddingSpansOnDifferentThread_WhileFinishing_DoesNotCrash() throws { - try SentryLog.withoutLogs { + try SentryTestUtils.SentryLog.withoutLogs { let sut = fixture.getSut(waitForChildren: false)