@@ -16,15 +16,15 @@ import Foundation
16
16
*/
17
17
18
18
/// An abstract representation of a file (or folder).
19
- protocol File {
19
+ public protocol File {
20
20
/// The name of the file.
21
21
var name : String { get }
22
22
23
23
/// Writes the file to a given URL.
24
24
func write( to url: URL ) throws
25
25
}
26
26
27
- extension File {
27
+ public extension File {
28
28
/// Writes the file inside of a folder and returns the URL that it was written to.
29
29
@discardableResult
30
30
func write( inside url: URL ) throws -> URL {
@@ -35,12 +35,12 @@ extension File {
35
35
}
36
36
37
37
/// An item which provides data.
38
- protocol DataRepresentable {
38
+ public protocol DataRepresentable {
39
39
func data( ) throws -> Data
40
40
}
41
41
42
42
/// `DataRepresentable` can automatically write itself to disk via `Data.write(to:)`
43
- extension DataRepresentable {
43
+ public extension DataRepresentable {
44
44
func write( to url: URL ) throws {
45
45
try data ( ) . write ( to: url)
46
46
}
@@ -49,17 +49,22 @@ extension DataRepresentable {
49
49
// MARK: -
50
50
51
51
/// An abstract representation of a folder, containing some files or folders.
52
- struct Folder : File {
53
- let name : String
52
+ public struct Folder : File {
53
+ public init ( name: String , content: [ File ] ) {
54
+ self . name = name
55
+ self . content = content
56
+ }
57
+
58
+ public let name : String
54
59
55
60
/// The files and sub folders that this folder contains.
56
- let content : [ File ]
61
+ public let content : [ File ]
57
62
58
- func appendingFile( _ newFile: File ) -> Folder {
63
+ public func appendingFile( _ newFile: File ) -> Folder {
59
64
return Folder ( name: name, content: content + [ newFile] )
60
65
}
61
66
62
- func write( to url: URL ) throws {
67
+ public func write( to url: URL ) throws {
63
68
try FileManager . default. createDirectory ( at: url, withIntermediateDirectories: false , attributes: nil )
64
69
for file in content {
65
70
try file. write ( inside: url)
@@ -69,7 +74,7 @@ struct Folder: File {
69
74
70
75
extension Folder {
71
76
/// Returns a flat list of a folder's recursive listing for testing purposes.
72
- var recursiveContent : [ File ] {
77
+ public var recursiveContent : [ File ] {
73
78
var result = content
74
79
for file in content {
75
80
if let content = ( file as? Folder ) ? . recursiveContent {
@@ -81,13 +86,13 @@ extension Folder {
81
86
}
82
87
83
88
/// A representation of an Info.plist file.
84
- struct InfoPlist : File , DataRepresentable {
85
- let name = " Info.plist "
89
+ public struct InfoPlist : File , DataRepresentable {
90
+ public let name = " Info.plist "
86
91
87
92
/// The information that the Into.plist file contains.
88
- let content : Content
93
+ public let content : Content
89
94
90
- init ( displayName: String , identifier: String , versionString: String = " 1.0 " , developmentRegion: String = " en " ) {
95
+ public init ( displayName: String , identifier: String , versionString: String = " 1.0 " , developmentRegion: String = " en " ) {
91
96
self . content = Content (
92
97
displayName: displayName,
93
98
identifier: identifier,
@@ -96,11 +101,11 @@ struct InfoPlist: File, DataRepresentable {
96
101
)
97
102
}
98
103
99
- struct Content : Codable , Equatable {
100
- let displayName : String
101
- let identifier : String
102
- let versionString : String
103
- let developmentRegion : String
104
+ public struct Content : Codable , Equatable {
105
+ public let displayName : String
106
+ public let identifier : String
107
+ public let versionString : String
108
+ public let developmentRegion : String
104
109
105
110
fileprivate init ( displayName: String , identifier: String , versionString: String , developmentRegion: String ) {
106
111
self . displayName = displayName
@@ -117,7 +122,7 @@ struct InfoPlist: File, DataRepresentable {
117
122
}
118
123
}
119
124
120
- func data( ) throws -> Data {
125
+ public func data( ) throws -> Data {
121
126
// TODO: Replace this with PropertListEncoder (see below) when it's available in swift-corelibs-foundation
122
127
// https://github.com/apple/swift-corelibs-foundation/commit/d2d72f88d93f7645b94c21af88a7c9f69c979e4f
123
128
let infoPlist = [
@@ -136,74 +141,85 @@ struct InfoPlist: File, DataRepresentable {
136
141
}
137
142
138
143
/// A representation of a text file with some UTF-8 content.
139
- struct TextFile : File , DataRepresentable {
140
- let name : String
144
+ public struct TextFile : File , DataRepresentable {
145
+ public init ( name: String , utf8Content: String ) {
146
+ self . name = name
147
+ self . utf8Content = utf8Content
148
+ }
149
+
150
+ public let name : String
141
151
142
152
/// The UTF8 content of the file.
143
- let utf8Content : String
153
+ public let utf8Content : String
144
154
145
- func data( ) throws -> Data {
155
+ public func data( ) throws -> Data {
146
156
return utf8Content. data ( using: . utf8) !
147
157
}
148
158
}
149
159
150
160
/// A representation of a text file with some UTF-8 content.
151
- struct JSONFile < Content: Codable > : File , DataRepresentable {
152
- let name : String
161
+ public struct JSONFile < Content: Codable > : File , DataRepresentable {
162
+ public init ( name: String , content: Content ) {
163
+ self . name = name
164
+ self . content = content
165
+ }
166
+
167
+ public let name : String
153
168
154
169
/// The UTF8 content of the file.
155
- let content : Content
170
+ public let content : Content
156
171
157
- func data( ) throws -> Data {
172
+ public func data( ) throws -> Data {
158
173
return try JSONEncoder ( ) . encode ( content)
159
174
}
160
175
}
161
176
162
177
/// A copy of another file on disk somewhere.
163
- struct CopyOfFile : File , DataRepresentable {
164
- enum Error : DescribedError {
178
+ public struct CopyOfFile : File , DataRepresentable {
179
+ enum Error : LocalizedError {
165
180
case notAFile( URL )
166
181
var errorDescription : String {
167
182
switch self {
168
- case . notAFile( let url) : return " Original url is not a file: \( url. path. singleQuoted ) "
183
+ case . notAFile( let url) : return " Original url is not a file: ' \( url. path) ' "
169
184
}
170
185
}
171
186
}
172
187
173
188
/// The original file.
174
- let original : URL
175
- let name : String
189
+ public let original : URL
190
+ public let name : String
176
191
177
- init ( original: URL , newName: String ? = nil ) {
192
+ public init ( original: URL , newName: String ? = nil ) {
178
193
self . original = original
179
194
self . name = newName ?? original. lastPathComponent
180
195
}
181
196
182
- func data( ) throws -> Data {
197
+ public func data( ) throws -> Data {
183
198
// Note that `CopyOfFile` always reads a file from disk and so it's okay
184
199
// to use `FileManager.default` directly here instead of `FileManagerProtocol`.
185
- guard !FileManager. default. directoryExists ( atPath: original. path) else { throw Error . notAFile ( original) }
200
+ var isDirectory : ObjCBool = false
201
+ guard FileManager . default. fileExists ( atPath: original. path, isDirectory: & isDirectory) , !isDirectory. boolValue else { throw Error . notAFile ( original) }
186
202
return try Data ( contentsOf: original)
187
203
}
188
204
189
- func write( to url: URL ) throws {
205
+ public func write( to url: URL ) throws {
190
206
try FileManager . default. copyItem ( at: original, to: url)
191
207
}
192
208
}
193
209
194
- struct CopyOfFolder : File {
210
+ public struct CopyOfFolder : File {
195
211
/// The original file.
196
212
let original : URL
197
- let name : String
213
+ public let name : String
198
214
let shouldCopyFile : ( URL ) -> Bool
199
215
200
- init ( original: URL , newName: String ? = nil , filter shouldCopyFile: @escaping ( URL ) -> Bool = { _ in true } ) {
216
+ public init ( original: URL , newName: String ? = nil , filter shouldCopyFile: @escaping ( URL ) -> Bool = { _ in true } ) {
201
217
self . original = original
202
218
self . name = newName ?? original. lastPathComponent
203
219
self . shouldCopyFile = shouldCopyFile
204
220
}
205
221
206
- func write( to url: URL ) throws {
222
+ public func write( to url: URL ) throws {
207
223
try FileManager . default. createDirectory ( at: url, withIntermediateDirectories: false , attributes: nil )
208
224
for filePath in try FileManager . default. contentsOfDirectory ( atPath: original. path) {
209
225
// `contentsOfDirectory(atPath)` includes hidden files, skipHiddenFiles option doesn't help on Linux.
@@ -217,37 +233,37 @@ struct CopyOfFolder: File {
217
233
}
218
234
219
235
/// A file backed by `Data`.
220
- struct DataFile : File , DataRepresentable {
221
- var name : String
236
+ public struct DataFile : File , DataRepresentable {
237
+ public var name : String
222
238
var _data : Data
223
239
224
- init ( name: String , data: Data ) {
240
+ public init ( name: String , data: Data ) {
225
241
self . name = name
226
242
self . _data = data
227
243
}
228
244
229
- func data( ) throws -> Data {
245
+ public func data( ) throws -> Data {
230
246
return _data
231
247
}
232
248
}
233
249
234
250
/// A temporary folder which can write files to a temporary location on disk and
235
251
/// will delete itself when its instance is released from memory.
236
- class TempFolder : File {
237
- let name : String
238
- let url : URL
252
+ public class TempFolder : File {
253
+ public let name : String
254
+ public let url : URL
239
255
240
256
/// The files and sub folders that this folder contains.
241
257
let content : [ File ]
242
258
243
- func write( to url: URL ) throws {
259
+ public func write( to url: URL ) throws {
244
260
try FileManager . default. createDirectory ( at: url, withIntermediateDirectories: false , attributes: nil )
245
261
for file in content {
246
262
try file. write ( inside: url)
247
263
}
248
264
}
249
265
250
- init ( content: [ File ] , atRoot root: URL ) throws {
266
+ public init ( content: [ File ] , atRoot root: URL ) throws {
251
267
self . content = content
252
268
253
269
url = root
0 commit comments