@@ -10,8 +10,7 @@ let moduleList = CommandLine.arguments[2]
10
10
11
11
let modules = moduleList. components ( separatedBy: " , " )
12
12
13
- let currentDirectoryUrl = URL ( fileURLWithPath: FileManager . default. currentDirectoryPath, isDirectory: true )
14
- let publicDirectoryUrl = currentDirectoryUrl. appendingPathComponent ( " public " , isDirectory: true )
13
+ let publicDirectoryUrl = URL . currentDirectory ( ) . appending ( component: " public/ " )
15
14
16
15
try run ( )
17
16
@@ -34,7 +33,7 @@ func run() throws {
34
33
}
35
34
36
35
func ensurePluginAvailable( ) throws {
37
- let manifestUrl = currentDirectoryUrl . appendingPathComponent ( " Package.swift " , isDirectory : false )
36
+ let manifestUrl = URL . currentDirectory ( ) . appending ( component : " Package.swift " )
38
37
var manifestContents = try String ( contentsOf: manifestUrl, encoding: . utf8)
39
38
if !manifestContents. contains ( " .package(url: \" https://github.com/apple/swift-docc-plugin " ) {
40
39
// This is freely admitted to be quick and dirty. When SE-0301 gets into a release, we can use that.
@@ -54,7 +53,7 @@ func ensurePluginAvailable() throws {
54
53
func generateDocs( module: String ) throws {
55
54
print ( " 🔎 Finding DocC catalog " )
56
55
let doccCatalogs = try FileManager . default. contentsOfDirectory (
57
- at: currentDirectoryUrl . appendingPathComponent ( " Sources " , isDirectory : true ) . appendingPathComponent ( module, isDirectory : true ) ,
56
+ at: URL . currentDirectory ( ) . appending ( components : " Sources " , " \ ( module) / " ) ,
58
57
includingPropertiesForKeys: nil ,
59
58
options: [ . skipsSubdirectoryDescendants]
60
59
) . filter { $0. hasDirectoryPath && $0. pathExtension == " docc " }
@@ -70,14 +69,10 @@ func generateDocs(module: String) throws {
70
69
print ( " 🗂️ Using DocC catalog \( doccCatalogUrl. lastPathComponent) " )
71
70
72
71
print ( " 📐 Copying theme " )
73
- do {
74
- try FileManager . default. copyItemIfExistsWithoutOverwrite (
75
- at: currentDirectoryUrl. appendingPathComponent ( " theme-settings.json " , isDirectory: false ) ,
76
- to: doccCatalogUrl. appendingPathComponent ( " theme-settings.json " , isDirectory: false )
77
- )
78
- } catch CocoaError . fileReadNoSuchFile , CocoaError. fileWriteFileExists {
79
- // ignore
80
- }
72
+ try FileManager . default. copyItemIfExistsWithoutOverwrite (
73
+ at: URL . currentDirectory ( ) . appending ( component: " theme-settings.json " ) ,
74
+ to: doccCatalogUrl. appending ( component: " theme-settings.json " )
75
+ )
81
76
82
77
print ( " 📝 Generating docs " )
83
78
try shell ( [
@@ -92,7 +87,7 @@ func generateDocs(module: String) throws {
92
87
" --fallback-bundle-version " , " 1.0.0 " ,
93
88
" --transform-for-static-hosting " ,
94
89
" --hosting-base-path " , " / \( module. lowercased ( ) ) " ,
95
- " --output-path " , publicDirectoryUrl. appendingPathComponent ( module. lowercased ( ) , isDirectory : true ) . path,
90
+ " --output-path " , publicDirectoryUrl. appending ( component : " \( module. lowercased ( ) ) / " ) . path,
96
91
] )
97
92
}
98
93
@@ -111,7 +106,7 @@ func shell(_ args: [String]) throws {
111
106
}
112
107
113
108
// Run the command:
114
- let task = try Process . run ( URL ( fileURLWithPath : " /usr/bin/env " , isDirectory : false ) , arguments: args)
109
+ let task = try Process . run ( URL ( filePath : " /usr/bin/env " ) , arguments: args)
115
110
task. waitUntilExit ( )
116
111
guard task. terminationStatus == 0 else {
117
112
throw ShellError ( terminationStatus: task. terminationStatus)
@@ -126,18 +121,51 @@ extension FileManager {
126
121
func removeItemIfExists( at url: URL ) throws {
127
122
do {
128
123
try self . removeItem ( at: url)
129
- } catch let error as NSError where error. domain == CocoaError . errorDomain && error . code == CocoaError . fileNoSuchFile. rawValue {
124
+ } catch let error as NSError where error. isCocoaError ( . fileNoSuchFile) {
130
125
// ignore
131
126
}
132
127
}
133
128
134
129
func copyItemIfExistsWithoutOverwrite( at src: URL , to dst: URL ) throws {
135
130
do {
131
+ // https://github.com/apple/swift-corelibs-foundation/pull/4808
132
+ #if !canImport(Darwin)
133
+ do {
134
+ _ = try dst. checkResourceIsReachable ( )
135
+ throw NSError ( domain: CocoaError . errorDomain, code: CocoaError . fileWriteFileExists. rawValue)
136
+ } catch let error as NSError where error. isCocoaError ( . fileReadNoSuchFile) { }
137
+ #endif
136
138
try self . copyItem ( at: src, to: dst)
137
- } catch let error as NSError where error. domain == CocoaError . errorDomain && error . code == CocoaError . fileReadNoSuchFile. rawValue {
139
+ } catch let error as NSError where error. isCocoaError ( . fileReadNoSuchFile) {
138
140
// ignore
139
- } catch let error as NSError where error. domain == CocoaError . errorDomain && error . code == CocoaError . fileWriteFileExists. rawValue {
141
+ } catch let error as NSError where error. isCocoaError ( . fileWriteFileExists) {
140
142
// ignore
141
143
}
142
144
}
143
145
}
146
+
147
+ extension NSError {
148
+ func isCocoaError( _ code: CocoaError . Code ) -> Bool {
149
+ self . domain == CocoaError . errorDomain && self . code == code. rawValue
150
+ }
151
+ }
152
+
153
+ #if !canImport(Darwin)
154
+ extension URL {
155
+ public enum DirectoryHint : Equatable { case isDirectory, notDirectory, inferFromPath }
156
+ static func isDirFlag( _ path: some StringProtocol , _ hint: DirectoryHint ) -> Bool {
157
+ hint == . inferFromPath ? path. last == " / " : hint == . isDirectory
158
+ }
159
+ public init ( filePath: String , directoryHint hint: DirectoryHint = . inferFromPath, relativeTo base: URL ? = nil ) {
160
+ self = URL ( fileURLWithPath: filePath, isDirectory: Self . isDirFlag ( path, hint) , relativeTo: base)
161
+ }
162
+ public func appending( component: some StringProtocol , directoryHint hint: DirectoryHint = . inferFromPath) -> URL {
163
+ self . appendingPathComponent ( component, isDirectory: Self . isDirFlag ( component, hint) )
164
+ }
165
+ public func appending( components: ( some StringProtocol ) ... , directoryHint hint: DirectoryHint = . inferFromPath) -> URL {
166
+ components. dropLast ( ) . reduce ( self ) { $0. appending ( component: $1, directoryHint: . isDirectory) }
167
+ . appending ( component: components. last!, directoryHint: hint)
168
+ }
169
+ public static func currentDirectory( ) -> URL { . init( filePath: FileManager . default. currentDirectoryPath, directoryHint: . isDirectory) }
170
+ }
171
+ #endif
0 commit comments