@@ -15,7 +15,7 @@ import Foundation
15
15
/// A file that describes which files and directories should be ignored by the formatter.
16
16
/// In the future, this file may contain complex rules for ignoring files, based
17
17
/// on pattern matching file paths.
18
- ///
18
+ ///
19
19
/// Currently, the only valid content for an ignore file is a single asterisk "*",
20
20
/// optionally surrounded by whitespace.
21
21
public class IgnoreFile {
@@ -26,18 +26,30 @@ public class IgnoreFile {
26
26
27
27
/// Errors that can be thrown by the IgnoreFile initializer.
28
28
public enum Error : Swift . Error {
29
- /// Error thrown when an ignore file has invalid content.
30
- case invalidContent( URL )
29
+ /// Error thrown when initialising with invalid content.
30
+ case invalidContent
31
+
32
+ /// Error thrown when we fail to initialise with the given URL.
33
+ case invalidFile( URL , Swift . Error )
34
+ }
35
+
36
+ /// Create an instance from a string.
37
+ /// Returns nil if the content is not valid.
38
+ public init ( _ content: String ) throws {
39
+ guard content. trimmingCharacters ( in: . whitespacesAndNewlines) == " * " else {
40
+ throw Error . invalidContent
41
+ }
31
42
}
32
43
33
44
/// Create an instance from the contents of the file at the given URL.
34
45
/// Throws an error if the file content can't be read, or is not valid.
35
- public init ( contentsOf url: URL ) throws {
36
- let content = try String ( contentsOf: url, encoding: . utf8)
37
- guard content. trimmingCharacters ( in: . whitespacesAndNewlines) == " * " else {
38
- throw Error . invalidContent ( url)
39
- }
40
- }
46
+ public convenience init ( contentsOf url: URL ) throws {
47
+ do {
48
+ try self . init ( try String ( contentsOf: url, encoding: . utf8) )
49
+ } catch {
50
+ throw Error . invalidFile ( url, error)
51
+ }
52
+ }
41
53
42
54
/// Create an instance for the given directory, if a valid
43
55
/// ignore file with the standard name is found in that directory.
@@ -47,35 +59,41 @@ public class IgnoreFile {
47
59
/// Note that this initializer does not search parent directories for ignore files.
48
60
public convenience init ? ( forDirectory directory: URL ) throws {
49
61
let url = directory. appendingPathComponent ( IgnoreFile . fileName)
50
- guard FileManager . default. isReadableFile ( atPath: url. path) else {
51
- return nil
52
- }
53
62
54
- try self . init ( contentsOf: url)
63
+ do {
64
+ try self . init ( contentsOf: url)
65
+ } catch {
66
+ if case let Error . invalidFile( _, underlying) = error, ( underlying as NSError ) . domain == NSCocoaErrorDomain,
67
+ ( underlying as NSError ) . code == NSFileReadNoSuchFileError
68
+ {
69
+ return nil
70
+ }
71
+ throw error
72
+ }
55
73
}
56
74
57
75
/// Create an instance to use for the given URL.
58
76
/// We search for an ignore file starting from the given URL's container,
59
77
/// and moving up the directory tree, until we reach the root directory.
60
78
/// Returns nil if no ignore file is found.
61
- /// Throws an error if an invalid ignore file is found somewhere
79
+ /// Throws an error if an invalid ignore file is found somewhere
62
80
/// in the directory tree.
63
81
///
64
82
/// Note that we start the search from the given URL's **container**,
65
83
/// not the URL itself; the URL passed in is expected to be for a file.
66
84
/// If you pass a directory URL, the search will not include the contents
67
85
/// of that directory.
68
86
public convenience init ? ( for url: URL ) throws {
69
- var containingDirectory = url. absoluteURL. standardized
70
- repeat {
71
- containingDirectory. deleteLastPathComponent ( )
72
- let url = containingDirectory. appendingPathComponent ( IgnoreFile . fileName)
73
- if FileManager . default. isReadableFile ( atPath: url. path) {
74
- try self . init ( contentsOf: url)
75
- return
76
- }
77
- } while !containingDirectory. isRoot
78
- return nil
87
+ var containingDirectory = url. absoluteURL. standardized
88
+ repeat {
89
+ containingDirectory. deleteLastPathComponent ( )
90
+ let url = containingDirectory. appendingPathComponent ( IgnoreFile . fileName)
91
+ if FileManager . default. isReadableFile ( atPath: url. path) {
92
+ try self . init ( contentsOf: url)
93
+ return
94
+ }
95
+ } while !containingDirectory. isRoot
96
+ return nil
79
97
}
80
98
81
99
/// Should the given URL be processed?
@@ -85,9 +103,9 @@ public class IgnoreFile {
85
103
return false
86
104
}
87
105
88
- /// Returns true if the name of the given URL matches
106
+ /// Returns true if the name of the given URL matches
89
107
/// the standard ignore file name.
90
108
public static func isStandardIgnoreFile( _ url: URL ) -> Bool {
91
109
return url. lastPathComponent == fileName
92
110
}
93
- }
111
+ }
0 commit comments