Chimera - `carthage` support. (#2060)
* [carthage] Init `DependencyManaging` * [carthage] add `InstallMethod` * [carthage] rename `InstallDependencies` -> `InstallDependenciesMethod` * [carthage] Renaming `*Manger`s -> `*Interactor`s * [carthage] stub `Dependencies` * [carthage] add `CarthageCommandBuilder` * [carthage] add `CartfileContentBuilder` * [carthage] start using raw strings in `CartfileContentBuilder` * [carthage] run `carthage` using `tuist dependencies` * [carthage] copy frameworks and `Cartfile.resolved` to `Tuist/Dependencies/*` * [carthage] add `DependenciesDirectoryController` * [carthage] add new TODO warning * [carthage] add `app_with_framework_and_tests_and_dependencies` * [carthage] WIP: reading dependencies from `Dependencies.swift` * [carthage] WIP: removing `ProjectDescription` from `TuistDependencies` * [carthage] add `DependenciesModelLoader` * [carthage] add `TuistCore.Dependencies` model * [carthage] determine platforms from `carthage` run * [carthage] add `CartfileContentBuilderError` * [carthage] add `CarfileContentBuilderTests` * [carthage] add `CarthageCommandBuilderTests` * [carthage] add `CocoapodsInteractorTests`, `SPMInteractorTests` * [carthage] remove fixed `warning` * [carthage] add `CartfileResolvedInteractor`, `CartfileResolvedInteractorTests` * [carthage] add `CarthageFrameworksInteractor`, `CarthageFrameworksInteractorTests` * [carthage] add `CarthageInteractorTests` * [carthage] mark `DependenciesCommand` as `EXPERIMENTAL` * [carthage] add `MockCarthageInteractor`, `MockCocoapodsInteractor`, `MockSPMInteractor` * [carthage] add `DependenciesControllerTests` * [carthage] fix fixture * [carthage] fix saving frameworks, fix unit tests * [carthage] add acceptance tests - `dependencies.feature` * [carthage] `bundle exec rake style_correct` * [carthage] fix `SwiftFormat` warning * [carthage] enable `dependencies` acceptance test * [carthage] change - grouping the files inside `TuistDependencies` * [carthage] change - description of `CartfileContentBuilderError.rangeRequirementNotSupported` * [carthage] remove - `carthage` via `bundler` * [carthage] update - refactor `CarfileContentBuilderTests` * [carthage] change - refactor `CarthageCommandBuilder` into `CarthageCommandGenerator` * [carthage] change - refactor `CartfileContentBuilder` into `CartfileContentGenerator` * [carthage] fix - typos * [carthage] remove - `Info.plist` from `fixture/app_with_framework_and_tests_and_dependencies` * [carthage] fix - typo * [carthage] remove - warning comment * [carthage] remove - unnecessary code * [carthage] add - logging to `DependenciesController` * [carthage] fix - typo * [carthage] change - move `CarthageDependency.toString()` to `CarthageDependency.cartfileValue()` * [carthage] add - `CarthageDependencyTests` * [carthage] add - `CartfileContentGenerator.validate` * [carthage] change - pass tuist directory path into `CarthageInteractor` * [carthage] remove - `CartfileResolvedInteractor` * [carthage] change - WIP: refactor `CarthageFrameworksInteractor` * [carthage] change - WIP: refactor `CarthageFrameworksInteractor` * [carthage] changed - refactor `CarthageFrameworksInteractor` * [carthage] `bundle exec rake style_correct` * [carthage] add - `CarthageFrameworksInteractorTests.test_save_only_one_platform` * [carthage] `bundle exec rake style_correct` * [carthage] add - `--use-netrc` flag * [carthage] fix - `CarthageInteractorError.carthageNotFound` description. * [carthage] add - `Platform.carthageDirectory` * [carthage] change - remove unused code * [carthage] remove - `TuistDependencies.Graph` * [carthage] add - `CarthageVersionFilesInteractor` * [carthage] add - `CarthageVersionFilesInteracting.loadVersionFiles` * [carthage] add - cache `Carthage/Build` directory * [carthage] change - new structure of `Tuist/Dependencies` directory * [carthage] change - refactor `CarthageInteractor` * [carthage] fix - deleting unnecessary frameworks * [carthage] fix - acceptance tests * [carthage] change - refactor `Dependencies.swift` * [carthage] change - update changelog * [carthage] fix - run `bundle exec rake style_correct` * [carthage] fix - swiftlint violation * [carthage] delete - `CarthageFrameworksInteractor` * [carthage] fix - acceptance tests * [carthage] fix - typos * [carthage] remove - copy `Cartfile.resolved` from previous run if exist * [carthage] change - refactor `Dependencies` model * [carthage] `bundle exec rake style_correct` * [carthage] add - `Dependency.CarthageOrigin` * [carthage] remove - `InstallDependenciesMethod` * [carthage] change - `CarthageInteractor.PathProvider` -> `CarthagePathsProvider` * [carthage] change - update `Gitignore.stencil` with `Tuist/Dependencies` * [carthage] add - documentation * [carthage] fix - changelog after rebase * [carthage] run `bundle exec rake style_correct` * [carthage] fix - `app_with_framework_and_tests_and_dependencies` fixture
This commit is contained in:
parent
f805ba0533
commit
56a72d653b
|
@ -89,6 +89,7 @@ jobs:
|
|||
'cache-xcframeworks',
|
||||
'cache-frameworks',
|
||||
'precompiled',
|
||||
'dependencies',
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
|
|
|
@ -11,6 +11,7 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/
|
|||
|
||||
### Added
|
||||
|
||||
- Support for `Carthage` dependencies in `Dependencies.swift` [#2060](https://github.com/tuist/tuist/pull/2060) by [@laxmorek](https://github.com/laxmorek).
|
||||
- Fourier CLI tool to automate development tasks [#2196](https://github.com/tuist/tuist/pull/2196) by @pepibumur](https://github.com/pepibumur).
|
||||
- Support `.s` source files [#2199](https://github.com/tuist/tuist/pull/2199) by[ @dcvz](https://github.com/dcvz).
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import Foundation
|
||||
|
||||
/// A `Dependencies` manifest allows for defining external dependencies for Tuist.
|
||||
public struct Dependencies: Codable, Equatable {
|
||||
/// List of dependencies.
|
||||
public let dependencies: [Dependency]
|
||||
|
||||
/// Initializes a new `Dependencies` manifest instance.
|
||||
/// - Parameter dependencies: List of dependencies.
|
||||
public init(_ dependencies: [Dependency] = []) {
|
||||
self.dependencies = dependencies
|
||||
dumpIfNeeded(self)
|
||||
}
|
||||
}
|
|
@ -1,51 +1,177 @@
|
|||
import Foundation
|
||||
|
||||
/// Dependency contains the description of any kind of dependency of your Xcode project.
|
||||
public struct Dependency: Codable, Equatable {
|
||||
/// Name of the dependency
|
||||
let name: String
|
||||
|
||||
/// Type of requirement for the given dependency
|
||||
let requirement: Dependency.Requirement
|
||||
|
||||
/// Dependecy manager used to retrieve the dependecy
|
||||
public let manager: Dependency.Manager
|
||||
|
||||
/// Set of platforms for the given dependency
|
||||
public let platforms: Set<Platform>
|
||||
|
||||
public init(name: String,
|
||||
requirement: Dependency.Requirement,
|
||||
manager: Dependency.Manager,
|
||||
platforms: [Platform])
|
||||
{
|
||||
self.name = name
|
||||
self.requirement = requirement
|
||||
self.manager = manager
|
||||
self.platforms = Set(platforms)
|
||||
/// Contains the description of external dependency that can by installed using Tuist.
|
||||
public enum Dependency: Codable, Equatable {
|
||||
/// Origin of the Carthage dependency
|
||||
public enum CarthageOrigin: Codable, Equatable {
|
||||
/// Mimics `github` keyword from `Cartfile`. GitHub repositories (both GitHub.com and GitHub Enterprise).
|
||||
case github(path: String)
|
||||
/// Mimics `git` keyword from `Cartfile`. Other Git repositories.
|
||||
case git(path: String)
|
||||
/// Mimics `binary` keyword from `Cartfile`. Dependencies that are only available as compiled binary `.frameworks`.
|
||||
case binary(path: String)
|
||||
}
|
||||
|
||||
/// Carthage dependency initailizer
|
||||
/// - Parameter name: Name of the dependency
|
||||
/// - Parameter requirement: Type of requirement for the given dependency
|
||||
/// - Returns Dependency
|
||||
public static func carthage(name: String,
|
||||
requirement: Dependency.Requirement,
|
||||
platforms: [Platform]) -> Dependency
|
||||
{
|
||||
Dependency(name: name, requirement: requirement, manager: .carthage, platforms: platforms)
|
||||
/// Requirement for the Carthage dependency
|
||||
public enum CarthageRequirement: Codable, Equatable {
|
||||
/// Mimics `== 1.0` from `Cartfile`.
|
||||
case exact(Version)
|
||||
/// Mimics `~> 1.0` from `Cartfile`.
|
||||
case upToNext(Version)
|
||||
/// Mimics `>= 1.0` from `Cartfile`.
|
||||
case atLeast(Version)
|
||||
/// Mimics `"branch"` from `Cartfile`.
|
||||
case branch(String)
|
||||
/// Mimics `"revision"` from `Cartfile`.
|
||||
case revision(String)
|
||||
}
|
||||
|
||||
public static func == (lhs: Dependency, rhs: Dependency) -> Bool {
|
||||
lhs.name == rhs.name && lhs.requirement == rhs.requirement
|
||||
/// Contains the description of dependency that can by installed using Carthage. More: https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md
|
||||
case carthage(origin: CarthageOrigin, requirement: CarthageRequirement, platforms: Set<Platform>)
|
||||
}
|
||||
|
||||
// MARK: - Dependency: Codable
|
||||
|
||||
extension Dependency {
|
||||
private enum Kind: String, Codable {
|
||||
case carthage
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case kind
|
||||
case origin
|
||||
case requirement
|
||||
case platforms
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
let kind = try container.decode(Kind.self, forKey: .kind)
|
||||
switch kind {
|
||||
case .carthage:
|
||||
let origin = try container.decode(CarthageOrigin.self, forKey: .origin)
|
||||
let requirement = try container.decode(CarthageRequirement.self, forKey: .requirement)
|
||||
let platforms = try container.decode(Set<Platform>.self, forKey: .platforms)
|
||||
self = .carthage(origin: origin, requirement: requirement, platforms: platforms)
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
switch self {
|
||||
case let .carthage(origin, requirement, platforms):
|
||||
try container.encode(Kind.carthage, forKey: .kind)
|
||||
try container.encode(origin, forKey: .origin)
|
||||
try container.encode(requirement, forKey: .requirement)
|
||||
try container.encode(platforms, forKey: .platforms)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct Dependencies: Codable, Equatable {
|
||||
public let dependencies: [Dependency]
|
||||
// MARK: - Dependency.CarthageRequirement: Codable
|
||||
|
||||
public init(_ dependencies: [Dependency]) {
|
||||
self.dependencies = dependencies
|
||||
dumpIfNeeded(self)
|
||||
extension Dependency.CarthageRequirement {
|
||||
private enum Kind: String, Codable {
|
||||
case exact
|
||||
case upToNext
|
||||
case atLeast
|
||||
case branch
|
||||
case revision
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case kind
|
||||
case version
|
||||
case branch
|
||||
case revision
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
let kind = try container.decode(Kind.self, forKey: .kind)
|
||||
switch kind {
|
||||
case .exact:
|
||||
let version = try container.decode(Version.self, forKey: .version)
|
||||
self = .exact(version)
|
||||
case .upToNext:
|
||||
let version = try container.decode(Version.self, forKey: .version)
|
||||
self = .upToNext(version)
|
||||
case .atLeast:
|
||||
let version = try container.decode(Version.self, forKey: .version)
|
||||
self = .atLeast(version)
|
||||
case .branch:
|
||||
let branch = try container.decode(String.self, forKey: .branch)
|
||||
self = .branch(branch)
|
||||
case .revision:
|
||||
let revision = try container.decode(String.self, forKey: .revision)
|
||||
self = .revision(revision)
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
switch self {
|
||||
case let .exact(version):
|
||||
try container.encode(Kind.exact, forKey: .kind)
|
||||
try container.encode(version, forKey: .version)
|
||||
case let .upToNext(version):
|
||||
try container.encode(Kind.upToNext, forKey: .kind)
|
||||
try container.encode(version, forKey: .version)
|
||||
case let .atLeast(version):
|
||||
try container.encode(Kind.atLeast, forKey: .kind)
|
||||
try container.encode(version, forKey: .version)
|
||||
case let .branch(branch):
|
||||
try container.encode(Kind.branch, forKey: .kind)
|
||||
try container.encode(branch, forKey: .branch)
|
||||
case let .revision(revision):
|
||||
try container.encode(Kind.revision, forKey: .kind)
|
||||
try container.encode(revision, forKey: .revision)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Dependency.CarthageOrigin: Codable
|
||||
|
||||
extension Dependency.CarthageOrigin {
|
||||
private enum Kind: String, Codable {
|
||||
case github
|
||||
case git
|
||||
case binary
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case kind
|
||||
case path
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
let kind = try container.decode(Kind.self, forKey: .kind)
|
||||
switch kind {
|
||||
case .github:
|
||||
let path = try container.decode(String.self, forKey: .path)
|
||||
self = .github(path: path)
|
||||
case .git:
|
||||
let path = try container.decode(String.self, forKey: .path)
|
||||
self = .git(path: path)
|
||||
case .binary:
|
||||
let path = try container.decode(String.self, forKey: .path)
|
||||
self = .binary(path: path)
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
switch self {
|
||||
case let .github(path):
|
||||
try container.encode(Kind.github, forKey: .kind)
|
||||
try container.encode(path, forKey: .path)
|
||||
case let .git(path):
|
||||
try container.encode(Kind.git, forKey: .kind)
|
||||
try container.encode(path, forKey: .path)
|
||||
case let .binary(path):
|
||||
try container.encode(Kind.binary, forKey: .kind)
|
||||
try container.encode(path, forKey: .path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
public extension Dependency {
|
||||
enum Manager: String, Codable, Equatable {
|
||||
case carthage
|
||||
// case spm
|
||||
// case cocoapods
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
// The idea of Requirement comes from SPM PackageRequirement
|
||||
// https://github.com/apple/swift-package-manager/blob/main/Sources/PackageDescription/PackageRequirement.swift
|
||||
// This could be further extended for more cases
|
||||
|
||||
/// DependencyRequiement describes which dependency the project needs.
|
||||
public extension Dependency {
|
||||
enum Requirement: Codable, Equatable {
|
||||
case exact(Version)
|
||||
// case range(Range<Version>)
|
||||
// case branch(String)
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self = .exact(try container.decode(Version.self, forKey: .exact))
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if case let .exact(version) = self {
|
||||
try container.encode(version, forKey: .exact)
|
||||
}
|
||||
}
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case exact
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,85 @@
|
|||
import Foundation
|
||||
import TuistSupport
|
||||
|
||||
// MARK: - Carthage Dependency
|
||||
|
||||
/// CarthageDependency contains the description of a dependency to be fetched with Carthage.
|
||||
struct CarthageDependency {
|
||||
/// Name of the dependency
|
||||
let name: String
|
||||
public struct CarthageDependency: Equatable {
|
||||
/// Origin of the dependency
|
||||
public let origin: Origin
|
||||
|
||||
/// Type of requirement for the given dependency
|
||||
let requirement: Requirement
|
||||
public let requirement: Requirement
|
||||
|
||||
/// Set of platforms for the given dependency
|
||||
let platforms: Set<Platform>
|
||||
public let platforms: Set<Platform>
|
||||
|
||||
/// Initializes the carthage dependency with its attributes.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - origin: Origin of the dependency
|
||||
/// - requirement: Type of requirement for the given dependency
|
||||
/// - platforms: Set of platforms for the given dependency
|
||||
public init(
|
||||
origin: Origin,
|
||||
requirement: Requirement,
|
||||
platforms: Set<Platform>
|
||||
) {
|
||||
self.origin = origin
|
||||
self.requirement = requirement
|
||||
self.platforms = platforms
|
||||
}
|
||||
|
||||
/// Returns `Cartfile` representation.
|
||||
public var cartfileValue: String {
|
||||
origin.cartfileValue + " " + requirement.cartfileValue
|
||||
}
|
||||
}
|
||||
|
||||
public extension CarthageDependency {
|
||||
enum Origin: Equatable {
|
||||
case github(path: String)
|
||||
case git(path: String)
|
||||
case binary(path: String)
|
||||
|
||||
/// Returns `Cartfile` representation.
|
||||
public var cartfileValue: String {
|
||||
switch self {
|
||||
case let .github(path):
|
||||
return #"github "\#(path)""#
|
||||
case let .git(path):
|
||||
return #"git "\#(path)""#
|
||||
case let .binary(path):
|
||||
return #"binary "\#(path)""#
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Requirement
|
||||
|
||||
public extension CarthageDependency {
|
||||
enum Requirement: Equatable {
|
||||
case exact(String)
|
||||
case upToNext(String)
|
||||
case atLeast(String)
|
||||
case branch(String)
|
||||
case revision(String)
|
||||
|
||||
/// Returns `Cartfile` representation.
|
||||
public var cartfileValue: String {
|
||||
switch self {
|
||||
case let .exact(version):
|
||||
return "== \(version)"
|
||||
case let .upToNext(version):
|
||||
return "~> \(version)"
|
||||
case let .atLeast(version):
|
||||
return ">= \(version)"
|
||||
case let .branch(branch):
|
||||
return #""\#(branch)""#
|
||||
case let .revision(revision):
|
||||
return #""\#(revision)""#
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import Foundation
|
||||
|
||||
public struct Dependencies: Equatable {
|
||||
public let carthageDependencies: [CarthageDependency]
|
||||
|
||||
public init(
|
||||
carthageDependencies: [CarthageDependency]
|
||||
) {
|
||||
self.carthageDependencies = carthageDependencies
|
||||
}
|
||||
}
|
|
@ -110,4 +110,14 @@ extension Platform {
|
|||
default: return nil
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the directory name whose Carthage uses to save frameworks.
|
||||
public var carthageDirectory: String {
|
||||
switch self {
|
||||
case .iOS, .watchOS, .tvOS:
|
||||
return caseValue
|
||||
case .macOS:
|
||||
return "Mac"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
import RxBlocking
|
||||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistSupport
|
||||
|
||||
// MARK: - Carthage Interactor Errors
|
||||
|
||||
enum CarthageInteractorError: FatalError, Equatable {
|
||||
/// Thrown when Carthage cannot be found.
|
||||
case carthageNotFound
|
||||
/// Thrown when Carfile cannont be found in temporary directory after Carthage installation.
|
||||
case cartfileNotFound
|
||||
/// Thrown when `Carthage/Build` directory cannont be found in temporary directory after Carthage installation.
|
||||
case buildDirectoryNotFound
|
||||
|
||||
/// Error type.
|
||||
var type: ErrorType {
|
||||
switch self {
|
||||
case .carthageNotFound, .cartfileNotFound, .buildDirectoryNotFound:
|
||||
return .abort
|
||||
}
|
||||
}
|
||||
|
||||
/// Error description.
|
||||
var description: String {
|
||||
switch self {
|
||||
case .carthageNotFound:
|
||||
return "Carthage was not found in the environment. It's possible that the tool is not installed or hasn't been exposed to your environment."
|
||||
case .cartfileNotFound:
|
||||
return "Cartfile was not found after Carthage installation."
|
||||
case .buildDirectoryNotFound:
|
||||
return "Carthage/Build directory was not found after Carthage installation."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Carthage Interacting
|
||||
|
||||
public protocol CarthageInteracting {
|
||||
/// Fetches `Carthage` dependencies.
|
||||
/// - Parameter dependenciesDirectory: The path to the directory that contains the `Tuist/Dependencies/` directory.
|
||||
/// - Parameter method: Installation method.
|
||||
/// - Parameter dependencies: List of dependencies to intall using `Carthage`.
|
||||
func fetch(dependenciesDirectory: AbsolutePath, dependencies: [CarthageDependency]) throws
|
||||
}
|
||||
|
||||
// MARK: - Carthage Interactor
|
||||
|
||||
public final class CarthageInteractor: CarthageInteracting {
|
||||
private let fileHandler: FileHandling
|
||||
private let carthageCommandGenerator: CarthageCommandGenerating
|
||||
private let cartfileContentGenerator: CartfileContentGenerating
|
||||
|
||||
public init(
|
||||
fileHandler: FileHandling = FileHandler.shared,
|
||||
carthageCommandGenerator: CarthageCommandGenerating = CarthageCommandGenerator(),
|
||||
cartfileContentGenerator: CartfileContentGenerating = CartfileContentGenerator()
|
||||
) {
|
||||
self.fileHandler = fileHandler
|
||||
self.carthageCommandGenerator = carthageCommandGenerator
|
||||
self.cartfileContentGenerator = cartfileContentGenerator
|
||||
}
|
||||
|
||||
public func fetch(dependenciesDirectory: AbsolutePath, dependencies: [CarthageDependency]) throws {
|
||||
logger.info("We are starting to fetch the Carthage dependencies.", metadata: .section)
|
||||
|
||||
// check availability of `carthage`
|
||||
guard canUseSystemCarthage() else {
|
||||
throw CarthageInteractorError.carthageNotFound
|
||||
}
|
||||
|
||||
// determine platforms
|
||||
let platforms: Set<Platform> = dependencies
|
||||
.reduce(Set<Platform>()) { platforms, dependency in platforms.union(dependency.platforms) }
|
||||
|
||||
try fileHandler.inTemporaryDirectory { temporaryDirectoryPath in
|
||||
// prepare paths
|
||||
let pathsProvider = CarthagePathsProvider(dependenciesDirectory: dependenciesDirectory, temporaryDirectoryPath: temporaryDirectoryPath)
|
||||
|
||||
// prepare for installation
|
||||
try prepareForInstallation(pathsProvider: pathsProvider, dependencies: dependencies)
|
||||
|
||||
// create `carthage` shell command
|
||||
let command = carthageCommandGenerator.command(path: temporaryDirectoryPath, platforms: platforms)
|
||||
|
||||
// run `carthage`
|
||||
try System.shared.runAndPrint(command)
|
||||
|
||||
// post intallation actions
|
||||
try postInstallationActions(pathsProvider: pathsProvider)
|
||||
}
|
||||
|
||||
logger.info("Carthage dependencies were fetched successfully.", metadata: .success)
|
||||
}
|
||||
|
||||
// MARK: - Installation
|
||||
|
||||
private func prepareForInstallation(pathsProvider: CarthagePathsProvider, dependencies: [CarthageDependency]) throws {
|
||||
// copy build directory from previous run if exist
|
||||
if fileHandler.exists(pathsProvider.destinationCarthageDirectory) {
|
||||
try copyDirectory(from: pathsProvider.destinationCarthageDirectory, to: pathsProvider.temporaryCarthageBuildDirectory)
|
||||
}
|
||||
|
||||
// create `Cartfile`
|
||||
let cartfileContent = cartfileContentGenerator.cartfileContent(for: dependencies)
|
||||
let cartfilePath = pathsProvider.temporaryDirectoryPath.appending(component: "Cartfile")
|
||||
try fileHandler.write(cartfileContent, path: cartfilePath, atomically: true)
|
||||
}
|
||||
|
||||
private func postInstallationActions(pathsProvider: CarthagePathsProvider) throws {
|
||||
// validation
|
||||
guard fileHandler.exists(pathsProvider.temporaryCarfileResolvedPath) else {
|
||||
throw CarthageInteractorError.cartfileNotFound
|
||||
}
|
||||
guard fileHandler.exists(pathsProvider.temporaryCarthageBuildDirectory) else {
|
||||
throw CarthageInteractorError.buildDirectoryNotFound
|
||||
}
|
||||
|
||||
// save `Cartfile.resolved`
|
||||
try copyFile(from: pathsProvider.temporaryCarfileResolvedPath, to: pathsProvider.destinationCarfileResolvedPath)
|
||||
// save build directory
|
||||
try copyDirectory(from: pathsProvider.temporaryCarthageBuildDirectory, to: pathsProvider.destinationCarthageDirectory)
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private func copyFile(from fromPath: AbsolutePath, to toPath: AbsolutePath) throws {
|
||||
try fileHandler.createFolder(toPath.removingLastComponent())
|
||||
|
||||
if fileHandler.exists(toPath) {
|
||||
try fileHandler.replace(toPath, with: fromPath)
|
||||
} else {
|
||||
try fileHandler.copy(from: fromPath, to: toPath)
|
||||
}
|
||||
}
|
||||
|
||||
private func copyDirectory(from fromPath: AbsolutePath, to toPath: AbsolutePath) throws {
|
||||
try fileHandler.createFolder(toPath.removingLastComponent())
|
||||
|
||||
if fileHandler.exists(toPath) {
|
||||
try fileHandler.delete(toPath)
|
||||
}
|
||||
|
||||
try fileHandler.copy(from: fromPath, to: toPath)
|
||||
}
|
||||
|
||||
/// Returns true if Carthage is avaiable in the environment.
|
||||
/// - Returns: True if Carthege is available globally in the system.
|
||||
private func canUseSystemCarthage() -> Bool {
|
||||
do {
|
||||
_ = try System.shared.which("carthage")
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Models
|
||||
|
||||
private struct CarthagePathsProvider {
|
||||
let dependenciesDirectory: AbsolutePath
|
||||
let temporaryDirectoryPath: AbsolutePath
|
||||
|
||||
let destinationCarfileResolvedPath: AbsolutePath
|
||||
let destinationCarthageDirectory: AbsolutePath
|
||||
|
||||
let temporaryCarfileResolvedPath: AbsolutePath
|
||||
let temporaryCarthageBuildDirectory: AbsolutePath
|
||||
|
||||
init(dependenciesDirectory: AbsolutePath, temporaryDirectoryPath: AbsolutePath) {
|
||||
self.dependenciesDirectory = dependenciesDirectory
|
||||
self.temporaryDirectoryPath = temporaryDirectoryPath
|
||||
|
||||
destinationCarfileResolvedPath = dependenciesDirectory
|
||||
.appending(component: Constants.DependenciesDirectory.lockfilesDirectoryName)
|
||||
.appending(component: Constants.DependenciesDirectory.cartfileResolvedName)
|
||||
destinationCarthageDirectory = dependenciesDirectory
|
||||
.appending(component: Constants.DependenciesDirectory.carthageDirectoryName)
|
||||
|
||||
temporaryCarfileResolvedPath = temporaryDirectoryPath
|
||||
.appending(component: Constants.DependenciesDirectory.cartfileResolvedName)
|
||||
temporaryCarthageBuildDirectory = temporaryDirectoryPath
|
||||
.appending(component: Constants.DependenciesDirectory.carthageDirectoryName)
|
||||
.appending(component: "Build")
|
||||
}
|
||||
}
|
23
Sources/TuistDependencies/Carthage/Generators/CartfileContentGenerator.swift
vendored
Normal file
23
Sources/TuistDependencies/Carthage/Generators/CartfileContentGenerator.swift
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistSupport
|
||||
|
||||
// MARK: - Cartfile Content Generating
|
||||
|
||||
public protocol CartfileContentGenerating {
|
||||
/// Generates content for `Cartfile`.
|
||||
/// - Parameter dependencies: The dependencies whose will be installed.
|
||||
func cartfileContent(for dependencies: [CarthageDependency]) -> String
|
||||
}
|
||||
|
||||
// MARK: - Cartfile Content Generator
|
||||
|
||||
public final class CartfileContentGenerator: CartfileContentGenerating {
|
||||
public init() {}
|
||||
|
||||
public func cartfileContent(for dependencies: [CarthageDependency]) -> String {
|
||||
dependencies
|
||||
.map(\.cartfileValue)
|
||||
.joined(separator: "\n")
|
||||
}
|
||||
}
|
51
Sources/TuistDependencies/Carthage/Generators/CarthageCommandGenerator.swift
vendored
Normal file
51
Sources/TuistDependencies/Carthage/Generators/CarthageCommandGenerator.swift
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistSupport
|
||||
|
||||
// MARK: - Carthage Command Generating
|
||||
|
||||
public protocol CarthageCommandGenerating {
|
||||
/// Builds `Carthage` command.
|
||||
/// - Parameters:
|
||||
/// - path: Directory whose project's dependencies will be installed.
|
||||
/// - platforms: The platforms to build for.
|
||||
func command(path: AbsolutePath, platforms: Set<Platform>?) -> [String]
|
||||
}
|
||||
|
||||
// MARK: - Carthage Command Generator
|
||||
|
||||
public final class CarthageCommandGenerator: CarthageCommandGenerating {
|
||||
public init() {}
|
||||
|
||||
public func command(path: AbsolutePath, platforms: Set<Platform>?) -> [String] {
|
||||
var commandComponents: [String] = []
|
||||
commandComponents.append("carthage")
|
||||
commandComponents.append("bootstrap")
|
||||
|
||||
// Project Directory
|
||||
|
||||
commandComponents.append("--project-directory")
|
||||
commandComponents.append(path.pathString)
|
||||
|
||||
// Platforms
|
||||
|
||||
if let platforms = platforms, !platforms.isEmpty {
|
||||
commandComponents.append("--platform")
|
||||
commandComponents.append(
|
||||
platforms
|
||||
.map(\.caseValue)
|
||||
.joined(separator: ",")
|
||||
)
|
||||
}
|
||||
|
||||
// Flags
|
||||
|
||||
commandComponents.append("--use-netrc")
|
||||
commandComponents.append("--cache-builds")
|
||||
commandComponents.append("--new-resolver")
|
||||
|
||||
// Return
|
||||
|
||||
return commandComponents
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
import TSCBasic
|
||||
import TuistSupport
|
||||
|
||||
// MARK: - CocoaPods Interactor Errors
|
||||
|
||||
enum CocoaPodsInteractorError: FatalError {
|
||||
case unimplemented
|
||||
|
||||
/// Error type.
|
||||
public var type: ErrorType {
|
||||
switch self {
|
||||
case .unimplemented:
|
||||
return .abort
|
||||
}
|
||||
}
|
||||
|
||||
/// Description.
|
||||
public var description: String {
|
||||
switch self {
|
||||
case .unimplemented:
|
||||
return "CocoaPods is not supported yet. It's being worked on and it'll be available soon."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - CocoaPods Interacting
|
||||
|
||||
public protocol CocoaPodsInteracting {
|
||||
/// Fetches `CocoaPods` dependencies.
|
||||
/// - Parameter dependenciesDirectory: The path to the directory that contains the `Tuist/Dependencies/` directory.
|
||||
func fetch(dependenciesDirectory: AbsolutePath) throws
|
||||
}
|
||||
|
||||
// MARK: - Cocoapods Interactor
|
||||
|
||||
public final class CocoaPodsInteractor: CocoaPodsInteracting {
|
||||
public init() {}
|
||||
|
||||
public func fetch(dependenciesDirectory _: AbsolutePath) throws {
|
||||
throw CocoaPodsInteractorError.unimplemented
|
||||
}
|
||||
}
|
|
@ -1,59 +1,43 @@
|
|||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistSupport
|
||||
|
||||
// MARK: - Dependencies Controller Errors
|
||||
|
||||
public enum DependenciesControllerError: FatalError {
|
||||
case unimplemented
|
||||
|
||||
/// Error type.
|
||||
public var type: ErrorType {
|
||||
switch self {
|
||||
case .unimplemented:
|
||||
return .abort
|
||||
}
|
||||
}
|
||||
|
||||
/// Description.
|
||||
public var description: String {
|
||||
switch self {
|
||||
case .unimplemented:
|
||||
return "A standard approach for managing third-party dependencies is being worked on and it'll be available soon."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Dependencies Controlling
|
||||
|
||||
/// `DependenciesControlling` controls:
|
||||
/// 1. Fetching/updating dependencies defined in `./Tuist/Dependencies.swift` by running appropriate dependencies managers (`Cocoapods`, `Carthage`, `SPM`).
|
||||
/// 2. Compiling fetched/updated depedencies into `.framework.`/`.xcframework.`.
|
||||
/// 3. Saving compiled frameworks uder `./Tuist/Dependencies/*`.
|
||||
/// 3. Saving compiled frameworks under `./Tuist/Dependencies/*`.
|
||||
/// 4. Generating dependencies graph under `./Tuist/Dependencies/graph.json`.
|
||||
public protocol DependenciesControlling {
|
||||
/// Fetches dependencies.
|
||||
/// - Parameter path: Directory whose project's dependencies will be fetched.
|
||||
func fetch(at path: AbsolutePath) throws
|
||||
/// Updates dependencies.
|
||||
/// - Parameter path: Directory whose project's dependencies will be updated.
|
||||
func update(at path: AbsolutePath) throws
|
||||
/// - Parameter path: Directory whose project's dependencies will be installed.
|
||||
/// - Parameter dependencies: List of dependencies to intall.
|
||||
func fetch(at path: AbsolutePath, dependencies: Dependencies) throws
|
||||
}
|
||||
|
||||
// MARK: - Dependencies Controller
|
||||
|
||||
public final class DependenciesController: DependenciesControlling {
|
||||
public init() {}
|
||||
private let carthageInteractor: CarthageInteracting
|
||||
private let cocoaPodsInteractor: CocoaPodsInteracting
|
||||
private let swiftPackageManagerInteractor: SwiftPackageManagerInteracting
|
||||
|
||||
public func fetch(at _: AbsolutePath) throws {
|
||||
logger.notice("Start fetching depednencies.")
|
||||
|
||||
// TODO: implement me!
|
||||
throw DependenciesControllerError.unimplemented
|
||||
public init(
|
||||
carthageInteractor: CarthageInteracting = CarthageInteractor(),
|
||||
cocoaPodsInteractor: CocoaPodsInteracting = CocoaPodsInteractor(),
|
||||
swiftPackageManagerInteractor: SwiftPackageManagerInteracting = SwiftPackageManagerInteractor()
|
||||
) {
|
||||
self.carthageInteractor = carthageInteractor
|
||||
self.cocoaPodsInteractor = cocoaPodsInteractor
|
||||
self.swiftPackageManagerInteractor = swiftPackageManagerInteractor
|
||||
}
|
||||
|
||||
public func update(at _: AbsolutePath) throws {
|
||||
logger.notice("Start updating depednencies.")
|
||||
public func fetch(at path: AbsolutePath, dependencies: Dependencies) throws {
|
||||
let dependenciesDirectory = path
|
||||
.appending(component: Constants.tuistDirectoryName)
|
||||
.appending(component: Constants.DependenciesDirectory.name)
|
||||
|
||||
// TODO: implement me!
|
||||
throw DependenciesControllerError.unimplemented
|
||||
try carthageInteractor.fetch(dependenciesDirectory: dependenciesDirectory, dependencies: dependencies.carthageDependencies)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import TSCBasic
|
||||
import TuistSupport
|
||||
|
||||
// MARK: - Swift Package Manager Interactor Error
|
||||
|
||||
public enum SwiftPackageManagerInteractorError: FatalError {
|
||||
case unimplemented
|
||||
|
||||
/// Error type.
|
||||
public var type: ErrorType {
|
||||
switch self {
|
||||
case .unimplemented:
|
||||
return .abort
|
||||
}
|
||||
}
|
||||
|
||||
/// Description.
|
||||
public var description: String {
|
||||
switch self {
|
||||
case .unimplemented:
|
||||
return "Swift Package Manager is not supported yet. It's being worked on and it'll be available soon."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Swift Package Manager Interacting
|
||||
|
||||
public protocol SwiftPackageManagerInteracting {
|
||||
/// Fetches `Swift Package Manager` dependencies.
|
||||
/// - Parameter dependenciesDirectoryPath: The path to the directory that contains the `Tuist/Dependencies/` directory.
|
||||
func fetch(dependenciesDirectory: AbsolutePath) throws
|
||||
}
|
||||
|
||||
// MARK: - Swift Package Manager Interactor
|
||||
|
||||
public final class SwiftPackageManagerInteractor: SwiftPackageManagerInteracting {
|
||||
public init() {}
|
||||
|
||||
public func fetch(dependenciesDirectory _: AbsolutePath) throws {
|
||||
throw SwiftPackageManagerInteractorError.unimplemented
|
||||
}
|
||||
}
|
26
Sources/TuistDependenciesTesting/Carthage/MockCartfileContentGenerator.swift
vendored
Normal file
26
Sources/TuistDependenciesTesting/Carthage/MockCartfileContentGenerator.swift
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
import TSCBasic
|
||||
import TuistCore
|
||||
|
||||
@testable import TuistDependencies
|
||||
|
||||
public final class MockCartfileContentGenerator: CartfileContentGenerating {
|
||||
public init() {}
|
||||
|
||||
var invokedCartfileContent = false
|
||||
var invokedCartfileContentCount = 0
|
||||
var invokedCartfileContentParameters: [CarthageDependency]?
|
||||
var invokedCartfileContentParametersList = [[CarthageDependency]]()
|
||||
var cartfileContentStub: (([CarthageDependency]) -> String)?
|
||||
|
||||
public func cartfileContent(for dependencies: [CarthageDependency]) -> String {
|
||||
invokedCartfileContent = true
|
||||
invokedCartfileContentCount += 1
|
||||
invokedCartfileContentParameters = dependencies
|
||||
invokedCartfileContentParametersList.append(dependencies)
|
||||
if let stub = cartfileContentStub {
|
||||
return stub(dependencies)
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
}
|
26
Sources/TuistDependenciesTesting/Carthage/MockCarthageCommandGenerator.swift
vendored
Normal file
26
Sources/TuistDependenciesTesting/Carthage/MockCarthageCommandGenerator.swift
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
import TSCBasic
|
||||
import TuistCore
|
||||
|
||||
@testable import TuistDependencies
|
||||
|
||||
public final class MockCarthageCommandGenerator: CarthageCommandGenerating {
|
||||
public init() {}
|
||||
|
||||
var invokedCommand = false
|
||||
var invokedCommandCount = 0
|
||||
var invokedCommandParameters: (path: AbsolutePath, platforms: Set<Platform>?)?
|
||||
var invokedCommandParametersList = [(path: AbsolutePath, platforms: Set<Platform>?)]()
|
||||
var commandStub: ((AbsolutePath, Set<Platform>?) -> [String])?
|
||||
|
||||
public func command(path: AbsolutePath, platforms: Set<Platform>?) -> [String] {
|
||||
invokedCommand = true
|
||||
invokedCommandCount += 1
|
||||
invokedCommandParameters = (path, platforms)
|
||||
invokedCommandParametersList.append((path, platforms))
|
||||
if let stub = commandStub {
|
||||
return stub(path, platforms)
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import TSCBasic
|
||||
import TuistCore
|
||||
|
||||
@testable import TuistDependencies
|
||||
|
||||
public final class MockCarthageInteractor: CarthageInteracting {
|
||||
public init() {}
|
||||
|
||||
var invokedFetch = false
|
||||
var invokedFetchCount = 0
|
||||
var invokedFetchParameters: (dependenciesDirectory: AbsolutePath, dependencies: [CarthageDependency])?
|
||||
var invokedFetchParametersList = [(dependenciesDirectory: AbsolutePath, dependencies: [CarthageDependency])]()
|
||||
var stubbedFetchError: Error?
|
||||
|
||||
public func fetch(dependenciesDirectory: AbsolutePath, dependencies: [CarthageDependency]) throws {
|
||||
invokedFetch = true
|
||||
invokedFetchCount += 1
|
||||
invokedFetchParameters = (dependenciesDirectory, dependencies)
|
||||
invokedFetchParametersList.append((dependenciesDirectory, dependencies))
|
||||
if let error = stubbedFetchError {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import TSCBasic
|
||||
import TuistCore
|
||||
|
||||
@testable import TuistDependencies
|
||||
|
||||
public final class MockCocoaPodsInteractor: CocoaPodsInteracting {
|
||||
public init() {}
|
||||
|
||||
var invokedFetch = false
|
||||
var invokedFetchCount = 0
|
||||
var invokedFetchParameters: AbsolutePath?
|
||||
var invokedFetchParametersList = [AbsolutePath]()
|
||||
var stubbedFetchError: Error?
|
||||
|
||||
public func fetch(dependenciesDirectory: AbsolutePath) throws {
|
||||
invokedFetch = true
|
||||
invokedFetchCount += 1
|
||||
invokedFetchParameters = dependenciesDirectory
|
||||
invokedFetchParametersList.append(dependenciesDirectory)
|
||||
if let error = stubbedFetchError {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
import TSCBasic
|
||||
import TuistCore
|
||||
|
||||
@testable import TuistDependencies
|
||||
|
||||
public final class MockDependenciesController: DependenciesControlling {
|
||||
|
@ -6,33 +8,17 @@ public final class MockDependenciesController: DependenciesControlling {
|
|||
|
||||
var invokedFetch = false
|
||||
var invokedFetchCount = 0
|
||||
var invokedFetchParameters: AbsolutePath?
|
||||
var invokedFetchParametersList = [AbsolutePath]()
|
||||
var invokedFetchParameters: (path: AbsolutePath, dependencies: Dependencies)?
|
||||
var invokedFetchParametersList = [(path: AbsolutePath, dependencies: Dependencies)]()
|
||||
var stubbedFetchError: Error?
|
||||
|
||||
public func fetch(at path: AbsolutePath) throws {
|
||||
public func fetch(at path: AbsolutePath, dependencies: Dependencies) throws {
|
||||
invokedFetch = true
|
||||
invokedFetchCount += 1
|
||||
invokedFetchParameters = path
|
||||
invokedFetchParametersList.append(path)
|
||||
invokedFetchParameters = (path, dependencies)
|
||||
invokedFetchParametersList.append((path, dependencies))
|
||||
if let error = stubbedFetchError {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
var invokedUpdate = false
|
||||
var invokedUpdateCount = 0
|
||||
var invokedUpdateParameters: AbsolutePath?
|
||||
var invokedUpdateParametersList = [AbsolutePath]()
|
||||
var stubbedUpdateError: Error?
|
||||
|
||||
public func update(at path: AbsolutePath) throws {
|
||||
invokedUpdate = true
|
||||
invokedUpdateCount += 1
|
||||
invokedUpdateParameters = path
|
||||
invokedUpdateParametersList.append(path)
|
||||
if let error = stubbedUpdateError {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import TSCBasic
|
||||
import TuistCore
|
||||
|
||||
@testable import TuistDependencies
|
||||
|
||||
public final class MockSwiftPackageManagerInteractor: SwiftPackageManagerInteracting {
|
||||
public init() {}
|
||||
|
||||
var invokedFetch = false
|
||||
var invokedFetchCount = 0
|
||||
var invokedFetchParameters: AbsolutePath?
|
||||
var invokedFetchParametersList = [AbsolutePath]()
|
||||
var stubbedFetchError: Error?
|
||||
|
||||
public func fetch(dependenciesDirectory: AbsolutePath) throws {
|
||||
invokedFetch = true
|
||||
invokedFetchCount += 1
|
||||
invokedFetchParameters = dependenciesDirectory
|
||||
invokedFetchParametersList.append(dependenciesDirectory)
|
||||
if let error = stubbedFetchError {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ import TSCBasic
|
|||
struct DependenciesCommand: ParsableCommand {
|
||||
static var configuration: CommandConfiguration {
|
||||
CommandConfiguration(commandName: "dependencies",
|
||||
abstract: "A set of commands for project's dependencies managment.",
|
||||
abstract: "[Experimental] A set of commands for project's dependencies managment.",
|
||||
subcommands: [
|
||||
DependenciesFetchCommand.self,
|
||||
DependenciesUpdateCommand.self,
|
||||
|
|
|
@ -2,19 +2,28 @@ import Foundation
|
|||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistDependencies
|
||||
import TuistLoader
|
||||
import TuistSupport
|
||||
|
||||
final class DependenciesFetchService {
|
||||
private let dependenciesController: DependenciesControlling
|
||||
private let dependenciesModelLoader: DependenciesModelLoading
|
||||
|
||||
init(dependenciesController: DependenciesControlling = DependenciesController()) {
|
||||
init(dependenciesController: DependenciesControlling = DependenciesController(),
|
||||
dependenciesModelLoader: DependenciesModelLoading = DependenciesModelLoader())
|
||||
{
|
||||
self.dependenciesController = dependenciesController
|
||||
self.dependenciesModelLoader = dependenciesModelLoader
|
||||
}
|
||||
|
||||
func run(path: String?) throws {
|
||||
logger.info("We are starting to fetch/update the dependencies.", metadata: .section)
|
||||
|
||||
let path = self.path(path)
|
||||
try dependenciesController.fetch(at: path)
|
||||
logger.notice("Successfully fetched dependencies", metadata: .success)
|
||||
let dependencies = try dependenciesModelLoader.loadDependencies(at: path)
|
||||
try dependenciesController.fetch(at: path, dependencies: dependencies)
|
||||
|
||||
logger.info("Dependencies were fetched successfully.", metadata: .success)
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
|
|
@ -2,28 +2,45 @@ import Foundation
|
|||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistDependencies
|
||||
import TuistLoader
|
||||
import TuistSupport
|
||||
|
||||
final class DependenciesUpdateService {
|
||||
private let dependenciesController: DependenciesControlling
|
||||
// MARK: - DependenciesUpdateServiceError
|
||||
|
||||
init(dependenciesController: DependenciesControlling = DependenciesController()) {
|
||||
self.dependenciesController = dependenciesController
|
||||
enum DependenciesUpdateServiceError: FatalError {
|
||||
case unimplemented
|
||||
|
||||
/// Error type.
|
||||
public var type: ErrorType {
|
||||
switch self {
|
||||
case .unimplemented:
|
||||
return .abort
|
||||
}
|
||||
}
|
||||
|
||||
func run(path: String?) throws {
|
||||
let path = self.path(path)
|
||||
try dependenciesController.update(at: path)
|
||||
logger.notice("Successfully updated dependencies", metadata: .success)
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private func path(_ path: String?) -> AbsolutePath {
|
||||
if let path = path {
|
||||
return AbsolutePath(path, relativeTo: FileHandler.shared.currentPath)
|
||||
} else {
|
||||
return FileHandler.shared.currentPath
|
||||
/// Description.
|
||||
public var description: String {
|
||||
switch self {
|
||||
case .unimplemented:
|
||||
return "Updating dependencies is not yet supported. It's being worked on and it'll be available soon."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - DependenciesUpdateService
|
||||
|
||||
final class DependenciesUpdateService {
|
||||
private let dependenciesController: DependenciesControlling
|
||||
private let dependenciesModelLoader: DependenciesModelLoading
|
||||
|
||||
init(dependenciesController: DependenciesControlling = DependenciesController(),
|
||||
dependenciesModelLoader: DependenciesModelLoading = DependenciesModelLoader())
|
||||
{
|
||||
self.dependenciesController = dependenciesController
|
||||
self.dependenciesModelLoader = dependenciesModelLoader
|
||||
}
|
||||
|
||||
func run(path _: String?) throws {
|
||||
throw DependenciesUpdateServiceError.unimplemented
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import Foundation
|
||||
import ProjectDescription
|
||||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistSupport
|
||||
|
||||
/// Entity responsible for providing dependencies model
|
||||
public protocol DependenciesModelLoading {
|
||||
/// Load array of Carthage Dependency models at the specified path.
|
||||
/// - Parameter path: The absolute path for the dependency models to load.
|
||||
/// - Returns: The Dependencies loaded from the specified path.
|
||||
/// - Throws: Error encountered during the loading process (e.g. Missing Dependencies file).
|
||||
func loadDependencies(at path: AbsolutePath) throws -> TuistCore.Dependencies
|
||||
}
|
||||
|
||||
public class DependenciesModelLoader: DependenciesModelLoading {
|
||||
private let manifestLoader: ManifestLoading
|
||||
|
||||
public init(manifestLoader: ManifestLoading = ManifestLoader()) {
|
||||
self.manifestLoader = manifestLoader
|
||||
}
|
||||
|
||||
public func loadDependencies(at path: AbsolutePath) throws -> TuistCore.Dependencies {
|
||||
let manifest = try manifestLoader.loadDependencies(at: path)
|
||||
return try TuistCore.Dependencies.from(manifest: manifest)
|
||||
}
|
||||
}
|
|
@ -156,14 +156,13 @@ public class ManifestLoader: ManifestLoading {
|
|||
}
|
||||
|
||||
public func loadDependencies(at path: AbsolutePath) throws -> ProjectDescription.Dependencies {
|
||||
let dependencyPath = path.appending(component: Manifest.dependencies.fileName(path))
|
||||
let dependencyPath = path.appending(components: Constants.tuistDirectoryName, Manifest.dependencies.fileName(path))
|
||||
guard FileHandler.shared.exists(dependencyPath) else {
|
||||
throw ManifestLoaderError.manifestNotFound(.dependencies, path)
|
||||
}
|
||||
|
||||
let dependenciesData = try loadManifestData(at: dependencyPath)
|
||||
let decoder = JSONDecoder()
|
||||
|
||||
return try decoder.decode(Dependencies.self, from: dependenciesData)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
import Foundation
|
||||
import ProjectDescription
|
||||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistSupport
|
||||
|
||||
extension TuistCore.CarthageDependency.Origin {
|
||||
static func from(manifest: ProjectDescription.Dependency.CarthageOrigin) throws -> Self {
|
||||
switch manifest {
|
||||
case let .github(path):
|
||||
return .github(path: path)
|
||||
case let .git(path):
|
||||
return .git(path: path)
|
||||
case let .binary(path):
|
||||
return .binary(path: path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension TuistCore.CarthageDependency.Requirement {
|
||||
static func from(manifest: ProjectDescription.Dependency.CarthageRequirement) throws -> Self {
|
||||
switch manifest {
|
||||
case let .exact(version):
|
||||
return .exact(version.description)
|
||||
case let .upToNext(version):
|
||||
return .upToNext(version.description)
|
||||
case let .atLeast(version):
|
||||
return .atLeast(version.description)
|
||||
case let .branch(branch):
|
||||
return .branch(branch)
|
||||
case let .revision(revision):
|
||||
return .revision(revision)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import Foundation
|
||||
import ProjectDescription
|
||||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistSupport
|
||||
|
||||
extension TuistCore.Dependencies {
|
||||
static func from(manifest: ProjectDescription.Dependencies) throws -> Self {
|
||||
let carthageDependencies = try manifest.dependencies.reduce(into: [CarthageDependency]()) { result, dependency in
|
||||
switch dependency {
|
||||
case let .carthage(origin, requirement, platforms):
|
||||
let origin = try TuistCore.CarthageDependency.Origin.from(manifest: origin)
|
||||
let requirement = try TuistCore.CarthageDependency.Requirement.from(manifest: requirement)
|
||||
let platforms = try platforms.map { try TuistCore.Platform.from(manifest: $0) }
|
||||
result.append(CarthageDependency(origin: origin, requirement: requirement, platforms: Set(platforms)))
|
||||
}
|
||||
}
|
||||
|
||||
return Self(carthageDependencies: carthageDependencies)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistSupport
|
||||
|
||||
@testable import TuistLoader
|
||||
|
||||
public class MockDependenciesModelLoader: DependenciesModelLoading {
|
||||
public init() {}
|
||||
|
||||
var invokedLoadDependencies = false
|
||||
var invokedLoadDependenciesCount = 0
|
||||
var invokedLoadDependenciesParameters: AbsolutePath?
|
||||
var invokedLoadDependenciesParemetersList = [AbsolutePath]()
|
||||
var loadDependenciesStub: ((AbsolutePath) throws -> Dependencies)?
|
||||
|
||||
public func loadDependencies(at path: AbsolutePath) throws -> Dependencies {
|
||||
invokedLoadDependencies = true
|
||||
invokedLoadDependenciesCount += 1
|
||||
invokedLoadDependenciesParameters = path
|
||||
invokedLoadDependenciesParemetersList.append(path)
|
||||
|
||||
if let stub = loadDependenciesStub {
|
||||
return try stub(path)
|
||||
} else {
|
||||
return Dependencies(carthageDependencies: [])
|
||||
}
|
||||
}
|
||||
}
|
|
@ -164,9 +164,7 @@ extension Arguments {
|
|||
}
|
||||
|
||||
extension Dependencies {
|
||||
public static func test(name: String = "Any Dependency",
|
||||
requirement: Dependency.Requirement = .exact("1.4.0")) -> Dependencies
|
||||
{
|
||||
Dependencies([.carthage(name: name, requirement: requirement, platforms: [.iOS])])
|
||||
public static func test(dependencies: [Dependency] = []) -> Dependencies {
|
||||
Dependencies(dependencies)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,13 @@ public struct Constants {
|
|||
public static let swiftDoc = "swift-doc"
|
||||
}
|
||||
|
||||
public struct DependenciesDirectory {
|
||||
public static let name = "Dependencies"
|
||||
public static let lockfilesDirectoryName = "Lockfiles"
|
||||
public static let cartfileResolvedName = "Cartfile.resolved"
|
||||
public static let carthageDirectoryName = "Carthage"
|
||||
}
|
||||
|
||||
public struct DerivedDirectory {
|
||||
public static let name = "Derived"
|
||||
public static let infoPlists = "InfoPlists"
|
||||
|
|
|
@ -65,3 +65,6 @@ DerivedData/
|
|||
### Tuist derived files ###
|
||||
graph.dot
|
||||
Derived/
|
||||
|
||||
### Tuist managed dependencies ###
|
||||
Tuist/Dependencies
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import Foundation
|
||||
import XCTest
|
||||
|
||||
@testable import ProjectDescription
|
||||
|
||||
final class DependenciesTests: XCTestCase {
|
||||
func test_dependencies_codable() throws {
|
||||
let subject = Dependencies([
|
||||
.carthage(origin: .github(path: "Dependency1/Dependency1"), requirement: .branch("BranchName"), platforms: [.iOS]),
|
||||
.carthage(origin: .git(path: "Dependency2/Dependency2"), requirement: .upToNext("1.2.3"), platforms: [.tvOS, .macOS]),
|
||||
])
|
||||
XCTAssertCodable(subject)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
import Foundation
|
||||
import XCTest
|
||||
|
||||
@testable import ProjectDescription
|
||||
|
||||
final class DependencyTests: XCTestCase {
|
||||
func test_dependency_carthage_codable() throws {
|
||||
let subject: Dependency = .carthage(origin: .github(path: "Dependency/Dependency"), requirement: .revision("xyz"), platforms: [.iOS, .macOS, .tvOS, .watchOS])
|
||||
XCTAssertCodable(subject)
|
||||
}
|
||||
|
||||
// MARK: - Carthage Origin tests
|
||||
|
||||
func test_carthageOrigin_github_codable() throws {
|
||||
let subject: Dependency.CarthageOrigin = .github(path: "Path/Path")
|
||||
XCTAssertCodable(subject)
|
||||
}
|
||||
|
||||
func test_carthageOrigin_git_codable() throws {
|
||||
let subject: Dependency.CarthageOrigin = .git(path: "Git/Git")
|
||||
XCTAssertCodable(subject)
|
||||
}
|
||||
|
||||
func test_carthageOrigin_binary_codable() throws {
|
||||
let subject: Dependency.CarthageOrigin = .binary(path: "file:///some/Path/MyFramework.json")
|
||||
XCTAssertCodable(subject)
|
||||
}
|
||||
|
||||
// MARK: - Carthage Requirement tests
|
||||
|
||||
func test_carthageRequirement_exact_codable() throws {
|
||||
let subject: Dependency.CarthageRequirement = .exact("1.0.0")
|
||||
XCTAssertCodable(subject)
|
||||
}
|
||||
|
||||
func test_carthageRequirement_upToNext_codable() throws {
|
||||
let subject: Dependency.CarthageRequirement = .upToNext("3.2.0")
|
||||
XCTAssertCodable(subject)
|
||||
}
|
||||
|
||||
func test_carthageRequirement_atLeast_codable() throws {
|
||||
let subject: Dependency.CarthageRequirement = .atLeast("3.2.0")
|
||||
XCTAssertCodable(subject)
|
||||
}
|
||||
|
||||
func test_carthageRequirement_branch_codable() throws {
|
||||
let subject: Dependency.CarthageRequirement = .branch("branch")
|
||||
XCTAssertCodable(subject)
|
||||
}
|
||||
|
||||
func test_carthageRequirement_revision_codable() throws {
|
||||
let subject: Dependency.CarthageRequirement = .revision("revision")
|
||||
XCTAssertCodable(subject)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
import Foundation
|
||||
import XCTest
|
||||
|
||||
@testable import TuistCore
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class CarthageDependencyTests: TuistTestCase {
|
||||
func test_cartfileValue_github_exact() throws {
|
||||
// Given
|
||||
let dependency = CarthageDependency(origin: .github(path: "Alamofire/Alamofire"), requirement: .exact("1.2.3"), platforms: [.iOS])
|
||||
let expected = #"github "Alamofire/Alamofire" == 1.2.3"#
|
||||
|
||||
// When
|
||||
let got = dependency.cartfileValue
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(got, expected)
|
||||
}
|
||||
|
||||
// MARK: - CarthageDependency.Origin tests
|
||||
|
||||
func test_origin_cartfileValue_github() {
|
||||
// Given
|
||||
let origin: CarthageDependency.Origin = .github(path: "Alamofire/Alamofire")
|
||||
let expected = #"github "Alamofire/Alamofire""#
|
||||
|
||||
// When
|
||||
let got = origin.cartfileValue
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(got, expected)
|
||||
}
|
||||
|
||||
func test_origin_cartfileValue_git() {
|
||||
// Given
|
||||
let origin: CarthageDependency.Origin = .git(path: "https://enterprise.local/desktop/git-error-translations2.git")
|
||||
let expected = #"git "https://enterprise.local/desktop/git-error-translations2.git""#
|
||||
|
||||
// When
|
||||
let got = origin.cartfileValue
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(got, expected)
|
||||
}
|
||||
|
||||
func test_origin_cartfileValue_binary() {
|
||||
// Given
|
||||
let origin: CarthageDependency.Origin = .binary(path: "file:///some/local/path/MyFramework.json")
|
||||
let expected = #"binary "file:///some/local/path/MyFramework.json""#
|
||||
|
||||
// When
|
||||
let got = origin.cartfileValue
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(got, expected)
|
||||
}
|
||||
|
||||
// MARK: - CarthageDependency.Requirement tests
|
||||
|
||||
func test_requirement_cartfileValue_exact() {
|
||||
// Given
|
||||
let origin: CarthageDependency.Requirement = .exact("1.2.3")
|
||||
let expected = #"== 1.2.3"#
|
||||
|
||||
// When
|
||||
let got = origin.cartfileValue
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(got, expected)
|
||||
}
|
||||
|
||||
func test_requirement_cartfileValue_upToNext() {
|
||||
// Given
|
||||
let origin: CarthageDependency.Requirement = .upToNext("3.2.3")
|
||||
let expected = #"~> 3.2.3"#
|
||||
|
||||
// When
|
||||
let got = origin.cartfileValue
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(got, expected)
|
||||
}
|
||||
|
||||
func test_requirement_cartfileValue_atLeast() {
|
||||
// Given
|
||||
let origin: CarthageDependency.Requirement = .atLeast("1.2.1")
|
||||
let expected = #">= 1.2.1"#
|
||||
|
||||
// When
|
||||
let got = origin.cartfileValue
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(got, expected)
|
||||
}
|
||||
|
||||
func test_requirement_cartfileValue_branch() {
|
||||
// Given
|
||||
let origin: CarthageDependency.Requirement = .branch("develop")
|
||||
let expected = #""develop""#
|
||||
|
||||
// When
|
||||
let got = origin.cartfileValue
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(got, expected)
|
||||
}
|
||||
|
||||
func test_requirement_cartfileValue_revision() {
|
||||
// Given
|
||||
let origin: CarthageDependency.Requirement = .revision("1234567898765432qwerty")
|
||||
let expected = #""1234567898765432qwerty""#
|
||||
|
||||
// When
|
||||
let got = origin.cartfileValue
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(got, expected)
|
||||
}
|
||||
}
|
|
@ -36,6 +36,13 @@ final class PlatformTests: XCTestCase {
|
|||
XCTAssertTrue(Platform.tvOS.hasSimulators)
|
||||
}
|
||||
|
||||
func test_carthageDirectory() {
|
||||
XCTAssertEqual(Platform.tvOS.carthageDirectory, "tvOS")
|
||||
XCTAssertEqual(Platform.iOS.carthageDirectory, "iOS")
|
||||
XCTAssertEqual(Platform.watchOS.carthageDirectory, "watchOS")
|
||||
XCTAssertEqual(Platform.macOS.carthageDirectory, "Mac")
|
||||
}
|
||||
|
||||
func test_xcodeSdkRootPath() {
|
||||
// Given
|
||||
let platforms: [Platform] = [
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistSupport
|
||||
import XCTest
|
||||
|
||||
@testable import TuistDependencies
|
||||
@testable import TuistDependenciesTesting
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class CarthageInteractorTests: TuistUnitTestCase {
|
||||
private var subject: CarthageInteractor!
|
||||
|
||||
private var fileHandlerMock: MockFileHandler!
|
||||
private var carthageCommandGenerator: MockCarthageCommandGenerator!
|
||||
private var cartfileContentGenerator: MockCartfileContentGenerator!
|
||||
|
||||
private var temporaryDirectoryPath: AbsolutePath!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
do {
|
||||
temporaryDirectoryPath = try TemporaryDirectory(removeTreeOnDeinit: true).path
|
||||
} catch {
|
||||
XCTFail("Failed to setup TemporaryDirectory")
|
||||
}
|
||||
|
||||
fileHandlerMock = MockFileHandler(temporaryDirectory: { self.temporaryDirectoryPath })
|
||||
carthageCommandGenerator = MockCarthageCommandGenerator()
|
||||
cartfileContentGenerator = MockCartfileContentGenerator()
|
||||
|
||||
subject = CarthageInteractor(fileHandler: fileHandlerMock,
|
||||
carthageCommandGenerator: carthageCommandGenerator,
|
||||
cartfileContentGenerator: cartfileContentGenerator)
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
fileHandlerMock = nil
|
||||
carthageCommandGenerator = nil
|
||||
cartfileContentGenerator = nil
|
||||
|
||||
temporaryDirectoryPath = nil
|
||||
|
||||
subject = nil
|
||||
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func test_fetch_all_for_platforms() throws {
|
||||
// Given
|
||||
let rootPath = try temporaryPath()
|
||||
let temporaryDependenciesDirectory = temporaryDirectoryPath
|
||||
.appending(component: Constants.DependenciesDirectory.carthageDirectoryName)
|
||||
.appending(component: "Build")
|
||||
let dependenciesDirectory = rootPath
|
||||
.appending(component: Constants.DependenciesDirectory.name)
|
||||
|
||||
try fileHandler.touch(temporaryDirectoryPath.appending(components: Constants.DependenciesDirectory.cartfileResolvedName))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "iOS", "Moya.framework", "Info.plist"))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "iOS", "ReactiveMoya.framework", "Info.plist"))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "iOS", "RxMoya.framework", "Info.plist"))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "Mac", "Moya.framework", "Info.plist"))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "Mac", "ReactiveMoya.framework", "Info.plist"))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "Mac", "RxMoya.framework", "Info.plist"))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "watchOS", "Moya.framework", "Info.plist"))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "watchOS", "ReactiveMoya.framework", "Info.plist"))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "watchOS", "RxMoya.framework", "Info.plist"))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "tvOS", "Moya.framework", "Info.plist"))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "tvOS", "ReactiveMoya.framework", "Info.plist"))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "tvOS", "RxMoya.framework", "Info.plist"))
|
||||
|
||||
let stubbedDependencies = [
|
||||
CarthageDependency(origin: .github(path: "Moya"), requirement: .exact("1.1.1"), platforms: [.iOS]),
|
||||
]
|
||||
let stubbedCommand = ["carthage", "bootstrap", "--project-directory", temporaryDirectoryPath.pathString, "--platform iOS", "--cache-builds", "--new-resolver"]
|
||||
|
||||
carthageCommandGenerator.commandStub = { _, _ in stubbedCommand }
|
||||
|
||||
system.whichStub = { _ in "1.0.0" }
|
||||
system.succeedCommand(stubbedCommand)
|
||||
|
||||
// When
|
||||
try subject.fetch(dependenciesDirectory: dependenciesDirectory, dependencies: stubbedDependencies)
|
||||
|
||||
// Then
|
||||
let expectedCartfileResolvedPath = dependenciesDirectory
|
||||
.appending(component: Constants.DependenciesDirectory.lockfilesDirectoryName)
|
||||
.appending(component: Constants.DependenciesDirectory.cartfileResolvedName)
|
||||
let expectedCarthageDirectory = dependenciesDirectory
|
||||
.appending(component: Constants.DependenciesDirectory.carthageDirectoryName)
|
||||
|
||||
XCTAssertTrue(fileHandler.exists(expectedCartfileResolvedPath))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "iOS", "Moya.framework", "Info.plist")))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "iOS", "ReactiveMoya.framework", "Info.plist")))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "iOS", "RxMoya.framework", "Info.plist")))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "Mac", "Moya.framework", "Info.plist")))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "Mac", "ReactiveMoya.framework", "Info.plist")))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "Mac", "RxMoya.framework", "Info.plist")))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "watchOS", "Moya.framework", "Info.plist")))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "watchOS", "ReactiveMoya.framework", "Info.plist")))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "watchOS", "RxMoya.framework", "Info.plist")))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "tvOS", "Moya.framework", "Info.plist")))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "tvOS", "ReactiveMoya.framework", "Info.plist")))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "tvOS", "RxMoya.framework", "Info.plist")))
|
||||
|
||||
XCTAssertTrue(carthageCommandGenerator.invokedCommand)
|
||||
XCTAssertEqual(carthageCommandGenerator.invokedCommandParameters?.path, temporaryDirectoryPath)
|
||||
XCTAssertEqual(carthageCommandGenerator.invokedCommandParameters?.platforms, [.iOS])
|
||||
|
||||
XCTAssertTrue(cartfileContentGenerator.invokedCartfileContent)
|
||||
XCTAssertEqual(cartfileContentGenerator.invokedCartfileContentParameters, stubbedDependencies)
|
||||
}
|
||||
|
||||
func test_fetch_only_one_platform() throws {
|
||||
// Given
|
||||
let rootPath = try temporaryPath()
|
||||
let temporaryDependenciesDirectory = temporaryDirectoryPath
|
||||
.appending(component: Constants.DependenciesDirectory.carthageDirectoryName)
|
||||
.appending(component: "Build")
|
||||
let dependenciesDirectory = rootPath
|
||||
.appending(component: Constants.DependenciesDirectory.name)
|
||||
|
||||
try fileHandler.touch(temporaryDirectoryPath.appending(components: Constants.DependenciesDirectory.cartfileResolvedName))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "iOS", "Moya.framework", "Info.plist"))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "iOS", "ReactiveMoya.framework", "Info.plist"))
|
||||
try fileHandler.touch(temporaryDependenciesDirectory.appending(components: "iOS", "RxMoya.framework", "Info.plist"))
|
||||
|
||||
let stubbedDependencies = [
|
||||
CarthageDependency(origin: .github(path: "Moya"), requirement: .exact("1.1.1"), platforms: [.iOS]),
|
||||
]
|
||||
let stubbedCommand = ["carthage", "bootstrap", "--project-directory", temporaryDirectoryPath.pathString, "--platform iOS", "--cache-builds", "--new-resolver"]
|
||||
|
||||
carthageCommandGenerator.commandStub = { _, _ in stubbedCommand }
|
||||
|
||||
system.whichStub = { _ in "1.0.0" }
|
||||
system.succeedCommand(stubbedCommand)
|
||||
|
||||
// When
|
||||
try subject.fetch(dependenciesDirectory: dependenciesDirectory, dependencies: stubbedDependencies)
|
||||
|
||||
// Then
|
||||
let expectedCartfileResolvedPath = dependenciesDirectory
|
||||
.appending(component: Constants.DependenciesDirectory.lockfilesDirectoryName)
|
||||
.appending(component: Constants.DependenciesDirectory.cartfileResolvedName)
|
||||
let expectedCarthageDirectory = dependenciesDirectory
|
||||
.appending(component: Constants.DependenciesDirectory.carthageDirectoryName)
|
||||
|
||||
XCTAssertTrue(fileHandler.exists(expectedCartfileResolvedPath))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "iOS", "Moya.framework", "Info.plist")))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "iOS", "ReactiveMoya.framework", "Info.plist")))
|
||||
XCTAssertTrue(fileHandler.exists(expectedCarthageDirectory.appending(components: "iOS", "RxMoya.framework", "Info.plist")))
|
||||
XCTAssertFalse(fileHandler.exists(expectedCarthageDirectory.appending(components: "Mac", "Moya.framework", "Info.plist")))
|
||||
XCTAssertFalse(fileHandler.exists(expectedCarthageDirectory.appending(components: "Mac", "ReactiveMoya.framework", "Info.plist")))
|
||||
XCTAssertFalse(fileHandler.exists(expectedCarthageDirectory.appending(components: "Mac", "RxMoya.framework", "Info.plist")))
|
||||
XCTAssertFalse(fileHandler.exists(expectedCarthageDirectory.appending(components: "watchOS", "Moya.framework", "Info.plist")))
|
||||
XCTAssertFalse(fileHandler.exists(expectedCarthageDirectory.appending(components: "watchOS", "ReactiveMoya.framework", "Info.plist")))
|
||||
XCTAssertFalse(fileHandler.exists(expectedCarthageDirectory.appending(components: "watchOS", "RxMoya.framework", "Info.plist")))
|
||||
XCTAssertFalse(fileHandler.exists(expectedCarthageDirectory.appending(components: "tvOS", "Moya.framework", "Info.plist")))
|
||||
XCTAssertFalse(fileHandler.exists(expectedCarthageDirectory.appending(components: "tvOS", "ReactiveMoya.framework", "Info.plist")))
|
||||
XCTAssertFalse(fileHandler.exists(expectedCarthageDirectory.appending(components: "tvOS", "RxMoya.framework", "Info.plist")))
|
||||
|
||||
XCTAssertTrue(carthageCommandGenerator.invokedCommand)
|
||||
XCTAssertEqual(carthageCommandGenerator.invokedCommandParameters?.path, temporaryDirectoryPath)
|
||||
XCTAssertEqual(carthageCommandGenerator.invokedCommandParameters?.platforms, [.iOS])
|
||||
|
||||
XCTAssertTrue(cartfileContentGenerator.invokedCartfileContent)
|
||||
XCTAssertEqual(cartfileContentGenerator.invokedCartfileContentParameters, stubbedDependencies)
|
||||
}
|
||||
}
|
77
Tests/TuistDependenciesTests/Carthage/Generators/CartfileContentGenetatorTests.swift
vendored
Normal file
77
Tests/TuistDependenciesTests/Carthage/Generators/CartfileContentGenetatorTests.swift
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
import TuistCore
|
||||
import TuistSupport
|
||||
import XCTest
|
||||
|
||||
@testable import TuistDependencies
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class CartfileContentGenetatorTests: TuistUnitTestCase {
|
||||
private var subject: CartfileContentGenerator!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
subject = CartfileContentGenerator()
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
subject = nil
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func test_build_no_dependencies() throws {
|
||||
// Given
|
||||
let dependencies: [CarthageDependency] = []
|
||||
let expected = """
|
||||
"""
|
||||
|
||||
// When
|
||||
let got = subject.cartfileContent(for: dependencies)
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(got, expected)
|
||||
}
|
||||
|
||||
func test_build_single_dependency() throws {
|
||||
// Given
|
||||
let dependencies: [CarthageDependency] = [
|
||||
.init(origin: .github(path: "Dependency/Dependency"), requirement: .exact("1.1.1"), platforms: [.iOS]),
|
||||
]
|
||||
let expected = """
|
||||
github "Dependency/Dependency" == 1.1.1
|
||||
"""
|
||||
|
||||
// When
|
||||
let got = subject.cartfileContent(for: dependencies)
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(got, expected)
|
||||
}
|
||||
|
||||
func test_build_multiple_dependencies() throws {
|
||||
// Given
|
||||
let dependencies: [CarthageDependency] = [
|
||||
.init(origin: .github(path: "Dependency/Dependency"), requirement: .exact("2.1.1"), platforms: [.iOS]),
|
||||
.init(origin: .github(path: "XYZ/Foo"), requirement: .revision("revision"), platforms: [.tvOS, .macOS]),
|
||||
.init(origin: .git(path: "Foo/Bar"), requirement: .atLeast("1.0.1"), platforms: [.iOS]),
|
||||
.init(origin: .github(path: "Qwerty/bar"), requirement: .branch("develop"), platforms: [.watchOS]),
|
||||
.init(origin: .github(path: "XYZ/Bar"), requirement: .upToNext("1.1.1"), platforms: [.iOS]),
|
||||
.init(origin: .binary(path: "https://my.domain.com/release/MyFramework.json"), requirement: .upToNext("1.0.1"), platforms: [.iOS]),
|
||||
.init(origin: .binary(path: "file:///some/local/path/MyFramework.json"), requirement: .atLeast("1.1.0"), platforms: [.iOS]),
|
||||
]
|
||||
let expected = """
|
||||
github "Dependency/Dependency" == 2.1.1
|
||||
github "XYZ/Foo" "revision"
|
||||
git "Foo/Bar" >= 1.0.1
|
||||
github "Qwerty/bar" "develop"
|
||||
github "XYZ/Bar" ~> 1.1.1
|
||||
binary "https://my.domain.com/release/MyFramework.json" ~> 1.0.1
|
||||
binary "file:///some/local/path/MyFramework.json" >= 1.1.0
|
||||
"""
|
||||
|
||||
// When
|
||||
let got = subject.cartfileContent(for: dependencies)
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(got, expected)
|
||||
}
|
||||
}
|
48
Tests/TuistDependenciesTests/Carthage/Generators/CarthageCommandGeneratorTests.swift
vendored
Normal file
48
Tests/TuistDependenciesTests/Carthage/Generators/CarthageCommandGeneratorTests.swift
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
import TuistCore
|
||||
import TuistSupport
|
||||
import XCTest
|
||||
|
||||
@testable import TuistDependencies
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class CarthageCommandGeneratorTests: TuistUnitTestCase {
|
||||
private var subject: CarthageCommandGenerator!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
subject = CarthageCommandGenerator()
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
subject = nil
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func test_command() throws {
|
||||
// Given
|
||||
let stubbedPath = try temporaryPath()
|
||||
let expected = "carthage bootstrap --project-directory \(stubbedPath.pathString) --use-netrc --cache-builds --new-resolver"
|
||||
|
||||
// When
|
||||
let got = subject
|
||||
.command(path: stubbedPath, platforms: nil)
|
||||
.joined(separator: " ")
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(got, expected)
|
||||
}
|
||||
|
||||
func test_command_with_platforms() throws {
|
||||
// Given
|
||||
let stubbedPath = try temporaryPath()
|
||||
let expected = "carthage bootstrap --project-directory \(stubbedPath.pathString) --platform iOS --use-netrc --cache-builds --new-resolver"
|
||||
|
||||
// When
|
||||
let got = subject
|
||||
.command(path: stubbedPath, platforms: [.iOS])
|
||||
.joined(separator: " ")
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(got, expected)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import TuistCore
|
||||
import TuistSupport
|
||||
import XCTest
|
||||
|
||||
@testable import TuistDependencies
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class CocoaPodsInteractorTests: TuistUnitTestCase {
|
||||
private var subject: CocoaPodsInteractor!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
subject = CocoaPodsInteractor()
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
subject = nil
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func test_fetch() throws {
|
||||
// Given
|
||||
let stubbedPath = try temporaryPath()
|
||||
|
||||
// When/Then
|
||||
XCTAssertThrowsSpecific(try subject.fetch(dependenciesDirectory: stubbedPath), CocoaPodsInteractorError.unimplemented)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistSupport
|
||||
import XCTest
|
||||
|
||||
@testable import TuistDependencies
|
||||
@testable import TuistDependenciesTesting
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class DependenciesControllerTests: TuistUnitTestCase {
|
||||
private var subject: DependenciesController!
|
||||
|
||||
private var carthageInteractor: MockCarthageInteractor!
|
||||
private var cocoaPodsInteractor: MockCocoaPodsInteractor!
|
||||
private var swiftPackageManagerInteractor: MockSwiftPackageManagerInteractor!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
carthageInteractor = MockCarthageInteractor()
|
||||
cocoaPodsInteractor = MockCocoaPodsInteractor()
|
||||
swiftPackageManagerInteractor = MockSwiftPackageManagerInteractor()
|
||||
|
||||
subject = DependenciesController(carthageInteractor: carthageInteractor,
|
||||
cocoaPodsInteractor: cocoaPodsInteractor,
|
||||
swiftPackageManagerInteractor: swiftPackageManagerInteractor)
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
subject = nil
|
||||
|
||||
carthageInteractor = nil
|
||||
cocoaPodsInteractor = nil
|
||||
swiftPackageManagerInteractor = nil
|
||||
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func test_fetch() throws {
|
||||
// Given
|
||||
let rootPath = try temporaryPath()
|
||||
let dependenciesDirectoryPath = rootPath
|
||||
.appending(component: Constants.tuistDirectoryName)
|
||||
.appending(component: Constants.DependenciesDirectory.name)
|
||||
|
||||
let stubbedCarthageDependencies = [
|
||||
CarthageDependency(origin: .github(path: "Moya"), requirement: .exact("1.1.1"), platforms: [.iOS]),
|
||||
CarthageDependency(origin: .github(path: "RxSwift"), requirement: .exact("2.0.0"), platforms: [.iOS]),
|
||||
]
|
||||
let stubbedDependencies = Dependencies(carthageDependencies: stubbedCarthageDependencies)
|
||||
|
||||
// When
|
||||
try subject.fetch(at: rootPath, dependencies: stubbedDependencies)
|
||||
|
||||
// Then
|
||||
XCTAssertTrue(carthageInteractor.invokedFetch)
|
||||
XCTAssertEqual(carthageInteractor.invokedFetchParameters?.dependenciesDirectory, dependenciesDirectoryPath)
|
||||
XCTAssertEqual(carthageInteractor.invokedFetchParameters?.dependencies, stubbedCarthageDependencies)
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
import Foundation
|
||||
import XCTest
|
||||
|
||||
@testable import TuistDependencies
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class EmptyTests: TuistUnitTestCase {
|
||||
func test_empty() {
|
||||
// Given
|
||||
|
||||
// When
|
||||
|
||||
// Then
|
||||
XCTAssertTrue(true)
|
||||
}
|
||||
}
|
||||
|
||||
#warning("Remove this file when you will start adding files to this target.")
|
|
@ -0,0 +1,28 @@
|
|||
import TuistCore
|
||||
import TuistSupport
|
||||
import XCTest
|
||||
|
||||
@testable import TuistDependencies
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class SwiftPackageManagerInteractorTests: TuistUnitTestCase {
|
||||
private var subject: SwiftPackageManagerInteractor!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
subject = SwiftPackageManagerInteractor()
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
subject = nil
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func test_fetch() throws {
|
||||
// Given
|
||||
let stubbedPath = try temporaryPath()
|
||||
|
||||
// When/Then
|
||||
XCTAssertThrowsSpecific(try subject.fetch(dependenciesDirectory: stubbedPath), SwiftPackageManagerInteractorError.unimplemented)
|
||||
}
|
||||
}
|
|
@ -6,10 +6,12 @@ import XCTest
|
|||
@testable import TuistCoreTesting
|
||||
@testable import TuistDependenciesTesting
|
||||
@testable import TuistKit
|
||||
@testable import TuistLoaderTesting
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class DependenciesFetchServiceTests: TuistUnitTestCase {
|
||||
private var dependenciesController: MockDependenciesController!
|
||||
private var dependenciesModelLoader: MockDependenciesModelLoader!
|
||||
|
||||
private var subject: DependenciesFetchService!
|
||||
|
||||
|
@ -17,40 +19,42 @@ final class DependenciesFetchServiceTests: TuistUnitTestCase {
|
|||
super.setUp()
|
||||
|
||||
dependenciesController = MockDependenciesController()
|
||||
dependenciesModelLoader = MockDependenciesModelLoader()
|
||||
|
||||
subject = DependenciesFetchService(dependenciesController: dependenciesController)
|
||||
subject = DependenciesFetchService(dependenciesController: dependenciesController,
|
||||
dependenciesModelLoader: dependenciesModelLoader)
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
subject = nil
|
||||
|
||||
dependenciesController = nil
|
||||
dependenciesModelLoader = nil
|
||||
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func test_run() throws {
|
||||
// Given
|
||||
let path = try temporaryPath()
|
||||
let stubbedPath = try temporaryPath()
|
||||
let stubbedDependencies = Dependencies(
|
||||
carthageDependencies: [
|
||||
CarthageDependency(origin: .github(path: "Dependency1"), requirement: .exact("1.1.1"), platforms: [.iOS, .macOS]),
|
||||
]
|
||||
)
|
||||
dependenciesModelLoader.loadDependenciesStub = { _ in stubbedDependencies }
|
||||
|
||||
// When
|
||||
try subject.run(path: path.pathString)
|
||||
try subject.run(path: stubbedPath.pathString)
|
||||
|
||||
// Then
|
||||
XCTAssertTrue(dependenciesController.invokedFetch)
|
||||
XCTAssertEqual(dependenciesController.invokedFetchCount, 1)
|
||||
XCTAssertEqual(dependenciesController.invokedFetchParameters, path)
|
||||
XCTAssertEqual(dependenciesController.invokedFetchParameters?.path, stubbedPath)
|
||||
XCTAssertEqual(dependenciesController.invokedFetchParameters?.dependencies, stubbedDependencies)
|
||||
|
||||
XCTAssertFalse(dependenciesController.invokedUpdate)
|
||||
}
|
||||
|
||||
func test_run_thorws_an_error() throws {
|
||||
// Given
|
||||
let path = try temporaryPath()
|
||||
let error = TestError("Failed fetching!")
|
||||
dependenciesController.stubbedFetchError = error
|
||||
|
||||
// When/Then
|
||||
XCTAssertThrowsSpecific(try subject.run(path: path.pathString), error)
|
||||
XCTAssertTrue(dependenciesModelLoader.invokedLoadDependencies)
|
||||
XCTAssertEqual(dependenciesModelLoader.invokedLoadDependenciesCount, 1)
|
||||
XCTAssertEqual(dependenciesModelLoader.invokedLoadDependenciesParameters, stubbedPath)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,12 @@ import XCTest
|
|||
@testable import TuistCoreTesting
|
||||
@testable import TuistDependenciesTesting
|
||||
@testable import TuistKit
|
||||
@testable import TuistLoaderTesting
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class DependenciesUpdateServiceTests: TuistUnitTestCase {
|
||||
private var dependenciesController: MockDependenciesController!
|
||||
private var dependenciesModelLoader: MockDependenciesModelLoader!
|
||||
|
||||
private var subject: DependenciesUpdateService!
|
||||
|
||||
|
@ -17,40 +19,32 @@ final class DependenciesUpdateServiceTests: TuistUnitTestCase {
|
|||
super.setUp()
|
||||
|
||||
dependenciesController = MockDependenciesController()
|
||||
dependenciesModelLoader = MockDependenciesModelLoader()
|
||||
|
||||
subject = DependenciesUpdateService(dependenciesController: dependenciesController)
|
||||
subject = DependenciesUpdateService(dependenciesController: dependenciesController,
|
||||
dependenciesModelLoader: dependenciesModelLoader)
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
subject = nil
|
||||
|
||||
dependenciesController = nil
|
||||
dependenciesModelLoader = nil
|
||||
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func test_run() throws {
|
||||
// Given
|
||||
let path = try temporaryPath()
|
||||
|
||||
// When
|
||||
try subject.run(path: path.pathString)
|
||||
|
||||
// Then
|
||||
XCTAssertTrue(dependenciesController.invokedUpdate)
|
||||
XCTAssertEqual(dependenciesController.invokedUpdateCount, 1)
|
||||
XCTAssertEqual(dependenciesController.invokedUpdateParameters, path)
|
||||
|
||||
XCTAssertFalse(dependenciesController.invokedFetch)
|
||||
}
|
||||
|
||||
func test_run_thorws_an_error() throws {
|
||||
// Given
|
||||
let path = try temporaryPath()
|
||||
let error = TestError("Failed fetching!")
|
||||
dependenciesController.stubbedUpdateError = error
|
||||
let stubbedPath = try temporaryPath()
|
||||
let stubbedDependencies = Dependencies(
|
||||
carthageDependencies: [
|
||||
CarthageDependency(origin: .github(path: "Dependency1"), requirement: .exact("1.1.1"), platforms: [.iOS, .macOS]),
|
||||
]
|
||||
)
|
||||
dependenciesModelLoader.loadDependenciesStub = { _ in stubbedDependencies }
|
||||
|
||||
// When/Then
|
||||
XCTAssertThrowsSpecific(try subject.run(path: path.pathString), error)
|
||||
XCTAssertThrowsSpecific(try subject.run(path: stubbedPath.pathString), DependenciesUpdateServiceError.unimplemented)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
import Foundation
|
||||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistSupport
|
||||
import XCTest
|
||||
|
||||
@testable import ProjectDescription
|
||||
@testable import TuistLoader
|
||||
@testable import TuistLoaderTesting
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class DependenciesModelLoaderTests: TuistUnitTestCase {
|
||||
private var manifestLoader: MockManifestLoader!
|
||||
|
||||
private var subject: DependenciesModelLoader!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
manifestLoader = MockManifestLoader()
|
||||
subject = DependenciesModelLoader(manifestLoader: manifestLoader)
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
subject = nil
|
||||
manifestLoader = nil
|
||||
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func test_loadDependencies() throws {
|
||||
// Given
|
||||
let stubbedPath = try temporaryPath()
|
||||
manifestLoader.loadDependenciesStub = { _ in
|
||||
Dependencies([
|
||||
.carthage(origin: .github(path: "Dependency1"), requirement: .exact("1.1.1"), platforms: [.iOS]),
|
||||
.carthage(origin: .git(path: "Dependency1"), requirement: .exact("2.3.4"), platforms: [.macOS, .tvOS]),
|
||||
])
|
||||
}
|
||||
|
||||
// When
|
||||
let model = try subject.loadDependencies(at: stubbedPath)
|
||||
|
||||
// Then
|
||||
let expectedCarthageModels: [TuistCore.CarthageDependency] = [
|
||||
CarthageDependency(origin: .github(path: "Dependency1"), requirement: .exact("1.1.1"), platforms: Set([.iOS])),
|
||||
CarthageDependency(origin: .git(path: "Dependency1"), requirement: .exact("2.3.4"), platforms: Set([.macOS, .tvOS])),
|
||||
]
|
||||
let expectedDependenciesModel = TuistCore.Dependencies(carthageDependencies: expectedCarthageModels)
|
||||
|
||||
XCTAssertEqual(model, expectedDependenciesModel)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
import Foundation
|
||||
import ProjectDescription
|
||||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistSupport
|
||||
import XCTest
|
||||
|
||||
@testable import TuistLoader
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class DependenciesManifestMapperTests: TuistUnitTestCase {
|
||||
func test_dependencies() throws {
|
||||
// Given
|
||||
let manifest: ProjectDescription.Dependencies = Dependencies([
|
||||
.carthage(origin: .github(path: "Dependency1"), requirement: .exact("1.1.1"), platforms: [.iOS]),
|
||||
.carthage(origin: .git(path: "Dependency.git"), requirement: .branch("BranchName"), platforms: [.macOS]),
|
||||
.carthage(origin: .binary(path: "DependencyXYZ"), requirement: .atLeast("2.3.1"), platforms: [.tvOS]),
|
||||
])
|
||||
|
||||
// When
|
||||
let model = try TuistCore.Dependencies.from(manifest: manifest)
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(model.carthageDependencies, [
|
||||
TuistCore.CarthageDependency(origin: .github(path: "Dependency1"), requirement: .exact("1.1.1"), platforms: Set([.iOS])),
|
||||
TuistCore.CarthageDependency(origin: .git(path: "Dependency.git"), requirement: .branch("BranchName"), platforms: Set([.macOS])),
|
||||
TuistCore.CarthageDependency(origin: .binary(path: "DependencyXYZ"), requirement: .atLeast("2.3.1"), platforms: Set([.tvOS])),
|
||||
])
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
import Foundation
|
||||
import ProjectDescription
|
||||
import TSCBasic
|
||||
import TuistCore
|
||||
import TuistSupport
|
||||
import XCTest
|
||||
|
||||
@testable import TuistLoader
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class PlatformManifestMapperTests: TuistUnitTestCase {
|
||||
func test_platform_iOS() throws {
|
||||
// Given
|
||||
let manifest: ProjectDescription.Platform = .iOS
|
||||
|
||||
// When
|
||||
let model = try TuistCore.Platform.from(manifest: manifest)
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(model, .iOS)
|
||||
}
|
||||
|
||||
func test_platform_tvOS() throws {
|
||||
// Given
|
||||
let manifest: ProjectDescription.Platform = .tvOS
|
||||
|
||||
// When
|
||||
let model = try TuistCore.Platform.from(manifest: manifest)
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(model, .tvOS)
|
||||
}
|
||||
|
||||
func test_platform_macOS() throws {
|
||||
// Given
|
||||
let manifest: ProjectDescription.Platform = .macOS
|
||||
|
||||
// When
|
||||
let model = try TuistCore.Platform.from(manifest: manifest)
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(model, .macOS)
|
||||
}
|
||||
|
||||
func test_platform_watchOS() throws {
|
||||
// Given
|
||||
let manifest: ProjectDescription.Platform = .watchOS
|
||||
|
||||
// When
|
||||
let model = try TuistCore.Platform.from(manifest: manifest)
|
||||
|
||||
// Then
|
||||
XCTAssertEqual(model, .watchOS)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
Feature: Install dependencies Tuist.
|
||||
|
||||
Scenario: The project is an application with framework and tests and Dependencies.swift (app_with_framework_and_tests_and_dependencies)
|
||||
Given that tuist is available
|
||||
And I have a working directory
|
||||
Then I copy the fixture app_with_framework_and_tests_and_dependencies into the working directory
|
||||
Then tuist fetches dependencies
|
||||
Then a directory Tuist/Dependencies/Carthage/Mac/Alamofire.framework exists
|
||||
Then a file Tuist/Dependencies/Carthage/.Alamofire.version exists
|
||||
Then a file Tuist/Dependencies/Lockfiles/Cartfile.resolved exists
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
Then(/tuist fetches dependencies/) do
|
||||
out, err, status = Open3.capture3("swift", "run", "tuist", "dependencies", "fetch", "--path", @dir)
|
||||
flunk(err) unless status.success?
|
||||
end
|
||||
|
||||
Then(/tuist updates dependencies/) do
|
||||
out, err, status = Open3.capture3("swift", "run", "tuist", "dependencies", "update", "--path", @dir)
|
||||
flunk(err) unless status.success?
|
||||
end
|
|
@ -119,7 +119,12 @@ end
|
|||
|
||||
Then(/^a file (.+) exists$/) do |file|
|
||||
file_path = File.join(@dir, file)
|
||||
assert(File.exist?(file_path), "#{file_path} does not exist")
|
||||
assert(File.file?(file_path), "#{file_path} does not exist")
|
||||
end
|
||||
|
||||
Then(/^a directory (.+) exists$/) do |directory|
|
||||
directory_path = File.join(@dir, directory)
|
||||
assert(Dir.exist?(directory_path), "#{directory_path} does not exist")
|
||||
end
|
||||
|
||||
Then("the product {string} with destination {string} contains the appClip {string} with architecture {string}") do |product, destination, app_clip, architecture|
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
### macOS ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### Xcode ###
|
||||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
## User settings
|
||||
xcuserdata/
|
||||
|
||||
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
|
||||
*.xcscmblueprint
|
||||
*.xccheckout
|
||||
|
||||
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
|
||||
build/
|
||||
DerivedData/
|
||||
*.moved-aside
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
|
||||
### Xcode Patch ###
|
||||
*.xcodeproj/*
|
||||
!*.xcodeproj/project.pbxproj
|
||||
!*.xcodeproj/xcshareddata/
|
||||
!*.xcworkspace/contents.xcworkspacedata
|
||||
/*.gcno
|
||||
|
||||
### Projects ###
|
||||
*.xcodeproj
|
||||
*.xcworkspace
|
||||
|
||||
### Tuist managed dependencies ###
|
||||
Tuist/Dependencies
|
|
@ -0,0 +1,22 @@
|
|||
import Framework
|
||||
import UIKit
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
var window: UIWindow?
|
||||
var framework: FrameworkClass = FrameworkClass()
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
||||
window = UIWindow(frame: UIScreen.main.bounds)
|
||||
let viewController = UIViewController()
|
||||
viewController.view.backgroundColor = .white
|
||||
window?.rootViewController = viewController
|
||||
window?.makeKeyAndVisible()
|
||||
return true
|
||||
}
|
||||
|
||||
func hello() -> String {
|
||||
return "AppDelegate.hello()"
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
import Foundation
|
||||
import XCTest
|
||||
|
||||
@testable import App
|
||||
|
||||
final class AppTests: XCTestCase {
|
||||
|
||||
func testHello() {
|
||||
let sut = AppDelegate()
|
||||
|
||||
XCTAssertEqual("AppDelegate.hello()", sut.hello())
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
import Foundation
|
||||
|
||||
public class FrameworkClass {
|
||||
public init() {}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import Foundation
|
||||
import XCTest
|
||||
@testable import Framework
|
||||
|
||||
final class FrameworkTests: XCTestCase {
|
||||
var subject: FrameworkClass = FrameworkClass()
|
||||
|
||||
func testExample() {
|
||||
print("Framework tests example")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
import ProjectDescription
|
||||
|
||||
let project = Project(
|
||||
name: "App",
|
||||
targets: [
|
||||
Target(
|
||||
name: "App",
|
||||
platform: .iOS,
|
||||
product: .app,
|
||||
bundleId: "io.tuist.app",
|
||||
infoPlist: .default,
|
||||
sources: "App/**",
|
||||
dependencies: [
|
||||
.target(name: "Framework"),
|
||||
]
|
||||
),
|
||||
Target(
|
||||
name: "AppTests",
|
||||
platform: .iOS,
|
||||
product: .unitTests,
|
||||
bundleId: "io.tuist.appTests",
|
||||
infoPlist: .default,
|
||||
sources: "AppTests/**",
|
||||
dependencies: [
|
||||
.target(name: "App"),
|
||||
]
|
||||
),
|
||||
Target(
|
||||
name: "Framework",
|
||||
platform: .iOS,
|
||||
product: .framework,
|
||||
bundleId: "io.tuist.framework",
|
||||
infoPlist: .default,
|
||||
sources: "Framework/**",
|
||||
dependencies: [
|
||||
]
|
||||
),
|
||||
Target(
|
||||
name: "FrameworkTests",
|
||||
platform: .iOS,
|
||||
product: .unitTests,
|
||||
bundleId: "io.tuist.frameworkTests",
|
||||
infoPlist: .default,
|
||||
sources: "FrameworkTests/**",
|
||||
dependencies: [
|
||||
.target(name: "Framework"),
|
||||
]
|
||||
),
|
||||
],
|
||||
schemes: [
|
||||
Scheme(
|
||||
name: "AppCustomScheme",
|
||||
buildAction: BuildAction(targets: [TargetReference("App")])
|
||||
)
|
||||
]
|
||||
)
|
|
@ -0,0 +1,6 @@
|
|||
import ProjectDescription
|
||||
|
||||
let config = Config(
|
||||
generationOptions: [
|
||||
]
|
||||
)
|
|
@ -0,0 +1,5 @@
|
|||
import ProjectDescription
|
||||
|
||||
let dependencies = Dependencies([
|
||||
.carthage(origin: .github(path: "Alamofire/Alamofire"), requirement: .exact("5.0.4"), platforms: [.macOS])
|
||||
])
|
|
@ -1,5 +1,8 @@
|
|||
import ProjectDescription
|
||||
|
||||
let dependencies = Dependencies([
|
||||
.carthage(name: "Alamofire", requirement: .exact("5.3.0"), platforms: [.iOS]),
|
||||
])
|
||||
let dependencies = Dependencies(
|
||||
carthage: [
|
||||
.init(name: "Alamofire/Alamofire", requirement: .exact("5.0.4"), platforms: [.macOS]),
|
||||
.init(name: "Swinject/Swinject", requirement: .exact("2.7.1"), platforms: [.macOS]),
|
||||
]
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue