Preserve provider for accepted source candidates

This commit is contained in:
John Burwell 2026-06-02 16:41:34 -05:00
parent ca21654b44
commit ffb6e497ec
2 changed files with 81 additions and 1 deletions

View File

@ -229,7 +229,45 @@ final class SourceLibrary: ObservableObject, SourceScanSessionHosting, SourcePer
}
func addSource(candidate: SourceCandidate) async -> URL {
await addSource(at: candidate.sourceRootURL)
let normalizedURL = candidate.sourceRootURL.standardizedFileURL
let bookmarkData = securityScopedBookmarkData(for: normalizedURL)
if sources.contains(where: { $0.id == normalizedURL }) {
updateSource(normalizedURL) { source in
if source.bookmarkData == nil {
source.bookmarkData = bookmarkData
}
source.accessDescriptor = SourceAccessDescriptor(
accessorIdentifier: candidate.providerID,
kind: .localFolder,
refreshStrategy: .eagerFullScan
)
source.providerID = candidate.providerID
source.edition = candidate.edition
source.displayName = candidate.displayName
source.capabilities = source.origin.defaultCapabilities
}
sourceCandidates.removeAll { $0.id == candidate.id || $0.sourceRootURL == normalizedURL }
startScan(for: normalizedURL, mode: .fullScan)
return normalizedURL
}
var source = MinecraftSource(
folderURL: normalizedURL,
bookmarkData: bookmarkData,
accessDescriptor: SourceAccessDescriptor(
accessorIdentifier: candidate.providerID,
kind: .localFolder,
refreshStrategy: .eagerFullScan
)
)
source.providerID = candidate.providerID
source.edition = candidate.edition
source.displayName = candidate.displayName
let sourceID = addSource(source, shouldPersist: true, shouldScan: true)
sourceCandidates.removeAll { $0.id == candidate.id || $0.sourceRootURL == sourceID }
return sourceID
}
@discardableResult

View File

@ -413,6 +413,48 @@ struct World_Manager_for_MinecraftTests {
#expect(snapshots.map(\.folderName).contains("a/e/f/resourcepacks"))
}
@Test func sourceLibraryAddSourceCandidatePreservesJavaAggregateProvider() async throws {
let fileManager = FileManager.default
let workingURL = fileManager.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)
let instanceURL = workingURL.appendingPathComponent("a/b/c", isDirectory: true)
let modURL = instanceURL.appendingPathComponent("mods/ExampleMod.jar")
defer { try? fileManager.removeItem(at: workingURL) }
try fileManager.createDirectory(at: modURL.deletingLastPathComponent(), withIntermediateDirectories: true)
try Data("jar".utf8).write(to: modURL)
let candidate = SourceCandidate(
providerID: JavaLocalFolderSourceAccess().accessorIdentifier,
edition: .java,
sourceRootURL: workingURL,
displayName: workingURL.lastPathComponent,
confidence: .strong,
reason: "Found multiple Java sources",
detectedKinds: [.mod]
)
let access = SourceAccessCoordinator(
accessMethods: [
LocalFolderSourceAccess(),
JavaLocalFolderSourceAccess()
]
)
let library = SourceLibrary(sourceAccessMethod: access)
let sourceID = await library.addSource(candidate: candidate)
guard let source = library.source(withID: sourceID) else {
Issue.record("Expected added source")
return
}
#expect(source.folderURL == workingURL.standardizedFileURL)
#expect(source.edition == .java)
#expect(source.providerID == JavaLocalFolderSourceAccess().accessorIdentifier)
#expect(source.accessDescriptor.accessorIdentifier == JavaLocalFolderSourceAccess().accessorIdentifier)
let items = try JavaContentScanner.discoverItems(in: source.folderURL)
#expect(items.contains { $0.contentKind == .mod && $0.folderName == "ExampleMod.jar" })
}
@Test func sourceLibraryAddSourceResolvesJavaWrapperFolder() async throws {
let fileManager = FileManager.default
let rootURL = fileManager.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)