Fixes & increased code coverage
This commit is contained in:
@@ -1,34 +1,35 @@
|
||||
import Foundation
|
||||
//#if os(Linux)
|
||||
//import func Glibc.chmod
|
||||
//#endif
|
||||
|
||||
public extension Path {
|
||||
//MARK: Filesystem Attributes
|
||||
|
||||
/**
|
||||
Returns the creation-time of the file.
|
||||
- Note: Returns UNIX-time-zero if there is no creation-time, this should only happen if the file doesn’t exist.
|
||||
- Note: Returns `nil` if there is no creation-time, this should only happen if the file doesn’t exist.
|
||||
- Important: On Linux this is filesystem dependendent and may not exist.
|
||||
*/
|
||||
var ctime: Date {
|
||||
var ctime: Date? {
|
||||
do {
|
||||
let attrs = try FileManager.default.attributesOfItem(atPath: string)
|
||||
return attrs[.creationDate] as? Date ?? Date(timeIntervalSince1970: 0)
|
||||
return attrs[.creationDate] as? Date
|
||||
} catch {
|
||||
//TODO log error
|
||||
return Date(timeIntervalSince1970: 0)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the modification-time of the file.
|
||||
- Note: Returns the creation time if there is no modification time.
|
||||
- Note: Returns UNIX-time-zero if neither are available, this should only happen if the file doesn’t exist.
|
||||
- Note: If this returns `nil` and the file exists, something is very wrong.
|
||||
*/
|
||||
var mtime: Date {
|
||||
var mtime: Date? {
|
||||
do {
|
||||
let attrs = try FileManager.default.attributesOfItem(atPath: string)
|
||||
return attrs[.modificationDate] as? Date ?? ctime
|
||||
return attrs[.modificationDate] as? Date
|
||||
} catch {
|
||||
//TODO log error
|
||||
return Date(timeIntervalSince1970: 0)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,27 +40,40 @@ public extension Path {
|
||||
*/
|
||||
@discardableResult
|
||||
func chmod(_ octal: Int) throws -> Path {
|
||||
// #if os(Linux)
|
||||
// Glibc.chmod(string, __mode_t(octal))
|
||||
// #else
|
||||
try FileManager.default.setAttributes([.posixPermissions: octal], ofItemAtPath: string)
|
||||
// #endif
|
||||
return self
|
||||
}
|
||||
|
||||
/// - Note: If file is already locked, does nothing
|
||||
/// - Note: If file doesn’t exist, throws
|
||||
/**
|
||||
- Note: If file is already locked, does nothing.
|
||||
- Note: If file doesn’t exist, throws.
|
||||
- Important: On Linux does nothing.
|
||||
*/
|
||||
@discardableResult
|
||||
func lock() throws -> Path {
|
||||
#if !os(Linux)
|
||||
var attrs = try FileManager.default.attributesOfItem(atPath: string)
|
||||
let b = attrs[.immutable] as? Bool ?? false
|
||||
if !b {
|
||||
attrs[.immutable] = true
|
||||
try FileManager.default.setAttributes(attrs, ofItemAtPath: string)
|
||||
}
|
||||
#endif
|
||||
return self
|
||||
}
|
||||
|
||||
/// - Note: If file isn‘t locked, does nothing
|
||||
/// - Note: If file doesn’t exist, does nothing
|
||||
/**
|
||||
- Note: If file isn‘t locked, does nothing.
|
||||
- Note: If file doesn’t exist, does nothing.
|
||||
- Important: On Linux does nothing.
|
||||
*/
|
||||
@discardableResult
|
||||
func unlock() throws -> Path {
|
||||
#if !os(Linux)
|
||||
var attrs: [FileAttributeKey: Any]
|
||||
do {
|
||||
attrs = try FileManager.default.attributesOfItem(atPath: string)
|
||||
@@ -71,6 +85,7 @@ public extension Path {
|
||||
attrs[.immutable] = false
|
||||
try FileManager.default.setAttributes(attrs, ofItemAtPath: string)
|
||||
}
|
||||
#endif
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +130,9 @@ public extension Path {
|
||||
Deletes the path, recursively if a directory.
|
||||
- Note: noop: if the path doesn’t exist
|
||||
∵ *Path.swift* doesn’t error if desired end result preexists.
|
||||
- Note: On UNIX will this function will succeed if the parent directory is writable and the current user has permission.
|
||||
- Note: This function will fail if the file or directory is “locked”
|
||||
- SeeAlso: `lock()`
|
||||
*/
|
||||
@inlinable
|
||||
func delete() throws {
|
||||
|
||||
@@ -10,6 +10,6 @@ extension Path: CustomStringConvertible {
|
||||
extension Path: CustomDebugStringConvertible {
|
||||
/// Returns eg. `Path(string: "/foo")`
|
||||
public var debugDescription: String {
|
||||
return "Path(string: \(string))"
|
||||
return "Path(\(string))"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import Foundation
|
||||
#if os(Linux)
|
||||
import func Glibc.access
|
||||
#else
|
||||
import func Darwin.access
|
||||
#endif
|
||||
|
||||
public extension Path {
|
||||
//MARK: Filesystem Properties
|
||||
@@ -32,11 +37,22 @@ public extension Path {
|
||||
|
||||
/// Returns true if the path represents an actual file that is also deletable by the current user.
|
||||
var isDeletable: Bool {
|
||||
return FileManager.default.isDeletableFile(atPath: string)
|
||||
#if os(Linux) && !swift(>=5.1)
|
||||
return exists && access(parent.string, W_OK) == 0
|
||||
#else
|
||||
// FileManager.isDeletableFile returns true if there is *not* a file there
|
||||
return exists && FileManager.default.isDeletableFile(atPath: string)
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Returns true if the path represents an actual file that is also executable by the current user.
|
||||
var isExecutable: Bool {
|
||||
return FileManager.default.isExecutableFile(atPath: string)
|
||||
if access(string, X_OK) == 0 {
|
||||
// FileManager.isExxecutableFile returns true even if there is *not*
|
||||
// a file there *but* if there was it could be *made* executable
|
||||
return FileManager.default.isExecutableFile(atPath: string)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user