From 8068cc3ee9326bf92060e8ac83d4c6831b484097 Mon Sep 17 00:00:00 2001 From: John Sundell Date: Sat, 29 Apr 2017 22:39:52 +0200 Subject: [PATCH] PackageManager: Fix bug preventing certain package descriptions from being parsed This patch fixes a bug that prevented `PackageManager` from parsing certain package description files, since it made too many assumptions about its format. The new parsing code is simpler, and a lot more robust, by scanning the package description line-by-line until it finds a name definition. --- Sources/MarathonCore/PackageManager.swift | 24 ++++++++++++--------- Tests/MarathonTests/MarathonTests.swift | 26 +++++++++++++++++++++++ 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/Sources/MarathonCore/PackageManager.swift b/Sources/MarathonCore/PackageManager.swift index d3ca82b..9866c13 100644 --- a/Sources/MarathonCore/PackageManager.swift +++ b/Sources/MarathonCore/PackageManager.swift @@ -233,21 +233,25 @@ internal final class PackageManager { private func nameOfPackage(in folder: Folder) throws -> String { let packageFile = try folder.file(named: "Package.swift") - var packageDescription = try packageFile.readAsString() - guard let nameStartRange = packageDescription.range(of: "name:") else { - throw Error.failedToReadPackageFile(packageFile.nameExcludingExtension) - } + for line in try packageFile.readAsString().components(separatedBy: .newlines) { + guard let nameTokenRange = line.range(of: "name:") else { + continue + } - packageDescription = packageDescription.substring(from: nameStartRange.upperBound) + var line = line.substring(from: nameTokenRange.upperBound) + + if let range = line.range(of: ",") { + line = line.substring(to: range.lowerBound) + } else if let range = line.range(of: ")") { + line = line.substring(to: range.lowerBound) + } - guard let delimiterRange = packageDescription.range(of: ",") ?? packageDescription.range(of: ")") else { - throw Error.failedToReadPackageFile(packageFile.nameExcludingExtension) + line = line.trimmingCharacters(in: .whitespacesAndNewlines) + return line.replacingOccurrences(of: "\"", with: "") } - packageDescription = packageDescription.substring(to: delimiterRange.lowerBound) - packageDescription = packageDescription.trimmingCharacters(in: .whitespacesAndNewlines) - return packageDescription.replacingOccurrences(of: "\"", with: "") + throw Error.failedToReadPackageFile(packageFile.name) } private func nameOfRemotePackage(at url: URL) throws -> String { diff --git a/Tests/MarathonTests/MarathonTests.swift b/Tests/MarathonTests/MarathonTests.swift index c160ecf..a46623f 100644 --- a/Tests/MarathonTests/MarathonTests.swift +++ b/Tests/MarathonTests/MarathonTests.swift @@ -106,6 +106,32 @@ class MarathonTests: XCTestCase { try XCTAssertEqual(folder.subfolder(named: "Packages").files.count, 0) } + func testAddingLocalPackage() throws { + let packageFolder = try folder.createSubfolder(named: "TestPackage") + try packageFolder.moveToAndPerform(command: "swift package init") + + let packageDescription = "import PackageDescription\n" + + "let package = Package(name: \"TestPackage\")" + + let packageFile = try packageFolder.file(named: "Package.swift") + try packageFile.write(string: packageDescription) + + let gitCommand = "git init && git add . && git commit -a -m \"Commit\" && git tag 0.1.0" + try packageFolder.moveToAndPerform(command: gitCommand) + + try run(with: ["add", "TestPackage"]) + XCTAssertNotNil(try? folder.subfolder(named: "Packages").file(named: "TestPackage").read()) + + let generatedFolder = try folder.subfolder(atPath: "Packages/Generated") + + let generatedPackageFile = try generatedFolder.file(named: "Package.swift") + try XCTAssertTrue(generatedPackageFile.readAsString().contains(packageFolder.path)) + + let packageNames = try generatedFolder.subfolder(atPath: ".build/checkouts").subfolders.names + XCTAssertEqual(packageNames.count, 1) + XCTAssertTrue(packageNames.contains { $0.hasPrefix("TestPackage-") }) + } + func testAddingLocalPackageWithDependency() throws { let packageFolder = try folder.createSubfolder(named: "TestPackage") try packageFolder.moveToAndPerform(command: "swift package init")