diff --git a/Sources/EvolutionMetadataExtraction/CommandLineSupport.swift b/Sources/EvolutionMetadataExtraction/CommandLineSupport.swift index 435e573..3ab73cd 100644 --- a/Sources/EvolutionMetadataExtraction/CommandLineSupport.swift +++ b/Sources/EvolutionMetadataExtraction/CommandLineSupport.swift @@ -128,7 +128,7 @@ public enum ArgumentValidation { for arg in forceExtract { if arg == "all" { forceAll = true - } else if arg.contains(/^SE-\d\d\d\d$/){ + } else if arg.contains(/^SE-\d{4}/){ forcedExtractionIDs.append(arg) } else { throw ValidationError("Valid --force-extraction values are 'all' and proposal ids of the form 'SE-NNNN'") diff --git a/Sources/EvolutionMetadataExtraction/ExtractionJob.swift b/Sources/EvolutionMetadataExtraction/ExtractionJob.swift index b1098b2..1e53323 100644 --- a/Sources/EvolutionMetadataExtraction/ExtractionJob.swift +++ b/Sources/EvolutionMetadataExtraction/ExtractionJob.swift @@ -178,8 +178,9 @@ extension ExtractionJob { return ExtractionJob(project: project, output: output, snapshot: snapshot, proposalSpecs: proposalSpecs, previousResults: nil, forcedExtractionIDs: forcedExtractionIDs, jobMetadata: jobMetadata) } - static func previousResults(from url: URL, ignorePreviousResults: Bool) async throws -> EvolutionMetadata? { + static func previousResults(from url: URL?, ignorePreviousResults: Bool) async throws -> EvolutionMetadata? { if ignorePreviousResults { return nil } + guard let url else { return nil } let data: Data? if url.isFileURL { diff --git a/Sources/EvolutionMetadataExtraction/Extractors/FieldExtractors/PreviousProposalExtractor.swift b/Sources/EvolutionMetadataExtraction/Extractors/FieldExtractors/PreviousProposalExtractor.swift index 7833cbd..07c9184 100644 --- a/Sources/EvolutionMetadataExtraction/Extractors/FieldExtractors/PreviousProposalExtractor.swift +++ b/Sources/EvolutionMetadataExtraction/Extractors/FieldExtractors/PreviousProposalExtractor.swift @@ -36,7 +36,7 @@ struct PreviousProposalExtractor: MarkupWalker, ValueExtractor { mutating func visitText(_ text: Text) -> () { // VALIDATION ENHANCEMENT: Potentially look for missing links or text that does not include a proposal ID - for match in text.string.matches(of: /SE-\d\d\d\d/) { + for match in text.string.matches(of: /SE-\d{4}/) { _previousProposalIDs.append(String(match.0)) } } diff --git a/Sources/EvolutionMetadataExtraction/Extractors/FieldExtractors/ProposalLinkExtractor.swift b/Sources/EvolutionMetadataExtraction/Extractors/FieldExtractors/ProposalLinkExtractor.swift index ac9070c..fb0c2a6 100644 --- a/Sources/EvolutionMetadataExtraction/Extractors/FieldExtractors/ProposalLinkExtractor.swift +++ b/Sources/EvolutionMetadataExtraction/Extractors/FieldExtractors/ProposalLinkExtractor.swift @@ -43,7 +43,7 @@ struct ProposalLinkExtractor: MarkupWalker, ValueExtractor { } // The link should be relative and contain the correct number of digits. - if !proposalLink.destination.contains(/^\d\d\d\d-.*\.md$/) { + if !proposalLink.destination.contains(/^\d{4}-.*\.md$/) { self.proposalLink?.destination = "" // Do not include an incorrect destination issues.reportIssue(Proposal.Issue.invalidProposalIDLink, source: source) } diff --git a/Sources/EvolutionMetadataExtraction/Utilities/Project.swift b/Sources/EvolutionMetadataExtraction/Utilities/Project.swift index 804cd2d..7c35ce8 100644 --- a/Sources/EvolutionMetadataExtraction/Utilities/Project.swift +++ b/Sources/EvolutionMetadataExtraction/Utilities/Project.swift @@ -22,14 +22,14 @@ public final class Project: Sendable { let path: String let proposalPrefix: String nonisolated(unsafe) let proposalRegex: Regex - let previousResultsURL: URL + let previousResultsURL: URL? let defaultOutputFilename: String private let endpointBaseURL: URL let mainBranchEndpoint: URL let proposalListingEndpoint: URL let validationExemptions: [Int:RangeSet] - private init(name: String, organization: String, repository: String, path: String, proposalPrefix: String, proposalRegex: Regex, previousResultsURL: URL, defaultOutputFilename: String, validationExemptions: [Int:RangeSet]) { + private init(name: String, organization: String, repository: String, path: String, proposalPrefix: String, proposalRegex: Regex, previousResultsURL: URL?, defaultOutputFilename: String, validationExemptions: [Int:RangeSet]) { self.name = name self.organization = organization self.repository = repository @@ -60,7 +60,7 @@ public final class Project: Sendable { repository: "swift-evolution", path: "proposals", proposalPrefix: "SE", - proposalRegex: /^SE-\d\d\d\d$/, + proposalRegex: /^SE-\d{4}$/, previousResultsURL: URL(string: "https://download.swift.org/swift-evolution/v1/evolution.json")!, defaultOutputFilename: "evolution.json", validationExemptions: [ @@ -90,8 +90,8 @@ public final class Project: Sendable { repository: "swift-evolution", path: "proposals/testing", proposalPrefix: "ST", - proposalRegex: /^ST-\d\d\d\d$/, - previousResultsURL: URL(string: "https://download.swift.org/swift-evolution/v1/testing-evolution.json")!, + proposalRegex: /^ST-\d{4}$/, + previousResultsURL: nil, // URL(string: "https://download.swift.org/swift-evolution/v1/testing-evolution.json")!, defaultOutputFilename: "testing-evolution.json", validationExemptions: [ // Early proposals did not have a review manager @@ -106,8 +106,8 @@ public final class Project: Sendable { repository: "swift-foundation", path: "Proposals", proposalPrefix: "SF", - proposalRegex: /^SF-\d\d\d\d$/, - previousResultsURL: URL(string: "https://download.swift.org/swift-evolution/v1/foundation-evolution.json")!, + proposalRegex: /^SF-\d{4}$/, + previousResultsURL: nil, // URL(string: "https://download.swift.org/swift-evolution/v1/foundation-evolution.json")!, defaultOutputFilename: "foundation-evolution.json", validationExemptions: [:] )