Skip to content

Commit

Permalink
Use custom extended attributes instead of modification date attribute…
Browse files Browse the repository at this point in the history
… of a directory
  • Loading branch information
mollyIV committed May 20, 2019
1 parent a2a669f commit bfca280
Showing 1 changed file with 40 additions and 7 deletions.
47 changes: 40 additions & 7 deletions Source/CarthageKit/Git.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public struct FetchCache {
}

internal static func needsFetch(forURL url: GitURL) -> Bool {
guard let lastFetch = lastFetchTimes[url] ?? repositoriesLastFetchTime()?.timeIntervalSince1970 else {
guard let lastFetch = lastFetchTimes[url] ?? repositoriesLastFetchTime() else {
return true
}

Expand All @@ -37,17 +37,50 @@ public struct FetchCache {
}
}

fileprivate static func repositoriesLastFetchTime() -> Date? {
do {
let attr = try FileManager.default.attributesOfItem(atPath: Constants.Dependency.repositoriesURL.path)
return attr[FileAttributeKey.modificationDate] as? Date
} catch {
fileprivate static func repositoriesLastFetchTime() -> TimeInterval? {
guard let data = try? Constants.Dependency.repositoriesURL.extendedAttribute(for: "\(Constants.bundleIdentifier).repositories.last.fetch.time") else {
return nil
}
return data.withUnsafeBytes { $0.pointee as TimeInterval }
}

public static func updateRepositoriesLastFetchTime() {
try? FileManager.default.setAttributes([FileAttributeKey.modificationDate: Date()], ofItemAtPath: Constants.Dependency.repositoriesURL.path)
var now = Date().timeIntervalSince1970
let data = Data(bytes: &now, count: MemoryLayout<TimeInterval>.size)
try? Constants.Dependency.repositoriesURL.setExtendedAttribute(for: "\(Constants.bundleIdentifier).repositories.last.fetch.time", data: data)
}
}

/// URL extension to support operations on extended attributes of a file
fileprivate extension URL {

enum ExtendedAttributesError: Error {
case cannotReadAttribute
case cannotSetAttribute
}

func extendedAttribute(for name: String) throws -> Data {
let data = try withUnsafeFileSystemRepresentation { path -> Data in
let length = getxattr(path, name, nil, 0, 0, 0)
guard length >= 0 else { throw ExtendedAttributesError.cannotReadAttribute }

var data = Data(count: length)
let result = data.withUnsafeMutableBytes { [count = data.count] in
getxattr(path, name, $0.baseAddress, count, 0, 0)
}
guard result >= 0 else { throw ExtendedAttributesError.cannotReadAttribute }
return data
}
return data
}

func setExtendedAttribute(for name: String, data: Data) throws {
try withUnsafeFileSystemRepresentation { path in
let result = data.withUnsafeBytes {
setxattr(path, name, $0, data.count, 0, 0)
}
guard result >= 0 else { throw ExtendedAttributesError.cannotSetAttribute }
}
}
}

Expand Down

0 comments on commit bfca280

Please sign in to comment.