Skip to content

Commit 60a271c

Browse files
committed
Add check that either all archives support static hosting or none do
1 parent b08c28a commit 60a271c

File tree

2 files changed

+156
-7
lines changed

2 files changed

+156
-7
lines changed

Sources/SwiftDocCUtilities/Action/Actions/MergeAction.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct MergeAction: Action {
2626

2727
try validateThatOutputIsEmpty()
2828
try validateThatArchivesHaveDisjointData()
29+
try validateThatAllArchivesOrNoArchivesSupportStaticHosting()
2930

3031
let targetURL = try Self.createUniqueDirectory(inside: fileManager.uniqueTemporaryDirectory(), template: firstArchive, fileManager: fileManager)
3132
defer {
@@ -159,4 +160,38 @@ struct MergeAction: Action {
159160
throw NonEmptyOutputError(existingContents: existingContents, fileManager: fileManager)
160161
}
161162
}
163+
164+
private func validateThatAllArchivesOrNoArchivesSupportStaticHosting() throws {
165+
let nonEmptyArchives = archives.filter {
166+
fileManager.directoryExists(atPath: $0.appendingPathComponent("data").path)
167+
}
168+
169+
let archivesWithStaticHostingSupport = nonEmptyArchives.filter {
170+
return fileManager.directoryExists(atPath: $0.appendingPathComponent("documentation").path)
171+
|| fileManager.directoryExists(atPath: $0.appendingPathComponent("tutorials").path)
172+
}
173+
174+
guard archivesWithStaticHostingSupport.count == nonEmptyArchives.count else {
175+
struct DifferentStaticHostingSupportError: DescribedError {
176+
var withSupport: Set<String>
177+
var withoutSupport: Set<String>
178+
179+
var errorDescription: String {
180+
"""
181+
Different static hosting support in different archives.
182+
183+
\(withSupport.sorted().joined(separator: ", ")) support\(withSupport.count == 1 ? "s" : "") static hosting \
184+
but \(withoutSupport.sorted().joined(separator: ", ")) do\(withoutSupport.count == 1 ? "es" : "")n't.
185+
"""
186+
}
187+
}
188+
let allArchiveNames = Set(nonEmptyArchives.map(\.lastPathComponent))
189+
let archiveNamesWithStaticHostingSupport = Set(archivesWithStaticHostingSupport.map(\.lastPathComponent))
190+
191+
throw DifferentStaticHostingSupportError(
192+
withSupport: archiveNamesWithStaticHostingSupport,
193+
withoutSupport: allArchiveNames.subtracting(archiveNamesWithStaticHostingSupport)
194+
)
195+
}
196+
}
162197
}

Tests/SwiftDocCUtilitiesTests/MergeActionTests.swift

Lines changed: 121 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,63 @@ class MergeActionTests: XCTestCase {
333333
XCTAssertEqual(logStorage.text, "", "The action didn't log anything")
334334
}
335335

336+
func testErrorWhenSomeArchivesDoNotSupportStaticHosting() throws {
337+
let fileSystem = try TestFileSystem(folders: [
338+
Self.makeArchive(
339+
name: "First",
340+
documentationPages: [
341+
"First",
342+
"First/SomeClass",
343+
"First/SomeClass/someProperty",
344+
"First/SomeClass/someFunction(:_)",
345+
],
346+
tutorialPages: [
347+
"First",
348+
"First/SomeTutorial",
349+
],
350+
images: ["something.png"],
351+
videos: ["something.mov"],
352+
downloads: ["something.zip"]
353+
),
354+
Self.makeArchive(
355+
name: "Second",
356+
documentationPages: [
357+
"Second",
358+
"Second/SomeStruct",
359+
"Second/SomeStruct/someProperty",
360+
"Second/SomeStruct/someFunction(:_)",
361+
],
362+
tutorialPages: [
363+
"Second",
364+
"Second/SomeTutorial",
365+
],
366+
images: ["something.png"],
367+
videos: ["something.mov"],
368+
downloads: ["something.zip"],
369+
supportsStaticHosting: false
370+
),
371+
])
372+
373+
let logStorage = LogHandle.LogStorage()
374+
var action = MergeAction(
375+
archives: [
376+
URL(fileURLWithPath: "/First.doccarchive"),
377+
URL(fileURLWithPath: "/Second.doccarchive"),
378+
],
379+
outputURL: URL(fileURLWithPath: "/Output.doccarchive"),
380+
fileManager: fileSystem
381+
)
382+
383+
XCTAssertThrowsError(try action.perform(logHandle: LogHandle.memory(logStorage))) { error in
384+
XCTAssertEqual(error.localizedDescription, """
385+
Different static hosting support in different archives.
386+
387+
First.doccarchive supports static hosting but Second.doccarchive doesn't.
388+
""")
389+
}
390+
XCTAssertEqual(logStorage.text, "", "The action didn't log anything")
391+
}
392+
336393
// MARK: Test helpers
337394

338395
func testMakeArchive() throws {
@@ -420,6 +477,58 @@ class MergeActionTests: XCTestCase {
420477
╰─ com.example.something/
421478
╰─ some-video.mov
422479
""")
480+
481+
XCTAssertEqual(Self.makeArchive(
482+
name: "Something",
483+
documentationPages: [
484+
"Something",
485+
"Something/SomeClass",
486+
"Something/SomeClass/someProperty",
487+
"Something/SomeClass/someFunction(:_)",
488+
],
489+
tutorialPages: [
490+
"Something",
491+
"Something/SomeTutorial",
492+
],
493+
images: ["first-image.png", "second-image.png"],
494+
videos: ["some-video.mov"],
495+
downloads: ["some-download.zip"],
496+
supportsStaticHosting: false
497+
).dump(), """
498+
Something.doccarchive/
499+
├─ css/
500+
│ ╰─ something.css
501+
├─ data/
502+
│ ├─ documentation/
503+
│ │ ├─ something.json
504+
│ │ ╰─ something/
505+
│ │ ├─ someclass.json
506+
│ │ ╰─ someclass/
507+
│ │ ├─ somefunction(:_).json
508+
│ │ ╰─ someproperty.json
509+
│ ╰─ tutorials/
510+
│ ├─ something.json
511+
│ ╰─ something/
512+
│ ╰─ sometutorial.json
513+
├─ downloads/
514+
│ ╰─ com.example.something/
515+
│ ╰─ some-download.zip
516+
├─ favicon.svg
517+
├─ images/
518+
│ ╰─ com.example.something/
519+
│ ├─ first-image.png
520+
│ ╰─ second-image.png
521+
├─ img/
522+
│ ╰─ something.svg
523+
├─ index/
524+
│ ╰─ index.json
525+
├─ js/
526+
│ ╰─ something.js
527+
├─ metadata.json
528+
╰─ videos/
529+
╰─ com.example.something/
530+
╰─ some-video.mov
531+
""")
423532
}
424533

425534
static func makeArchive(
@@ -428,7 +537,8 @@ class MergeActionTests: XCTestCase {
428537
tutorialPages: [String],
429538
images: [String] = [],
430539
videos: [String] = [],
431-
downloads: [String] = []
540+
downloads: [String] = [],
541+
supportsStaticHosting: Bool = true
432542
) -> Folder {
433543
let identifier = "com.example.\(name.lowercased())"
434544

@@ -449,17 +559,21 @@ class MergeActionTests: XCTestCase {
449559
// Content
450560
var dataContent: [File] = []
451561
if !documentationPages.isEmpty {
452-
content += [
453-
Folder(name: "documentation", content: Folder.makeStructure(filePaths: documentationPages.map { "\($0.lowercased())/index.html" })),
454-
]
562+
if supportsStaticHosting {
563+
content += [
564+
Folder(name: "documentation", content: Folder.makeStructure(filePaths: documentationPages.map { "\($0.lowercased())/index.html" })),
565+
]
566+
}
455567
dataContent += [
456568
Folder(name: "documentation", content: Folder.makeStructure(filePaths: documentationPages.map { "\($0.lowercased()).json" })),
457569
]
458570
}
459571
if !tutorialPages.isEmpty {
460-
content += [
461-
Folder(name: "tutorials", content: Folder.makeStructure(filePaths: tutorialPages.map { "\($0.lowercased())/index.html" })),
462-
]
572+
if supportsStaticHosting {
573+
content += [
574+
Folder(name: "tutorials", content: Folder.makeStructure(filePaths: tutorialPages.map { "\($0.lowercased())/index.html" })),
575+
]
576+
}
463577
dataContent += [
464578
Folder(name: "tutorials", content: Folder.makeStructure(filePaths: tutorialPages.map { "\($0.lowercased()).json" })),
465579
]

0 commit comments

Comments
 (0)