Skip to content

Commit

Permalink
Update SwiftPlate template
Browse files Browse the repository at this point in the history
  • Loading branch information
dreymonde committed Jan 18, 2018
1 parent bcd439a commit cf5305e
Show file tree
Hide file tree
Showing 9 changed files with 441 additions and 155 deletions.
2 changes: 1 addition & 1 deletion Configs/Shallows.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2017 Oleg Dreyman. All rights reserved.</string>
<string>Copyright © 2018 Oleg Dreyman. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
Expand Down
25 changes: 24 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Shallows"
name: "Shallows",
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: "Shallows",
targets: ["Shallows"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "Shallows",
dependencies: []),
.testTarget(
name: "ShallowsTests",
dependencies: ["Shallows"]),
]
)
4 changes: 2 additions & 2 deletions Shallows.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ Pod::Spec.new do |s|
s.description = <<-DESC
Your description here.
DESC
s.homepage = ""
s.homepage = "https://github.com/dreymonde/Shallows"
s.license = { :type => "MIT", :file => "LICENSE" }
s.author = { "Oleg Dreyman" => "[email protected]" }
s.social_media_url = ""
s.ios.deployment_target = "8.0"
s.osx.deployment_target = "10.9"
s.watchos.deployment_target = "2.0"
s.tvos.deployment_target = "9.0"
s.source = { :git => ".git", :tag => s.version.to_s }
s.source = { :git => "https://github.com/dreymonde/Shallows.git", :tag => s.version.to_s }
s.source_files = "Sources/**/*"
s.frameworks = "Foundation"
end
271 changes: 150 additions & 121 deletions Shallows.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,11 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableThreadSanitizer = "YES"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
stopOnEveryThreadSanitizerIssue = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
Expand Down
227 changes: 227 additions & 0 deletions Sources/DiskStorage.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
//
// DiskStorage.swift
// Shallows
//
// Created by Олег on 18.01.2018.
// Copyright © 2018 Shallows. All rights reserved.
//

import Foundation

public struct FileURL {

public let url: URL

public init(_ url: URL) {
self.url = url
}

public init(_ path: String) {
self.init(URL.init(fileURLWithPath: path))
}

}

public struct Filename : RawRepresentable, Hashable, ExpressibleByStringLiteral {

public var hashValue: Int {
return rawValue.hashValue
}

public var rawValue: String

public init(rawValue: String) {
self.rawValue = rawValue
}

public init(stringLiteral value: String) {
self.init(rawValue: value)
}

public init(unicodeScalarLiteral value: String) {
self.init(rawValue: value)
}

public init(extendedGraphemeClusterLiteral value: String) {
self.init(rawValue: value)
}

public func base64Encoded() -> String {
guard let data = rawValue.data(using: .utf8) else {
return rawValue
}
return data.base64EncodedString()
}

public struct Transform {

private let transform: (Filename) -> String

private init(transform: @escaping (Filename) -> String) {
self.transform = transform
}

public static let base64: Transform = Transform(transform: { $0.base64Encoded() })
public static let notTransformed: Transform = Transform(transform: { $0.rawValue })
public static func custom(_ transform: @escaping (Filename) -> String) -> Transform {
return Transform(transform: transform)
}

public func finalForm(of filename: Filename) -> String {
return transform(filename)
}

}

}

public final class DiskFolderStorage : StorageProtocol {

public typealias Key = Filename
public typealias Value = Data

public let storageName: String
public let folderURL: URL

private let diskStorage: Storage<FileURL, Data>

public let transformFilename: Filename.Transform

public init(folderURL: URL,
diskStorage: Storage<FileURL, Data> = DiskStorage.main.asStorage(),
transformFilename: Filename.Transform = .base64) {
self.diskStorage = diskStorage
self.folderURL = folderURL
self.transformFilename = transformFilename
self.storageName = "disk-\(folderURL.lastPathComponent)"
}

public func fileURL(forFilename filename: Filename) -> FileURL {
let finalForm = transformFilename.finalForm(of: filename)
return FileURL(folderURL.appendingPathComponent(finalForm))
}

public func retrieve(forKey filename: Filename, completion: @escaping (Result<Data>) -> ()) {
let fileURL = self.fileURL(forFilename: filename)
diskStorage.retrieve(forKey: fileURL, completion: completion)
}

public func set(_ data: Data, forKey filename: Filename, completion: @escaping (Result<Void>) -> ()) {
let fileURL = self.fileURL(forFilename: filename)
diskStorage.set(data, forKey: fileURL, completion: completion)
}

}

extension URL {

public init(directory: FileManager.SearchPathDirectory, domainMask: FileManager.SearchPathDomainMask = .userDomainMask) {
let urls = FileManager.default.urls(for: directory, in: domainMask)
self = urls.first!
}

}

extension DiskFolderStorage {

public static func inDirectory(_ directory: FileManager.SearchPathDirectory,
appending pathComponent: String,
domainMask: FileManager.SearchPathDomainMask = .userDomainMask,
diskStorage: Storage<FileURL, Data>,
transformFilename: Filename.Transform) -> DiskFolderStorage {
let directoryURL = URL(directory: directory, domainMask: domainMask).appendingPathComponent(pathComponent)
return DiskFolderStorage(folderURL: directoryURL,
diskStorage: diskStorage,
transformFilename: transformFilename)
}

}

public final class DiskStorage : StorageProtocol {

public typealias Key = FileURL
public typealias Value = Data

public var storageName: String {
return "disk"
}

private let queue: DispatchQueue = DispatchQueue(label: "disk-storage-queue", qos: .userInitiated)
private let fileManager = FileManager.default

fileprivate let creatingDirectories: Bool

public init(creatingDirectories: Bool = true) {
self.creatingDirectories = creatingDirectories
}

public func retrieve(forKey key: FileURL, completion: @escaping (Result<Data>) -> ()) {
queue.async {
do {
let data = try Data.init(contentsOf: key.url)
completion(succeed(with: data))
} catch {
completion(fail(with: error))
}
}
}

public enum Error : Swift.Error {
case cantCreatFile
case cantCreateDirectory(Swift.Error)
}

public func set(_ value: Data, forKey key: FileURL, completion: @escaping (Result<Void>) -> ()) {
queue.async {
do {
try self.createDirectoryURLIfNotExisting(for: key)
let path = key.url.path
if self.fileManager.createFile(atPath: path,
contents: value,
attributes: nil) {
completion(.success)
} else {
completion(fail(with: Error.cantCreatFile))
}
} catch {
completion(fail(with: error))
}
}
}

public static func directoryURL(of fileURL: FileURL) -> URL {
return fileURL.url.deletingLastPathComponent()
}

fileprivate func createDirectoryURLIfNotExisting(for fileURL: FileURL) throws {
let directoryURL = DiskStorage.directoryURL(of: fileURL)
if !fileManager.fileExists(atPath: directoryURL.path) {
do {
try fileManager.createDirectory(at: directoryURL,
withIntermediateDirectories: true,
attributes: nil)
} catch {
throw Error.cantCreateDirectory(error)
}
}
}

}

extension DiskStorage {

public static let main = DiskStorage(creatingDirectories: true)

public func folder(_ folderName: String,
in directory: FileManager.SearchPathDirectory,
domainMask: FileManager.SearchPathDomainMask = .userDomainMask,
transformFilename: Filename.Transform = .base64) -> DiskFolderStorage {
return DiskFolderStorage.inDirectory(
directory,
appending: folderName,
diskStorage: self.asStorage(),
transformFilename: transformFilename
)
}

}
26 changes: 0 additions & 26 deletions Sources/FileSystemStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,6 @@ extension FileSystemStorageProtocol {

}

public struct Filename : RawRepresentable, Hashable, ExpressibleByStringLiteral {

public var hashValue: Int {
return rawValue.hashValue
}

public var rawValue: String

public init(rawValue: String) {
self.rawValue = rawValue
}

public init(stringLiteral value: String) {
self.init(rawValue: value)
}

public init(unicodeScalarLiteral value: String) {
self.init(rawValue: value)
}

public init(extendedGraphemeClusterLiteral value: String) {
self.init(rawValue: value)
}

}

public final class FileSystemStorage : FileSystemStorageProtocol {

public static func validFilename(for key: Filename) -> Filename {
Expand Down
36 changes: 36 additions & 0 deletions Tests/ShallowsTests/DiskStorageTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// DiskStorageTests.swift
// Shallows
//
// Created by Олег on 18.01.2018.
// Copyright © 2018 Shallows. All rights reserved.
//

import XCTest
@testable import Shallows

class DiskStorageTests: XCTestCase {

override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}

override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}

func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}

func testPerformanceExample() {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}

}
3 changes: 1 addition & 2 deletions Tests/ShallowsTests/ShallowsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,8 @@ class ShallowsTests: XCTestCase {
}
}

//
}

static var allTests = [
("testFileSystemStorage", testFileSystemStorage),
]
Expand Down

0 comments on commit cf5305e

Please sign in to comment.