From fa28628cb99993fc39794b05b7cab23ade1c4bf0 Mon Sep 17 00:00:00 2001 From: Alex Deem Date: Thu, 27 Jul 2023 07:55:18 +1000 Subject: [PATCH] Also look for Package.resolved in .xcworkspace when performing version check (#3048) Co-authored-by: Zach FettersMoore <4425109+BobaFetters@users.noreply.github.com> --- .../Extensions/VersionChecker.swift | 70 +++++++++++++------ .../CodegenCLITests/VersionCheckerTests.swift | 59 ++++++++++++++++ 2 files changed, 107 insertions(+), 22 deletions(-) diff --git a/Sources/CodegenCLI/Extensions/VersionChecker.swift b/Sources/CodegenCLI/Extensions/VersionChecker.swift index d0894ad8e..731bece8d 100644 --- a/Sources/CodegenCLI/Extensions/VersionChecker.swift +++ b/Sources/CodegenCLI/Extensions/VersionChecker.swift @@ -40,14 +40,35 @@ enum VersionChecker { return fileManager.base.contents(atPath: path) } - // When using SPM via Xcode, the `Package.resolved` file is nested inside the `.xcproject` - // package. Since we don't know the name of your Xcode project, we just look for the first - // `.xcproject` file in project's root directory that depends on Apollo. This may not be - // 100% fool-proof, but it should be accurate in almost all cases. - func findInXcodeProject(named projectFileName: String) -> Data? { - let projectPackagePath = - "\(projectFileName)/project.xcworkspace/xcshareddata/swiftpm/\(Package_resolved)" - + // When using SPM via Xcode, the `Package.resolved` file is nested inside either the + // `.xcworkspace` or the `.xcproject` package. Since we don't know the name of your project, + // we just look for the first workspace or project that depends on Apollo, prioritising + // workspaces. This may not be 100% fool-proof, but it should be accurate in almost all cases. + func findInXcode( + fileSuffix: String, + packagePath: String, + excludeFilePathComponents: [String] = [] + ) -> PackageResolvedModel? { + let projectEnumerator = fileManager.base.enumerator(atPath: projectRootURL?.path ?? ".") + enumeratorLoop: while let file = projectEnumerator?.nextObject() as? String { + if file.hasSuffix(fileSuffix) { + //check if this file should be ignored + for component in excludeFilePathComponents { + if file.contains(component) { + continue enumeratorLoop + } + } + + let projectPackagePath = "\(file)\(packagePath)" + if let package = apolloDependantPackage(atPath: projectPackagePath) { + return package + } + } + } + return nil + } + + func apolloDependantPackage(atPath projectPackagePath: String) -> PackageResolvedModel? { let path: String if let projectRootURL { path = projectRootURL.appendingPathComponent(projectPackagePath, isDirectory: false).path @@ -55,27 +76,32 @@ enum VersionChecker { path = projectPackagePath } - return fileManager.base.contents(atPath: path) + if let packageResolvedData = fileManager.base.contents(atPath: path), + var packageModel = try? PackageResolvedModel(data: packageResolvedData), + packageModel.apolloVersion != nil { + return packageModel + } + return nil } if let packageResolvedData = findInProjectRoot() { return try PackageResolvedModel(data: packageResolvedData) + } - } else { - // Find in Xcode Projects - let projectEnumerator = fileManager.base.enumerator(atPath: projectRootURL?.path ?? ".") - - while let file = projectEnumerator?.nextObject() as? String { - if file.hasSuffix(".xcodeproj") { - if let packageResolvedData = findInXcodeProject(named: file), - var packageModel = try PackageResolvedModel(data: packageResolvedData), - packageModel.apolloVersion != nil { + if let packageModel = findInXcode( + fileSuffix: ".xcworkspace", + packagePath: "/xcshareddata/swiftpm/\(Package_resolved)", + excludeFilePathComponents: [".xcodeproj/project.xcworkspace"] + ) { + return packageModel + } - return packageModel - } - } - } + if let packageModel = findInXcode( + fileSuffix: ".xcodeproj", + packagePath: "/project.xcworkspace/xcshareddata/swiftpm/\(Package_resolved)" + ) { + return packageModel } return nil diff --git a/Tests/CodegenCLITests/VersionCheckerTests.swift b/Tests/CodegenCLITests/VersionCheckerTests.swift index 0810560aa..67198d1c8 100644 --- a/Tests/CodegenCLITests/VersionCheckerTests.swift +++ b/Tests/CodegenCLITests/VersionCheckerTests.swift @@ -186,6 +186,41 @@ class VersionCheckerTests: XCTestCase { expect(result).to(equal(.versionMismatch(cliVersion: Constants.CLIVersion, apolloVersion: apolloVersion))) } + func test__matchCLIVersionToApolloVersion__givenPackageResolvedFileInXcodeWorkspace_withVersion2FileFormat_hasMatchingVersion_returns_versionMatch() throws { + // given + try fileManager.createFile( + body: version2PackageResolvedFileBody(apolloVersion: Constants.CLIVersion), + named: "Package.resolved", + inDirectory: "MyProject.xcworkspace/xcshareddata/swiftpm" + ) + + // when + let result = try VersionChecker.matchCLIVersionToApolloVersion( + projectRootURL: fileManager.directoryURL + ) + + // then + expect(result).to(equal(.versionMatch)) + } + + func test__matchCLIVersionToApolloVersion__givenPackageResolvedFileInXcodeWorkspace_withVersion2FileFormat_hasNonMatchingVersion_returns_versionMismatch() throws { + // given + let apolloVersion = "1.0.0.test-1" + try fileManager.createFile( + body: version2PackageResolvedFileBody(apolloVersion: apolloVersion), + named: "Package.resolved", + inDirectory: "MyProject.xcworkspace/xcshareddata/swiftpm" + ) + + // when + let result = try VersionChecker.matchCLIVersionToApolloVersion( + projectRootURL: fileManager.directoryURL + ) + + // then + expect(result).to(equal(.versionMismatch(cliVersion: Constants.CLIVersion, apolloVersion: apolloVersion))) + } + func test__matchCLIVersionToApolloVersion__givenPackageResolvedFileInXcodeProject_withVersion2FileFormat_hasMatchingVersion_returns_versionMatch() throws { // given try fileManager.createFile( @@ -220,6 +255,30 @@ class VersionCheckerTests: XCTestCase { // then expect(result).to(equal(.versionMismatch(cliVersion: Constants.CLIVersion, apolloVersion: apolloVersion))) } + + func test__matchCLIVersionToApolloVersion__givenPackageResolvedFileInXcodeWorkspaceAndProject_withVersion2FileFormat_hasMatchingVersion_returns_versionMatch_fromWorkspace() throws { + // given + try fileManager.createFile( + body: version2PackageResolvedFileBody(apolloVersion: Constants.CLIVersion), + named: "Package.resolved", + inDirectory: "MyProject.xcworkspace/xcshareddata/swiftpm" + ) + + let apolloProjectVersion = "1.0.0.test-1" + try fileManager.createFile( + body: version2PackageResolvedFileBody(apolloVersion: apolloProjectVersion), + named: "Package.resolved", + inDirectory: "MyProject.xcodeproj/project.xcworkspace/xcshareddata/swiftpm" + ) + + // when + let result = try VersionChecker.matchCLIVersionToApolloVersion( + projectRootURL: fileManager.directoryURL + ) + + // then + expect(result).to(equal(.versionMatch)) + } }