File: FileManagerProtocol.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (126 lines) | stat: -rw-r--r-- 5,913 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 This source file is part of the Swift.org open source project

 Copyright (c) 2021-2024 Apple Inc. and the Swift project authors
 Licensed under Apache License v2.0 with Runtime Library Exception

 See https://swift.org/LICENSE.txt for license information
 See https://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

import Foundation

/// A read-write file manager.
///
/// A file-system manager is a type that's central to *managing* files on
/// a file-system, it performs actions like creating new files, copying, renaming
/// and deleting files, and organizing them in directories.
///
/// The Cocoa `FileManager` type is the default implementation of that protocol
/// that manages files stored on disk.
///
/// Should you need a file system with a different storage, create your own
/// protocol implementations to manage files in memory,
/// on a network, in a database, or elsewhere.
package protocol FileManagerProtocol {
    
    /// Returns the data content of a file at the given path, if it exists.
    func contents(atPath: String) -> Data?
    /// Compares the contents of two files at the given paths.
    func contentsEqual(atPath: String, andPath: String) -> Bool

    /// The *current* directory path.
    var currentDirectoryPath: String { get }
    
    /// Returns `true` if a file or a directory exists at the given path.
    func fileExists(atPath: String, isDirectory: UnsafeMutablePointer<ObjCBool>?) -> Bool
    /// Returns `true` if a directory exists at the given path.
    func directoryExists(atPath: String) -> Bool
    /// Returns `true` if a file exists at the given path.
    func fileExists(atPath: String) -> Bool
    /// Copies a file from one location on the file-system to another.
    func copyItem(at: URL, to: URL) throws
    /// Moves a file from one location on the file-system to another.
    func moveItem(at: URL, to: URL) throws
    /// Creates a new file folder at the given location.
    func createDirectory(at: URL, withIntermediateDirectories: Bool, attributes: [FileAttributeKey : Any]?) throws
    /// Removes a file from the given location.
    func removeItem(at: URL) throws
    /// Returns a list of items in a directory
    func contentsOfDirectory(atPath path: String) throws -> [String]
    func contentsOfDirectory(at url: URL, includingPropertiesForKeys keys: [URLResourceKey]?, options mask: FileManager.DirectoryEnumerationOptions) throws -> [URL]
    
    /// Returns a unique temporary directory.
    ///
    /// Each call to this function will return a new temporary directory.
    func uniqueTemporaryDirectory() -> URL // Because we shadow 'FileManager.temporaryDirectory' in our tests, we can't also use 'temporaryDirectory' in FileManagerProtocol
    
    /// Creates a file with the specified `contents` at the specified location.
    ///
    /// - Parameters:
    ///   - at: The location to create the file
    ///   - contents: The data to write to the file.
    ///
    /// - Note: This method doesn't exist on ``FileManager``.
    ///         There is a similar looking method but it doesn't provide information about potential errors.
    ///
    /// - Throws: If the file couldn't be created with the specified contents.
    func createFile(at: URL, contents: Data) throws
    
    /// Returns the data content of a file at the given URL.
    ///
    /// - Parameters:
    ///   - url: The location to create the file
    ///
    /// - Note: This method doesn't exist on ``FileManager``.
    ///         There is a similar looking method but it doesn't provide information about potential errors.
    ///
    /// - Throws: If the file couldn't be read.
    func contents(of url: URL) throws -> Data
    
    /// Creates a file with the given contents at the given url with the specified
    /// writing options.
    ///
    /// - Parameters:
    ///   - at: The location to create the file
    ///   - contents: The data to write to the file.
    ///   - options: Options for writing the data. Provide `nil` to use the default
    ///              writing options of the file manager.
    func createFile(at location: URL, contents: Data, options writingOptions: NSData.WritingOptions?) throws
}

extension FileManagerProtocol {
    /// Returns a Boolean value that indicates whether a directory exists at a specified path.
    package func directoryExists(atPath path: String) -> Bool {
        var isDirectory = ObjCBool(booleanLiteral: false)
        let fileExistsAtPath = fileExists(atPath: path, isDirectory: &isDirectory)
        return fileExistsAtPath && isDirectory.boolValue
    }
}

/// Add compliance to `FileManagerProtocol` to `FileManager`,
/// most of the methods are already implemented in Foundation.
extension FileManager: FileManagerProtocol {
    // This method doesn't exist on `FileManager`. There is a similar looking method but it doesn't provide information about potential errors.
    package func contents(of url: URL) throws -> Data {
        return try Data(contentsOf: url)
    }
    
    // This method doesn't exist on `FileManager`. There is a similar looking method but it doesn't provide information about potential errors.
    package func createFile(at location: URL, contents: Data) throws {
        try contents.write(to: location, options: .atomic)
    }
    
    package func createFile(at location: URL, contents: Data, options writingOptions: NSData.WritingOptions?) throws {
        if let writingOptions {
            try contents.write(to: location, options: writingOptions)
        } else {
            try contents.write(to: location)
        }
    }
    
    // Because we shadow 'FileManager.temporaryDirectory' in our tests, we can't also use 'temporaryDirectory' in FileManagerProtocol/
    package func uniqueTemporaryDirectory() -> URL {
        temporaryDirectory.appendingPathComponent(ProcessInfo.processInfo.globallyUniqueString, isDirectory: true)
    }
}