Compare commits

...

3 Commits

Author SHA1 Message Date
JP Simard 860814fe78
undo local development changes 2017-02-03 17:36:47 -08:00
JP Simard ee9ce4a3b6
move caches to ~/Library/Caches 2017-02-03 17:35:52 -08:00
JP Simard 327e98a86e
WIP: use modified time instead of file content hash for caching 2017-02-03 17:32:02 -08:00
5 changed files with 33 additions and 25 deletions

View File

@ -10,6 +10,7 @@ import Foundation
public protocol LintableFileManager { public protocol LintableFileManager {
func filesToLint(inPath: String, rootDirectory: String?) -> [String] func filesToLint(inPath: String, rootDirectory: String?) -> [String]
func modifiedDate(forFileAtPath: String) -> Date?
} }
extension FileManager: LintableFileManager { extension FileManager: LintableFileManager {
@ -31,4 +32,9 @@ extension FileManager: LintableFileManager {
return nil return nil
} ?? [] } ?? []
} }
public func modifiedDate(forFileAtPath path: String) -> Date? {
// swiftlint:disable:next force_cast
return try? attributesOfItem(atPath: path)[.modificationDate] as! Date
}
} }

View File

@ -34,7 +34,7 @@ public struct Configuration: Equatable {
public let rules: [Rule] public let rules: [Rule]
public var rootPath: String? // the root path to search for nested configurations public var rootPath: String? // the root path to search for nested configurations
public var configurationPath: String? // if successfully loaded from a path public var configurationPath: String? // if successfully loaded from a path
public var hash: Int? public var cacheDescription: String?
public let cachePath: String? public let cachePath: String?
public init?(disabledRules: [String] = [], public init?(disabledRules: [String] = [],
@ -175,7 +175,7 @@ public struct Configuration: Equatable {
} }
self.init(dict: dict, enableAllRules: enableAllRules)! self.init(dict: dict, enableAllRules: enableAllRules)!
configurationPath = fullPath configurationPath = fullPath
hash = dict.description.hashValue cacheDescription = dict.description
self.rootPath = rootPath self.rootPath = rootPath
return return
} catch YamlParserError.yamlParsing(let message) { } catch YamlParserError.yamlParsing(let message) {

View File

@ -85,8 +85,7 @@ public struct Linter {
} }
if let cache = cache, let path = file.path { if let cache = cache, let path = file.path {
let hash = file.contents.hash cache.cache(violations: violations, forFile: path)
cache.cache(violations: violations, forFile: path, fileHash: hash)
} }
for (deprecatedIdentifier, identifier) in deprecatedToValidIdentifier { for (deprecatedIdentifier, identifier) in deprecatedToValidIdentifier {
@ -99,11 +98,8 @@ public struct Linter {
private func cachedStyleViolations(benchmark: Bool = false) -> ([StyleViolation], [(id: String, time: Double)])? { private func cachedStyleViolations(benchmark: Bool = false) -> ([StyleViolation], [(id: String, time: Double)])? {
let start: Date! = benchmark ? Date() : nil let start: Date! = benchmark ? Date() : nil
guard let cache = cache, guard let cache = cache, let file = file.path, let cachedViolations = cache.violations(forFile: file) else {
let file = file.path, return nil
case let hash = self.file.contents.hash,
let cachedViolations = cache.violations(forFile: file, hash: hash) else {
return nil
} }
var ruleTimes = [(id: String, time: Double)]() var ruleTimes = [(id: String, time: Double)]()

View File

@ -19,24 +19,24 @@ public final class LinterCache {
private var cache: [String: Any] private var cache: [String: Any]
private let lock = NSLock() private let lock = NSLock()
public init(currentVersion: Version = .current, configurationHash: Int? = nil) { public init(currentVersion: Version = .current, configurationDescription: String? = nil) {
cache = [ cache = [
"version": currentVersion.value, "version": currentVersion.value,
"files": [:] "files": [:]
] ]
cache["configuration_hash"] = configurationHash cache["configuration"] = configurationDescription
} }
public init(cache: Any, currentVersion: Version = .current, configurationHash: Int? = nil) throws { public init(cache: Any, currentVersion: Version = .current, configurationDescription: String? = nil) throws {
guard let dictionary = cache as? [String: Any] else { guard let dictionary = cache as? [String: Any] else {
throw LinterCacheError.invalidFormat throw LinterCacheError.invalidFormat
} }
guard let version = dictionary["version"] as? String, version == currentVersion.value else { guard dictionary["version"] as? String == currentVersion.value else {
throw LinterCacheError.differentVersion throw LinterCacheError.differentVersion
} }
if dictionary["configuration_hash"] as? Int != configurationHash { guard dictionary["configuration"] as? String == configurationDescription else {
throw LinterCacheError.differentConfiguration throw LinterCacheError.differentConfiguration
} }
@ -44,31 +44,37 @@ public final class LinterCache {
} }
public convenience init(contentsOf url: URL, currentVersion: Version = .current, public convenience init(contentsOf url: URL, currentVersion: Version = .current,
configurationHash: Int? = nil) throws { configurationDescription: String? = nil) throws {
let data = try Data(contentsOf: url) let data = try Data(contentsOf: url)
let json = try JSONSerialization.jsonObject(with: data, options: []) let json = try JSONSerialization.jsonObject(with: data, options: [])
try self.init(cache: json, currentVersion: currentVersion, try self.init(cache: json, currentVersion: currentVersion,
configurationHash: configurationHash) configurationDescription: configurationDescription)
} }
public func cache(violations: [StyleViolation], forFile file: String, fileHash: Int) { public func cache(violations: [StyleViolation], forFile file: String) {
guard let lastModified = FileManager.default.modifiedDate(forFileAtPath: file) else {
return
}
lock.lock() lock.lock()
var filesCache = (cache["files"] as? [String: Any]) ?? [:] var filesCache = (cache["files"] as? [String: Any]) ?? [:]
filesCache[file] = [ filesCache[file] = [
"violations": violations.map(dictionary(for:)), "violations": violations.map(dictionary(for:)),
"hash": fileHash "last_modified": Int(lastModified.timeIntervalSinceReferenceDate)
] ]
cache["files"] = filesCache cache["files"] = filesCache
lock.unlock() lock.unlock()
} }
public func violations(forFile file: String, hash: Int) -> [StyleViolation]? { public func violations(forFile file: String) -> [StyleViolation]? {
guard let lastModified = FileManager.default.modifiedDate(forFileAtPath: file) else {
return nil
}
lock.lock() lock.lock()
guard let filesCache = cache["files"] as? [String: Any], guard let filesCache = cache["files"] as? [String: Any],
let entry = filesCache[file] as? [String: Any], let entry = filesCache[file] as? [String: Any],
let cacheHash = entry["hash"] as? Int, let cacheLastModified = entry["last_modified"] as? Int,
cacheHash == hash, cacheLastModified == Int(lastModified.timeIntervalSinceReferenceDate),
let violations = entry["violations"] as? [[String: Any]] else { let violations = entry["violations"] as? [[String: Any]] else {
lock.unlock() lock.unlock()
return nil return nil

View File

@ -16,12 +16,12 @@ extension LinterCache {
return nil return nil
} }
let configurationHash = configuration.hash let configurationDescription = configuration.cacheDescription
let cache: LinterCache let cache: LinterCache
do { do {
cache = try LinterCache(contentsOf: url, configurationHash: configurationHash) cache = try LinterCache(contentsOf: url, configurationDescription: configurationDescription)
} catch { } catch {
cache = LinterCache(configurationHash: configurationHash) cache = LinterCache(configurationDescription: configurationDescription)
} }
return cache return cache
@ -50,7 +50,7 @@ private func defaultCacheURL(options: LintOptions) -> URL {
#if os(Linux) #if os(Linux)
let baseURL = URL(fileURLWithPath: "/var/tmp/") let baseURL = URL(fileURLWithPath: "/var/tmp/")
#else #else
let baseURL = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0] let baseURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
#endif #endif
let fileName = String(rootPath.hash) + ".json" let fileName = String(rootPath.hash) + ".json"