Skip to content

Commit

Permalink
add and internally test convenience methods to access the script dire…
Browse files Browse the repository at this point in the history
…ctory for supported package managers
  • Loading branch information
designatednerd committed Dec 19, 2019
1 parent 63540aa commit a1dca7c
Show file tree
Hide file tree
Showing 8 changed files with 269 additions and 9 deletions.
26 changes: 24 additions & 2 deletions Apollo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
9B7B6F59233C287200F32205 /* ApolloCodegen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B7B6F57233C287100F32205 /* ApolloCodegen.swift */; };
9B7B6F5A233C287200F32205 /* ApolloCodegenOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B7B6F58233C287100F32205 /* ApolloCodegenOptions.swift */; };
9B7B6F69233C2C0C00F32205 /* FileManager+Apollo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B7B6F68233C2C0C00F32205 /* FileManager+Apollo.swift */; };
9B8110A323A18B3500688AC4 /* PackageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B8110A223A18B3500688AC4 /* PackageManager.swift */; };
9B8110A923A19B6F00688AC4 /* ScriptDiectoryFinderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B8110A823A19B6F00688AC4 /* ScriptDiectoryFinderTests.swift */; };
9B8110AA23A19DC500688AC4 /* ScriptDirectoryFinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B8110A023A18A3700688AC4 /* ScriptDirectoryFinder.swift */; };
9B95EDC022CAA0B000702BB2 /* GETTransformerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B95EDBF22CAA0AF00702BB2 /* GETTransformerTests.swift */; };
9BA1244A22D8A8EA00BF1D24 /* JSONSerialziation+Sorting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA1244922D8A8EA00BF1D24 /* JSONSerialziation+Sorting.swift */; };
9BA1245E22DE116B00BF1D24 /* Result+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA1245D22DE116B00BF1D24 /* Result+Helpers.swift */; };
Expand Down Expand Up @@ -337,6 +340,10 @@
9B7B6F58233C287100F32205 /* ApolloCodegenOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApolloCodegenOptions.swift; sourceTree = "<group>"; };
9B7B6F60233C299E00F32205 /* ApolloCodegen */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ApolloCodegen; sourceTree = BUILT_PRODUCTS_DIR; };
9B7B6F68233C2C0C00F32205 /* FileManager+Apollo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileManager+Apollo.swift"; sourceTree = "<group>"; };
9B8110A023A18A3700688AC4 /* ScriptDirectoryFinder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptDirectoryFinder.swift; sourceTree = "<group>"; };
9B8110A223A18B3500688AC4 /* PackageManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PackageManager.swift; sourceTree = "<group>"; };
9B8110A723A1995D00688AC4 /* .keep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .keep; sourceTree = "<group>"; };
9B8110A823A19B6F00688AC4 /* ScriptDiectoryFinderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScriptDiectoryFinderTests.swift; sourceTree = "<group>"; };
9B8D864E22E7A846001F6D50 /* RepoURL.graphql */ = {isa = PBXFileReference; lastKnownFileType = text; path = RepoURL.graphql; sourceTree = "<group>"; };
9B95EDBF22CAA0AF00702BB2 /* GETTransformerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GETTransformerTests.swift; sourceTree = "<group>"; };
9BA1244922D8A8EA00BF1D24 /* JSONSerialziation+Sorting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSONSerialziation+Sorting.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -610,10 +617,12 @@
9BAEEBED2346644600808306 /* ApolloSchemaOptions.swift */,
9B518C8A235F8B05004C426D /* ApolloFilePathHelper.swift */,
9BC2D9D1233C6DC0007BD083 /* Basher.swift */,
9B518C85235F8125004C426D /* CLIDownloader.swift */,
9B8110A023A18A3700688AC4 /* ScriptDirectoryFinder.swift */,
9BAEEBF42346E90700808306 /* CLIExtractor.swift */,
9B518C85235F8125004C426D /* CLIDownloader.swift */,
9BAEEBF22346DDAD00808306 /* CodegenLogger.swift */,
9B7B6F68233C2C0C00F32205 /* FileManager+Apollo.swift */,
9B8110A223A18B3500688AC4 /* PackageManager.swift */,
9BAEEBF62346F0A000808306 /* StaticString+Apollo.swift */,
9B7B6F51233C26E400F32205 /* Info.plist */,
);
Expand All @@ -629,6 +638,14 @@
path = ApolloCodegen;
sourceTree = "<group>";
};
9B8110A623A1994000688AC4 /* SourcePackages */ = {
isa = PBXGroup;
children = (
9B8110A723A1995D00688AC4 /* .keep */,
);
path = SourcePackages;
sourceTree = "<group>";
};
9B8D864A22E7A60C001F6D50 /* TestFolder */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -672,12 +689,14 @@
9BAEEC0A234BB95B00808306 /* ApolloCodegenTests */ = {
isa = PBXGroup;
children = (
9B8110A623A1994000688AC4 /* SourcePackages */,
9BAEEC11234BBA9200808306 /* CodegenTestHelper.swift */,
9BAEEC16234C275600808306 /* ApolloSchemaTests.swift */,
9BAEEC18234C297800808306 /* ApolloCodegenTests.swift */,
9BAEEC14234C132600808306 /* CLIExtractorTests.swift */,
9B518C88235F8AD4004C426D /* CLIDownloaderTests.swift */,
9BAEEC14234C132600808306 /* CLIExtractorTests.swift */,
9BAEEC0D234BB95B00808306 /* FileManagerExtensionsTests.swift */,
9B8110A823A19B6F00688AC4 /* ScriptDiectoryFinderTests.swift */,
9BAEEC0C234BB95B00808306 /* Info.plist */,
);
path = ApolloCodegenTests;
Expand Down Expand Up @@ -1444,13 +1463,15 @@
9BC2D9D3233C6EF0007BD083 /* Basher.swift in Sources */,
9BAEEBEF2346644B00808306 /* ApolloSchemaDownloader.swift in Sources */,
9BAEEBF72346F0A000808306 /* StaticString+Apollo.swift in Sources */,
9B8110A323A18B3500688AC4 /* PackageManager.swift in Sources */,
9BAEEBF32346DDAD00808306 /* CodegenLogger.swift in Sources */,
9B518C8C235F8B5F004C426D /* ApolloFilePathHelper.swift in Sources */,
9B518C87235F819E004C426D /* CLIDownloader.swift in Sources */,
9BAEEBF123467E0A00808306 /* ApolloCLI.swift in Sources */,
9B7B6F69233C2C0C00F32205 /* FileManager+Apollo.swift in Sources */,
9B7B6F59233C287200F32205 /* ApolloCodegen.swift in Sources */,
9B7B6F5A233C287200F32205 /* ApolloCodegenOptions.swift in Sources */,
9B8110AA23A19DC500688AC4 /* ScriptDirectoryFinder.swift in Sources */,
9BAEEBF52346E90700808306 /* CLIExtractor.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -1471,6 +1492,7 @@
9BAEEC17234C275600808306 /* ApolloSchemaTests.swift in Sources */,
9BAEEC12234BBA9200808306 /* CodegenTestHelper.swift in Sources */,
9B518C8D235F8B9E004C426D /* CLIDownloaderTests.swift in Sources */,
9B8110A923A19B6F00688AC4 /* ScriptDiectoryFinderTests.swift in Sources */,
9BAEEC15234C132600808306 /* CLIExtractorTests.swift in Sources */,
9BAEEC19234C297800808306 /* ApolloCodegenTests.swift in Sources */,
);
Expand Down
10 changes: 6 additions & 4 deletions Sources/ApolloCodegen/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import ApolloCodegenLib
enum MyCodegenError: Error {
case sourceRootNotProvided
case sourceRootNotADirectory
case doesntExist
case targetDoesntExist
}

guard let sourceRootPath = ProcessInfo.processInfo.environment["SRCROOT"] else {
Expand All @@ -19,18 +19,20 @@ guard FileManager.default.apollo_folderExists(at: sourceRootPath) else {

let sourceRootURL = URL(fileURLWithPath: sourceRootPath)

let starWarsTarget = sourceRootURL.appendingPathComponent("Tests").appendingPathComponent("StarWarsAPI")
let starWarsTarget = sourceRootURL
.appendingPathComponent("Tests")
.appendingPathComponent("StarWarsAPI")

guard FileManager.default.apollo_folderExists(at: starWarsTarget) else {
throw MyCodegenError.doesntExist
throw MyCodegenError.targetDoesntExist
}

let scriptFolderURL = sourceRootURL.appendingPathComponent("scripts")
let options = ApolloCodegenOptions(targetRootURL: starWarsTarget)

do {
let result = try ApolloCodegen.run(from: starWarsTarget,
scriptFolderURL: scriptFolderURL,
with: .custom(scriptsFolderURL: scriptFolderURL),
options: options)
print("RESULT: \(result)")
} catch {
Expand Down
5 changes: 4 additions & 1 deletion Sources/ApolloCodegenLib/ApolloCodegen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public class ApolloCodegen {
/// - Parameter scriptFolderURL: The folder where the Apollo scripts have been checked out.
/// - Parameter options: The options object to use to run the code generation.
public static func run(from folder: URL,
scriptFolderURL: URL,
environment: [String: String] = ProcessInfo.processInfo.environment,
with packageManager: PackageManager,
options: ApolloCodegenOptions) throws -> String {
guard FileManager.default.apollo_folderExists(at: folder) else {
throw ApolloCodegenError.folderDoesNotExist(folder)
Expand All @@ -42,6 +43,8 @@ public class ApolloCodegen {
try FileManager.default.apollo_createContainingFolderIfNeeded(for: fileURL)
}

let scriptFolderURL = try ScriptDirectoryFinder.findScriptsFolder(for: packageManager, in: environment)

let cli = try ApolloCLI.createCLI(scriptsFolderURL: scriptFolderURL)
return try cli.runApollo(with: options.arguments, from: folder)
}
Expand Down
19 changes: 19 additions & 0 deletions Sources/ApolloCodegenLib/PackageManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// PackageManager.swift
// ApolloCodegenLib
//
// Created by Ellen Shapiro on 12/11/19.
// Copyright © 2019 Apollo GraphQL. All rights reserved.
//

import Foundation

/// How are you integrating the Apollo library?
public enum PackageManager {
case swiftPackageManager
case cocoaPods
case carthage

/// - parameter scriptsFolderURL: The direct URL to the checked out `apollo-ios/scripts` folder.
case custom(scriptsFolderURL: URL)
}
101 changes: 101 additions & 0 deletions Sources/ApolloCodegenLib/ScriptDirectoryFinder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//
// ScriptDirectoryFinder.swift
// ApolloCodegenLib
//
// Created by Ellen Shapiro on 12/11/19.
// Copyright © 2019 Apollo GraphQL. All rights reserved.
//

import Foundation

struct ScriptDirectoryFinder {

enum FindError: Error, LocalizedError {
/// SPM-related
case noBuildRootEnvironmentVariable
case couldNotFindSourcePackagesDirectory(buildRoot: String)

/// CocoaPods-related
case noPodsRootEnvironmentVariable

/// Carthage-related
case noSourceRootEnvironmentVariable

var errorDescription: String? {
switch self {
case .noBuildRootEnvironmentVariable:
return "Could not find the `BUILD_ROOT` environment variable. Please ensure this is provided and that you are using Swift Package Manager to install Apollo."
case .couldNotFindSourcePackagesDirectory(let buildRoot):
return "Unable to locate SourcePackages directory from `BUILD_ROOT`: '\(buildRoot)', ensure that the apollo-ios SDK has finished installing with Swift Package Manager."
case .noPodsRootEnvironmentVariable:
return "Could not find the `PODS_ROOT` environment variable. Please ensure this is provided and that you are using CocoaPods to install Apollo."
case .noSourceRootEnvironmentVariable:
return "Could not find the `SOURCE_ROOT` environment variable. Please ensure this is provided and "
}
}
}

static func findScriptsFolder(for packageManager: PackageManager,
in environment: [String: String]) throws -> URL {
switch packageManager {
case .swiftPackageManager:
return try self.findScriptsFolderForSPM(in: environment)
case .cocoaPods:
return try self.findScriptsFolderForCocoaPods(in: environment)
case .carthage:
return try self.findScriptsFolderForCarthage(in: environment)
case .custom(let urlToScriptsFolder):
return urlToScriptsFolder
}
}

private static func findScriptsFolderForSPM(in environment: [String: String]) throws -> URL {
guard let buildRootPath = environment["BUILD_ROOT"] else {
throw FindError.noBuildRootEnvironmentVariable
}

let buildRootURL = URL(fileURLWithPath: buildRootPath)
var currentDirectoryURL = buildRootURL

// Go to the build root and search up the chain to find the Derived Data Path where the source packages are checked out.
while !FileManager.default.apollo_folderExists(at: currentDirectoryURL.appendingPathComponent("SourcePackages")) {
guard currentDirectoryURL.path != "/" else {
throw FindError.couldNotFindSourcePackagesDirectory(buildRoot: buildRootURL.path)
}

currentDirectoryURL = buildRootURL.deletingLastPathComponent()
}

return currentDirectoryURL
.appendingPathComponent("SourcePackages")
.appendingPathComponent("checkouts")
.appendingPathComponent("apollo-ios")
.appendingPathComponent("scripts")
}

private static func findScriptsFolderForCocoaPods(in environment: [String: String]) throws -> URL {
guard let podsRootPath = environment["PODS_ROOT"] else {
throw FindError.noPodsRootEnvironmentVariable
}

let podsRootURL = URL(fileURLWithPath: podsRootPath)

return podsRootURL
.appendingPathComponent("Apollo")
.appendingPathComponent("scripts")

}

private static func findScriptsFolderForCarthage(in environment: [String: String]) throws -> URL {
guard let sourceRootPath = environment["SRCROOT"] else {
throw FindError.noSourceRootEnvironmentVariable
}

let sourceRootURL = URL(fileURLWithPath: sourceRootPath)
return sourceRootURL
.appendingPathComponent("Carthage")
.appendingPathComponent("Checkouts")
.appendingPathComponent("apollo-ios")
.appendingPathComponent("scripts")
}
}
4 changes: 2 additions & 2 deletions Tests/ApolloCodegenTests/ApolloCodegenTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class ApolloCodegenTests: XCTestCase {
urlToSchemaFile: starWarsSchemaFileURL)
do {
_ = try ApolloCodegen.run(from: starWarsFolderURL,
scriptFolderURL: scriptFolderURL,
with: .custom(scriptsFolderURL: scriptFolderURL),
options: options)
} catch {
XCTFail("Error running codegen: \(error.localizedDescription)")
Expand All @@ -134,7 +134,7 @@ class ApolloCodegenTests: XCTestCase {
urlToSchemaFile: starWarsSchemaFileURL)

_ = try ApolloCodegen.run(from: starWarsFolderURL,
scriptFolderURL: scriptFolderURL,
with: .custom(scriptsFolderURL: scriptFolderURL),
options: options)

XCTAssertTrue(FileManager.default.apollo_folderExists(at: outputFolder))
Expand Down
112 changes: 112 additions & 0 deletions Tests/ApolloCodegenTests/ScriptDiectoryFinderTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
//
// ScriptDirectoryFinderTests.swift
// ApolloCodegenTests
//
// Created by Ellen Shapiro on 12/11/19.
// Copyright © 2019 Apollo GraphQL. All rights reserved.
//

import XCTest
@testable import ApolloCodegenLib

class ScriptDirectoryFinderTests: XCTestCase {

func testMissingPathForSPMBuildRootThrowsCorrectError() {
XCTAssertThrowsError(try ScriptDirectoryFinder.findScriptsFolder(for: .swiftPackageManager, in: [:])) { error in
switch error {
case ScriptDirectoryFinder.FindError.noBuildRootEnvironmentVariable:
// This is what we want
break
default:
XCTFail("Incorrect error: \(error)")
}
}
}

func testBogusPathForSPMBuildRootThrowsCorrectError() {
let fakeEnvironment = [
"BUILD_ROOT": "/Applications"
]

XCTAssertThrowsError(try ScriptDirectoryFinder.findScriptsFolder(for: .swiftPackageManager, in: fakeEnvironment)) { error in
switch error {
case ScriptDirectoryFinder.FindError.couldNotFindSourcePackagesDirectory(let buildRoot):
XCTAssertEqual(buildRoot, "/Applications")
default:
XCTFail("Incorrect error: \(error)")
}
}
}

func testBuildRootWithSourcePackagesFolderGivesCorrectPath() throws {
let actualSourceRootPath = try XCTUnwrap(ProcessInfo.processInfo.environment["SRCROOT"])

let fakeEnvironment = [
"BUILD_ROOT": "\(actualSourceRootPath)/Tests/ApolloCodegenTests"
]

let spmScriptFolderURL = try ScriptDirectoryFinder.findScriptsFolder(for: .swiftPackageManager, in: fakeEnvironment)

XCTAssertEqual(spmScriptFolderURL.path, "\(actualSourceRootPath)/Tests/ApolloCodegenTests/SourcePackages/checkouts/apollo-ios/scripts")
}


func testMissingPodsRootPathThrowsCorrectError() {
XCTAssertThrowsError(try ScriptDirectoryFinder.findScriptsFolder(for: .cocoaPods, in: [:])) { error in
switch error {
case ScriptDirectoryFinder.FindError.noPodsRootEnvironmentVariable:
// This is what we want.
break
default:
XCTFail("Incorrect error: \(error)")
}
}
}

func testPresentPodsRootPathReturnsCorrectURL() throws {
let fakeEnvironment = [
"PODS_ROOT" : "/Path/to/Pods"
]

let podsScriptFolderURL = try ScriptDirectoryFinder.findScriptsFolder(for: .cocoaPods, in: fakeEnvironment)

XCTAssertEqual(podsScriptFolderURL.path, "/Path/to/Pods/Apollo/scripts")

}

func testMissingSourceRootPathForCarthageThrowsCorrectError() {
XCTAssertThrowsError(try ScriptDirectoryFinder.findScriptsFolder(for: .carthage, in: [:])) { error in
switch error {
case ScriptDirectoryFinder.FindError.noSourceRootEnvironmentVariable:
// This is what we want.
break
default:
XCTFail("Incorrect error: \(error)")
}
}
}

func testPresentSourceRootPathReturnsCorrectURL() throws {
let fakeEnvironment = [
"SRCROOT": "/Path/to/source/root"
]

let carthageScriptFolderURL = try ScriptDirectoryFinder.findScriptsFolder(for: .carthage, in: fakeEnvironment)

XCTAssertEqual(carthageScriptFolderURL.path, "/Path/to/source/root/Carthage/Checkouts/apollo-ios/scripts")
}

func testCustomPackageManagerGivesYouBackWhateverYouHandIt() throws {
let url = URL(string: "https://apollographql.com")!

let returnedURL = try ScriptDirectoryFinder.findScriptsFolder(for: .custom(scriptsFolderURL: url), in: [:])

XCTAssertEqual(returnedURL, url)

let fileURL = URL(fileURLWithPath: "/Applications")

let returnedFileURL = try ScriptDirectoryFinder.findScriptsFolder(for: .custom(scriptsFolderURL: fileURL), in: [:])

XCTAssertEqual(returnedFileURL, fileURL)
}
}
1 change: 1 addition & 0 deletions Tests/ApolloCodegenTests/SourcePackages/.keep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This file exists to preserve folder structure in git.

0 comments on commit a1dca7c

Please sign in to comment.