From 208a4300663533b057bc93e0373bb297f8f14026 Mon Sep 17 00:00:00 2001 From: Nico Verbruggen Date: Sun, 5 Feb 2023 13:16:04 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8F=97=20Parse=20CaskFile=20using=20regex?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- phpmon/Domain/App/AppUpdater.swift | 4 ++ .../DomainList/Cells/DomainListPhpCell.swift | 3 +- .../Integrations/Homebrew/CaskFile.swift | 38 ++++++++++++++++--- tests/unit/Parsers/CaskFileParserTest.swift | 28 ++++++++------ 4 files changed, 54 insertions(+), 19 deletions(-) diff --git a/phpmon/Domain/App/AppUpdater.swift b/phpmon/Domain/App/AppUpdater.swift index dfc25ea..a214c42 100644 --- a/phpmon/Domain/App/AppUpdater.swift +++ b/phpmon/Domain/App/AppUpdater.swift @@ -48,4 +48,8 @@ class AppUpdater { public func presentCouldNotRetrieveUpdate() { } + + private func prepareForDownload() { + + } } diff --git a/phpmon/Domain/DomainList/Cells/DomainListPhpCell.swift b/phpmon/Domain/DomainList/Cells/DomainListPhpCell.swift index 5ee78f5..a875ed6 100644 --- a/phpmon/Domain/DomainList/Cells/DomainListPhpCell.swift +++ b/phpmon/Domain/DomainList/Cells/DomainListPhpCell.swift @@ -37,7 +37,8 @@ class DomainListPhpCell: NSTableCellView, DomainListCellProtocol { imageViewPhpVersionOK.image = NSImage(named: "Isolated") imageViewPhpVersionOK.toolTip = "domain_list.tooltips.isolated".localized(site.servingPhpVersion) } else { - imageViewPhpVersionOK.isHidden = (site.preferredPhpVersion == "???" || !site.isCompatibleWithPreferredPhpVersion) + imageViewPhpVersionOK.isHidden = (site.preferredPhpVersion == "???" + || !site.isCompatibleWithPreferredPhpVersion) imageViewPhpVersionOK.image = NSImage(named: "Checkmark") imageViewPhpVersionOK.toolTip = "domain_list.tooltips.checkmark".localized(site.preferredPhpVersion) diff --git a/phpmon/Domain/Integrations/Homebrew/CaskFile.swift b/phpmon/Domain/Integrations/Homebrew/CaskFile.swift index b2db7f7..c3f916d 100644 --- a/phpmon/Domain/Integrations/Homebrew/CaskFile.swift +++ b/phpmon/Domain/Integrations/Homebrew/CaskFile.swift @@ -11,10 +11,24 @@ import Foundation struct CaskFile { var properties: [String: String] + var name: String { + return self.properties["name"]! + } + var url: String { + return self.properties["url"]! + } + var sha256: String { + return self.properties["sha256"]! + } + var version: String { + return self.properties["version"]! + } + public static func from(url: URL) -> CaskFile? { let string = try? String(contentsOf: url) guard let string else { + Log.err("The content of the URL for the CaskFile could not be retrieved") return nil } @@ -22,25 +36,37 @@ struct CaskFile { .filter { $0 != "" } if lines.count < 4 { + Log.err("The CaskFile is <4 lines long, which is too short") return nil } if !lines.first!.starts(with: "cask") || !lines.last!.starts(with: "end") { + Log.err("The CaskFile does not start with 'cask' or does not end with 'end'") return nil } var props: [String: String] = [:] - lines.forEach { line in - let text = line.trimmingCharacters(in: .whitespacesAndNewlines) - let parts = text.split(separator: " ") + let regex = try! NSRegularExpression(pattern: "(\\w+)\\s+'([^']+)'") - if parts.count == 2 { - props[String(parts[0])] = String(parts[1]) - .replacingOccurrences(of: "\'", with: "") + for line in lines { + if let match = regex.firstMatch( + in: String(line), + range: NSRange(location: 0, length: line.utf16.count) + ) { + let keyRange = match.range(at: 1) + let valueRange = match.range(at: 2) + let key = (line as NSString).substring(with: keyRange) + let value = (line as NSString).substring(with: valueRange) + props[key] = value } } + for required in ["version", "sha256", "url", "name"] where !props.keys.contains(required) { + Log.err("Property '\(required)' expected on CaskFile, assuming CaskFile is invalid") + return nil + } + return CaskFile(properties: props) } diff --git a/tests/unit/Parsers/CaskFileParserTest.swift b/tests/unit/Parsers/CaskFileParserTest.swift index 8cc661b..314c473 100644 --- a/tests/unit/Parsers/CaskFileParserTest.swift +++ b/tests/unit/Parsers/CaskFileParserTest.swift @@ -17,32 +17,36 @@ class CaskFileParserTest: XCTestCase { } func test_can_extract_fields_from_cask_file() throws { - let caskFile = CaskFile.from(url: CaskFileParserTest.exampleFilePath) + guard let caskFile = CaskFile.from(url: CaskFileParserTest.exampleFilePath) else { + return XCTFail("The CaskFile could not be parsed, check the log for more info") + } XCTAssertEqual( - caskFile!.properties["version"], + caskFile.version, "5.7.2_1035" ) XCTAssertEqual( - caskFile!.properties["homepage"], - "https://phpmon.app" + caskFile.sha256, + "1cb147bd1b1fbd52971d90dff577465b644aee7c878f15ede57f46e8f217067a" ) XCTAssertEqual( - caskFile!.properties["appcast"], - "https://github.com/nicoverbruggen/phpmon/releases.atom" + caskFile.name, + "PHP Monitor DEV" ) XCTAssertEqual( - caskFile!.properties["url"], + caskFile.url, "https://github.com/nicoverbruggen/phpmon/releases/download/v5.7.2/phpmon-dev.zip" ) } func test_can_extract_fields_from_remote_cask_file() throws { - let caskFile = CaskFile.from(url: Constants.Urls.StableBuildCaskFile) + guard let caskFile = CaskFile.from(url: Constants.Urls.StableBuildCaskFile) else { + return XCTFail("The remote CaskFile could not be parsed, check the log for more info") + } - XCTAssertTrue(caskFile!.properties.keys.contains("version")) - XCTAssertTrue(caskFile!.properties.keys.contains("homepage")) - XCTAssertTrue(caskFile!.properties.keys.contains("url")) - XCTAssertTrue(caskFile!.properties.keys.contains("appcast")) + XCTAssertTrue(caskFile.properties.keys.contains("version")) + XCTAssertTrue(caskFile.properties.keys.contains("homepage")) + XCTAssertTrue(caskFile.properties.keys.contains("url")) + XCTAssertTrue(caskFile.properties.keys.contains("appcast")) } }