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

feat: prep for Linux, Windows, and Android support #1

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
68 changes: 68 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,71 @@ jobs:
if [ "`ls -A | grep -i \\.xcworkspace\$`" ]; then filetype_parameter="workspace" && file_to_build="`ls -A | grep -i \\.xcworkspace\$`"; else filetype_parameter="project" && file_to_build="`ls -A | grep -i \\.xcodeproj\$`"; fi
file_to_build=`echo $file_to_build | awk '{$1=$1;print}'`
xcodebuild test -scheme "$scheme" -"$filetype_parameter" "$file_to_build" -destination "platform=iOS Simulator,name=iPhone 13 Pro,OS=15.2"
- name: Prepare codecov
uses: sersoft-gmbh/swift-coverage-action@v2
id: coverage-files
with:
format: lcov
search-paths: ./DerivedData
env:
DEVELOPER_DIR: ${{ env.CI_XCODE_13 }}
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v2
with:
files: ${{join(fromJSON(steps.coverage-files.outputs.files), ',')}}
env_vars: IOS

# spm-test:
# runs-on: macos-latest
# steps:
# - uses: maxim-lobanov/setup-xcode@v1
# with:
# xcode-version: latest-stable
# - name: Checkout
# uses: actions/checkout@v2
# - name: Build and Test
# run: swift test --enable-code-coverage -v
# - name: Prepare codecov
# uses: sersoft-gmbh/swift-coverage-action@v2
# id: coverage-files
# with:
# format: lcov
# search-paths: ./.build
# - name: Upload coverage to Codecov
# uses: codecov/codecov-action@v2
# with:
# files: ${{join(fromJSON(steps.coverage-files.outputs.files), ',')}}
# env_vars: SPM

# linux:
# runs-on: ubuntu-18.04
# steps:
# - uses: actions/checkout@v2
# - uses: sersoft-gmbh/SwiftyActions@v1
# with:
# release-version: "5"
# github-token: ${{ secrets.GITHUB_TOKEN }}
# - name: Build and Test
# run: swift test --enable-test-discovery --enable-code-coverage -v
# - name: Prepare codecov
# run: |
# llvm-cov export -format="lcov" .build/x86_64-unknown-linux-gnu/debug/PapyrusPackageTests.xctest -instr-profile .build/x86_64-unknown-linux-gnu/debug/codecov/default.profdata > info_linux.lcov
# - name: Upload coverage to Codecov
# uses: codecov/codecov-action@v2
# with:
# env_vars: LINUX
# fail_ci_if_error: true

# windows:
# runs-on: windows-2019
# steps:
# - uses: actions/checkout@v2
# - uses: MaxDesiatov/swift-windows-action@v1
# with:
# swift-version: "5.5.1"
# shell-action: swift test --enable-test-discovery --enable-code-coverage -v
# - name: Upload coverage to Codecov
# uses: codecov/codecov-action@v2
# with:
# env_vars: WINDOWS

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
xcuserdata
profile
*.moved-aside
.swiftpm
DerivedData
.idea/
*.hmap
Expand Down
11 changes: 7 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.3
// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
Expand All @@ -7,8 +7,10 @@ import PackageDescription
let package = Package(
name: "Papyrus",
platforms: [
.iOS("15.0"),
.macOS("12.0")
.iOS(.v15),
.macOS(.v12),
.tvOS(.v15),
.watchOS(.v8)
],
products: [
.library(
Expand All @@ -24,7 +26,8 @@ let package = Package(
.testTarget(
name: "PapyrusTests",
dependencies: ["Papyrus"],
path: "PapyrusTests"
path: "PapyrusTests",
exclude: ["Supporting Files/Info.plist"]
)
]
)
3 changes: 3 additions & 0 deletions Papyrus/Source/Logger.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#if !os(Linux) && !os(Android) && !os(Windows)

import Foundation
import os.log

Expand Down Expand Up @@ -75,3 +77,4 @@ public enum LogLevel: Int {
extension LogLevel: Comparable {
public static func <(lhs: LogLevel, rhs: LogLevel) -> Bool { lhs.rawValue < rhs.rawValue }
}
#endif
31 changes: 27 additions & 4 deletions Papyrus/Source/PapyrusStore.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#if canImport(Combine)
import Combine
#endif
import Foundation


Expand All @@ -7,18 +9,23 @@ import Foundation
/// `PapyrusStore` aims to hit the sweet spot between saving raw API responses to the file system
/// and a fully fledged database like Realm.
public final class PapyrusStore {

#if !os(Linux) && !os(Android) && !os(Windows)
/// The verboseness of the logger.
public var logLevel: LogLevel {
get { self.logger.logLevel }
set { self.logger.logLevel = newValue }
}
#endif

// Private
private let fileManager = FileManager.default
#if canImport(Combine)
private var cancellables: Set<AnyCancellable> = []
#endif
private let url: URL
#if !os(Linux) && !os(Android) && !os(Windows)
private let logger: Logger
#endif

private let encoder: JSONEncoder
private let decoder: JSONDecoder
Expand All @@ -35,12 +42,14 @@ public final class PapyrusStore {
encoder: JSONEncoder = JSONEncoder(),
decoder: JSONDecoder = JSONDecoder()) {
self.url = url
self.encoder = encoder
self.decoder = decoder
#if !os(Linux) && !os(Android) && !os(Windows)
self.logger = Logger(
subsystem: "com.reddavis.PapyrusStore",
category: "PapyrusStore"
)
self.encoder = encoder
self.decoder = decoder
#endif
self.setupDataDirectory()
}

Expand All @@ -63,7 +72,9 @@ public final class PapyrusStore {
do {
try self.createDirectoryIfNeeded(at: self.url)
} catch {
#if !os(Linux) && !os(Android) && !os(Windows)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether it is cleaner to bring these checks inside the Logger class. So the Logger class decides whether to print or use os log?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember correctly, Linux, Android, and Windows don't have os.log, so it can't go directly in the logger. I'm not sure if those OS's have an equivalent logger

self.logger.fault("Unable to create store directory: \(error)")
#endif
}
}

Expand Down Expand Up @@ -101,7 +112,9 @@ public final class PapyrusStore {

// Create directory
try self.fileManager.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
#if !os(Linux) && !os(Android) && !os(Windows)
self.logger.debug("Created directory: \(url.absoluteString)")
#endif
}
}

Expand All @@ -123,9 +136,11 @@ public extension PapyrusStore {
self.save($0, filename: $0.filename)
touchedDirectories.insert(self.directoryURL(for: $0.typeDescription))
}


#if !os(Linux) && !os(Android) && !os(Windows)
// Touch all changed directories
self.logger.debug("Touching directories: \(touchedDirectories)")
#endif

let now = Date()
touchedDirectories.forEach {
Expand All @@ -150,9 +165,13 @@ public extension PapyrusStore {
try self.createDirectoryIfNeeded(for: object.typeDescription)
let data = try self.encoder.encode(object)
try data.write(to: self.fileURL(for: object.typeDescription, filename: filename))
#if !os(Linux) && !os(Android) && !os(Windows)
self.logger.debug("Saved: \(object.typeDescription) [Filename: \(filename)]")
#endif
} catch {
#if !os(Linux) && !os(Android) && !os(Windows)
self.logger.fault("Failed to save: \(error)")
#endif
}
}
}
Expand Down Expand Up @@ -225,12 +244,16 @@ public extension PapyrusStore {
group.addTask {
let url = self.fileURL(for: String(describing: type), id: id)
try? self.fileManager.removeItem(at: url)
#if !os(Linux) && !os(Android) && !os(Windows)
self.logger.debug("Deleted: \(url)")
#endif
}
}

#if !os(Linux) && !os(Android) && !os(Windows)
// Touch all changed directories
self.logger.debug("Touching directories: \(touchedDirectories)")
#endif

let now = Date()
for url in touchedDirectories {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if canImport(Combine)
import Combine
import Foundation

Expand All @@ -22,3 +23,4 @@ struct CollectionObserverPublisher<T>: Publisher where T: Papyrus {
subscriber.receive(subscription: subscription)
}
}
#endif
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if canImport(Combine)
import Combine
import Foundation

Expand Down Expand Up @@ -70,3 +71,4 @@ where T.Input == [Output] {
}
}
}
#endif
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#if canImport(Combine)

import Combine
import Foundation

Expand Down Expand Up @@ -28,3 +30,4 @@ struct ObjectObserverPublisher<T>: Publisher where T: Papyrus & Equatable {
subscriber.receive(subscription: subscription)
}
}
#endif
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if canImport(Combine)
import Combine
import Foundation

Expand Down Expand Up @@ -62,3 +63,4 @@ where T.Input == Output,
}
}
}
#endif
8 changes: 6 additions & 2 deletions Papyrus/Source/Queries/CollectionQuery.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#if canImport(Combine)
import Combine
#endif
import Foundation


Expand Down Expand Up @@ -68,7 +70,8 @@ public class CollectionQuery<T> where T: Papyrus {
self.sort = onSort
return self
}


#if canImport(Combine)
/// Observe changes to the query.
/// - Returns: A publisher that emits values when
/// valid objects are changed.
Expand All @@ -79,7 +82,8 @@ public class CollectionQuery<T> where T: Papyrus {
.replaceError(with: [])
.eraseToAnyPublisher()
}

#endif

/// Observe changes to the query.
/// - Returns: A `AsyncThrowingStream` instance.
public func stream() -> AsyncThrowingStream<[T], Error> {
Expand Down
6 changes: 5 additions & 1 deletion Papyrus/Source/Queries/ObjectQuery.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#if canImport(Combine)
import Combine
#endif
import Foundation


Expand Down Expand Up @@ -40,7 +42,8 @@ public class ObjectQuery<T: Papyrus> {
throw PapyrusStore.QueryError.invalidSchema(details: error)
}
}


#if canImport(Combine)
/// Observe changes to the query via a publisher.
/// - Returns: A publisher that emits values when
/// valid objects are changed.
Expand All @@ -51,6 +54,7 @@ public class ObjectQuery<T: Papyrus> {
)
.eraseToAnyPublisher()
}
#endif

/// Observe changes to the query via an async stream.
/// - Returns: A `AsyncThrowingStream` instance.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if canImport(Combine)
import Combine
import XCTest
@testable import Papyrus
Expand Down Expand Up @@ -105,3 +106,4 @@ final class CollectionObserverPublisherTests: XCTestCase {
self.waitForExpectations(timeout: 2.0)
}
}
#endif
4 changes: 4 additions & 0 deletions PapyrusTests/Source/Tests/CollectionQueryTests.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#if canImport(Combine)
import Combine
#endif
import XCTest
@testable import Papyrus

Expand All @@ -7,7 +9,9 @@ import XCTest
final class CollectionQueryTests: XCTestCase {
private var storeDirectory: URL!
private let numberOfDummyObjects = 10
#if canImport(Combine)
private var cancellables: Set<AnyCancellable>!
#endif

// MARK: Setup

Expand Down
2 changes: 2 additions & 0 deletions PapyrusTests/Source/Tests/ObjectObserverPublisherTests.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if canImport(Combine)
import Combine
import XCTest
@testable import Papyrus
Expand Down Expand Up @@ -184,3 +185,4 @@ extension ObjectObserverPublisherTests {
)
}
}
#endif
4 changes: 4 additions & 0 deletions PapyrusTests/Source/Tests/ObjectQueryTests.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#if canImport(Combine)
import Combine
#endif
import XCTest
@testable import Papyrus

Expand All @@ -7,7 +9,9 @@ import XCTest
final class ObjectQueryTests: XCTestCase {
private let fileManager = FileManager.default
private var storeDirectory: URL!
#if canImport(Combine)
private var cancellables: Set<AnyCancellable>!
#endif

// MARK: Setup

Expand Down
4 changes: 4 additions & 0 deletions PapyrusTests/Source/Tests/PapyrusStoreTests.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#if canImport(Combine)
import Combine
#endif
import XCTest
@testable import Papyrus

Expand All @@ -8,7 +10,9 @@ final class PapyrusStoreTests: XCTestCase {
private let fileManager = FileManager.default
private var store: PapyrusStore!
private var storeDirectory: URL!
#if canImport(Combine)
private var cancellables: Set<AnyCancellable>!
#endif

// MARK: Setup

Expand Down