diff --git a/Sources/Commands/Snippets/Cards/SnippetCard.swift b/Sources/Commands/Snippets/Cards/SnippetCard.swift index 1f9af16931e..ab524bca617 100644 --- a/Sources/Commands/Snippets/Cards/SnippetCard.swift +++ b/Sources/Commands/Snippets/Cards/SnippetCard.swift @@ -87,7 +87,7 @@ struct SnippetCard: Card { func runExample() throws { print("Building '\(snippet.path)'\n") - let buildSystem = try swiftTool.createBuildSystem(explicitProduct: snippet.name) + let buildSystem = try swiftTool.createBuildSystem() try buildSystem.build(subset: .product(snippet.name)) let executablePath = try swiftTool.buildParameters().buildPath.appending(component: snippet.name) if let exampleTarget = try buildSystem.getPackageGraph().allTargets.first(where: { $0.name == snippet.name }) { diff --git a/Sources/Commands/SwiftBuildTool.swift b/Sources/Commands/SwiftBuildTool.swift index 15370980f5c..740bae0dddd 100644 --- a/Sources/Commands/SwiftBuildTool.swift +++ b/Sources/Commands/SwiftBuildTool.swift @@ -104,7 +104,7 @@ public struct SwiftBuildTool: SwiftCommand { guard let subset = options.buildSubset(observabilityScope: swiftTool.observabilityScope) else { throw ExitCode.failure } - let buildSystem = try swiftTool.createBuildSystem(explicitProduct: options.product) + let buildSystem = try swiftTool.createBuildSystem() do { try buildSystem.build(subset: subset) } catch _ as Diagnostics { diff --git a/Sources/Commands/SwiftRunTool.swift b/Sources/Commands/SwiftRunTool.swift index 8b1bb79009d..5c64ca73f8c 100644 --- a/Sources/Commands/SwiftRunTool.swift +++ b/Sources/Commands/SwiftRunTool.swift @@ -111,9 +111,7 @@ public struct SwiftRunTool: SwiftCommand { case .repl: // Load a custom package graph which has a special product for REPL. let graphLoader = { - try swiftTool.loadPackageGraph( - explicitProduct: self.options.executable, - createREPLProduct: true) + try swiftTool.loadPackageGraph(createREPLProduct: true) } let buildParameters = try swiftTool.buildParameters() @@ -145,7 +143,7 @@ public struct SwiftRunTool: SwiftCommand { case .debugger: do { - let buildSystem = try swiftTool.createBuildSystem(explicitProduct: options.executable) + let buildSystem = try swiftTool.createBuildSystem() let productName = try findProductName(in: buildSystem.getPackageGraph()) if options.shouldBuildTests { try buildSystem.build(subset: .allIncludingTests) @@ -189,7 +187,7 @@ public struct SwiftRunTool: SwiftCommand { swiftTool.redirectStdoutToStderr() do { - let buildSystem = try swiftTool.createBuildSystem(explicitProduct: options.executable) + let buildSystem = try swiftTool.createBuildSystem() let productName = try findProductName(in: buildSystem.getPackageGraph()) if options.shouldBuildTests { try buildSystem.build(subset: .allIncludingTests) diff --git a/Sources/Commands/SwiftTool.swift b/Sources/Commands/SwiftTool.swift index 541c148b53e..beb69c3b70e 100644 --- a/Sources/Commands/SwiftTool.swift +++ b/Sources/Commands/SwiftTool.swift @@ -694,11 +694,8 @@ public class SwiftTool { /// Fetch and load the complete package graph. /// - /// - Parameters: - /// - explicitProduct: The product specified on the command line to a “swift run” or “swift build” command. This allows executables from dependencies to be run directly without having to hook them up to any particular target. @discardableResult func loadPackageGraph( - explicitProduct: String? = nil, createMultipleTestProducts: Bool = false, createREPLProduct: Bool = false ) throws -> PackageGraph { @@ -708,7 +705,6 @@ public class SwiftTool { // Fetch and load the package graph. let graph = try workspace.loadPackageGraph( rootInput: getWorkspaceRoot(), - explicitProduct: explicitProduct, createMultipleTestProducts: createMultipleTestProducts, createREPLProduct: createREPLProduct, forceResolvedVersions: options.forceResolvedVersions, @@ -806,9 +802,9 @@ public class SwiftTool { return true } - func createBuildOperation(explicitProduct: String? = nil, cacheBuildManifest: Bool = true) throws -> BuildOperation { + func createBuildOperation(cacheBuildManifest: Bool = true) throws -> BuildOperation { // Load a custom package graph which has a special product for REPL. - let graphLoader = { try self.loadPackageGraph(explicitProduct: explicitProduct) } + let graphLoader = { try self.loadPackageGraph() } // Construct the build operation. let buildOp = try BuildOperation( @@ -827,11 +823,11 @@ public class SwiftTool { return buildOp } - func createBuildSystem(explicitProduct: String? = nil, buildParameters: BuildParameters? = nil) throws -> BuildSystem { + func createBuildSystem(buildParameters: BuildParameters? = nil) throws -> BuildSystem { let buildSystem: BuildSystem switch options.buildSystem { case .native: - let graphLoader = { try self.loadPackageGraph(explicitProduct: explicitProduct) } + let graphLoader = { try self.loadPackageGraph() } let pluginInvoker = { try self.invokePlugins(graph: $0) } buildSystem = try BuildOperation( buildParameters: buildParameters ?? self.buildParameters(), @@ -844,7 +840,7 @@ public class SwiftTool { observabilityScope: self.observabilityScope ) case .xcode: - let graphLoader = { try self.loadPackageGraph(explicitProduct: explicitProduct, createMultipleTestProducts: true) } + let graphLoader = { try self.loadPackageGraph(createMultipleTestProducts: true) } // FIXME: Implement the custom build command provider also. buildSystem = try XcodeBuildSystem( buildParameters: buildParameters ?? self.buildParameters(), diff --git a/Sources/PackageGraph/DependencyResolutionNode.swift b/Sources/PackageGraph/DependencyResolutionNode.swift index 70ec821f8f9..76a5fd7d5cf 100644 --- a/Sources/PackageGraph/DependencyResolutionNode.swift +++ b/Sources/PackageGraph/DependencyResolutionNode.swift @@ -12,6 +12,7 @@ import TSCBasic import PackageModel import struct TSCUtility.Version +/* /// A node in the dependency resolution graph. /// /// See the documentation of each case for more detailed descriptions of each kind and how they interact. @@ -133,3 +134,4 @@ extension DependencyResolutionNode: CustomStringConvertible { return "\(package.name)\(productFilter)" } } +*/ diff --git a/Sources/PackageGraph/DependencyResolver.swift b/Sources/PackageGraph/DependencyResolver.swift index 2b555361f59..a0ec6413100 100644 --- a/Sources/PackageGraph/DependencyResolver.swift +++ b/Sources/PackageGraph/DependencyResolver.swift @@ -13,7 +13,7 @@ import PackageModel import TSCBasic public protocol DependencyResolver { - typealias Binding = (package: PackageReference, binding: BoundVersion, products: ProductFilter) + typealias Binding = (package: PackageReference, binding: BoundVersion) typealias Delegate = DependencyResolverDelegate } @@ -55,15 +55,15 @@ public struct TracingDependencyResolverDelegate: DependencyResolverDelegate { } public func willResolve(term: Term) { - self.log("resolving: \(term.node.package.identity)") + self.log("resolving: \(term.package.identity)") } public func didResolve(term: Term, version: Version, duration: DispatchTimeInterval) { - self.log("resolved: \(term.node.package.identity) @ \(version)") + self.log("resolved: \(term.package.identity) @ \(version)") } public func derived(term: Term) { - self.log("derived: \(term.node.package.identity)") + self.log("derived: \(term.package.identity)") } public func conflict(conflict: Incompatibility) { @@ -88,7 +88,7 @@ public struct TracingDependencyResolverDelegate: DependencyResolverDelegate { public func solved(result: [DependencyResolver.Binding]) { self.log("solved:") - for (package, binding, _) in result { + for (package, binding) in result { self.log("\(package) \(binding)") } } @@ -134,8 +134,7 @@ public struct MultiplexResolverDelegate: DependencyResolverDelegate { underlying.forEach { $0.failedToResolve(incompatibility: incompatibility) } } - public func solved(result: [(package: PackageReference, binding: BoundVersion, products: ProductFilter)]) { + public func solved(result: [(package: PackageReference, binding: BoundVersion)]) { underlying.forEach { $0.solved(result: result) } } - } diff --git a/Sources/PackageGraph/GraphLoadingNode.swift b/Sources/PackageGraph/GraphLoadingNode.swift index 21eabee9eea..311a96af5e6 100644 --- a/Sources/PackageGraph/GraphLoadingNode.swift +++ b/Sources/PackageGraph/GraphLoadingNode.swift @@ -17,6 +17,7 @@ import TSCBasic /// This node uses the product filter that was already finalized during resolution. /// /// - SeeAlso: DependencyResolutionNode +// FIXME: tomer deprecate or replace withe some other manifest envelope public struct GraphLoadingNode: Equatable, Hashable { /// The package identity. @@ -25,28 +26,20 @@ public struct GraphLoadingNode: Equatable, Hashable { /// The package manifest. public let manifest: Manifest - /// The product filter applied to the package. - public let productFilter: ProductFilter - - public init(identity: PackageIdentity, manifest: Manifest, productFilter: ProductFilter) { + public init(identity: PackageIdentity, manifest: Manifest) { self.identity = identity self.manifest = manifest - self.productFilter = productFilter + //self.productFilter = productFilter } /// Returns the dependencies required by this node. internal func requiredDependencies() -> [PackageDependency] { - return manifest.dependenciesRequired(for: productFilter) + return self.manifest.requiredDependencies() } } extension GraphLoadingNode: CustomStringConvertible { public var description: String { - switch productFilter { - case .everything: - return self.manifest.name - case .specific(let set): - return "\(self.manifest.name)[\(set.sorted().joined(separator: ", "))]" - } + return self.identity.description } } diff --git a/Sources/PackageGraph/PackageContainer.swift b/Sources/PackageGraph/PackageContainer.swift index c59e376ef4e..2e57d608624 100644 --- a/Sources/PackageGraph/PackageContainer.swift +++ b/Sources/PackageGraph/PackageContainer.swift @@ -68,7 +68,7 @@ public protocol PackageContainer { /// - Precondition: `versions.contains(version)` /// - Throws: If the version could not be resolved; this will abort /// dependency resolution completely. - func getDependencies(at version: Version, productFilter: ProductFilter) throws -> [PackageContainerConstraint] + func getDependencies(at version: Version) throws -> [PackageContainerConstraint] /// Fetch the declared dependencies for a particular revision. /// @@ -77,12 +77,12 @@ public protocol PackageContainer { /// /// - Throws: If the revision could not be resolved; this will abort /// dependency resolution completely. - func getDependencies(at revision: String, productFilter: ProductFilter) throws -> [PackageContainerConstraint] + func getDependencies(at revision: String) throws -> [PackageContainerConstraint] /// Fetch the dependencies of an unversioned package container. /// /// NOTE: This method should not be called on a versioned container. - func getUnversionedDependencies(productFilter: ProductFilter) throws -> [PackageContainerConstraint] + func getUnversionedDependencies() throws -> [PackageContainerConstraint] /// Get the updated identifier at a bound version. /// @@ -113,27 +113,23 @@ public struct PackageContainerConstraint: Equatable, Hashable { /// The constraint requirement. public let requirement: PackageRequirement - /// The required products. - public let products: ProductFilter - /// Create a constraint requiring the given `container` satisfying the /// `requirement`. - public init(package: PackageReference, requirement: PackageRequirement, products: ProductFilter) { + public init(package: PackageReference, requirement: PackageRequirement) { self.package = package self.requirement = requirement - self.products = products } /// Create a constraint requiring the given `container` satisfying the /// `versionRequirement`. - public init(package: PackageReference, versionRequirement: VersionSetSpecifier, products: ProductFilter) { - self.init(package: package, requirement: .versionSet(versionRequirement), products: products) + public init(package: PackageReference, versionRequirement: VersionSetSpecifier) { + self.init(package: package, requirement: .versionSet(versionRequirement)) } } extension PackageContainerConstraint: CustomStringConvertible { public var description: String { - return "Constraint(\(self.package), \(requirement), \(products)" + return "Constraint(\(self.package), \(requirement)" } } diff --git a/Sources/PackageGraph/PackageGraph+Loading.swift b/Sources/PackageGraph/PackageGraph+Loading.swift index 6b887c6b546..465c83d923e 100644 --- a/Sources/PackageGraph/PackageGraph+Loading.swift +++ b/Sources/PackageGraph/PackageGraph+Loading.swift @@ -43,7 +43,7 @@ extension PackageGraph { let successors: (GraphLoadingNode) -> [GraphLoadingNode] = { node in node.requiredDependencies().compactMap{ dependency in return manifestMap[dependency.identity].map { manifest in - GraphLoadingNode(identity: dependency.identity, manifest: manifest, productFilter: dependency.productFilter) + GraphLoadingNode(identity: dependency.identity, manifest: manifest) } } } @@ -54,11 +54,11 @@ extension PackageGraph { manifestMap[$0.identity] }) let rootManifestNodes = root.packages.map { identity, package in - GraphLoadingNode(identity: identity, manifest: package.manifest, productFilter: .everything) + GraphLoadingNode(identity: identity, manifest: package.manifest) } let rootDependencyNodes = root.dependencies.lazy.compactMap { (dependency: PackageDependency) -> GraphLoadingNode? in manifestMap[dependency.identity].map { - GraphLoadingNode(identity: dependency.identity, manifest: $0, productFilter: dependency.productFilter) + GraphLoadingNode(identity: dependency.identity, manifest: $0) } } let inputManifests = rootManifestNodes + rootDependencyNodes @@ -76,13 +76,15 @@ extension PackageGraph { allNodes = try topologicalSort(inputManifests, successors: successors) } + // FIXME: tomer simplify + /* var flattenedManifests: [PackageIdentity: GraphLoadingNode] = [:] for node in allNodes { if let existing = flattenedManifests[node.identity] { let merged = GraphLoadingNode( identity: node.identity, - manifest: node.manifest, - productFilter: existing.productFilter.union(node.productFilter) + manifest: node.manifest//, + //productFilter: existing.productFilter.union(node.productFilter) ) flattenedManifests[node.identity] = merged } else { @@ -91,7 +93,8 @@ extension PackageGraph { } // sort by identity allNodes = flattenedManifests.keys.sorted().map { flattenedManifests[$0]! } // force unwrap fine since we are iterating on keys - + */ + // Create the packages. var manifestToPackage: [Manifest: Package] = [:] for node in allNodes { @@ -110,7 +113,7 @@ extension PackageGraph { let builder = PackageBuilder( identity: node.identity, manifest: manifest, - productFilter: node.productFilter, + //productFilter: node.productFilter, path: packagePath, additionalFileRules: additionalFileRules, binaryArtifacts: binaryArtifacts, @@ -209,7 +212,7 @@ private func createResolvedPackages( let allowedToOverride = rootManifestSet.contains(node.manifest) return ResolvedPackageBuilder( package, - productFilter: node.productFilter, + //productFilter: node.productFilter, isAllowedToVendUnsafeProducts: isAllowedToVendUnsafeProducts, allowedToOverride: allowedToOverride ) @@ -234,7 +237,7 @@ private func createResolvedPackages( var dependenciesByNameForTargetDependencyResolution = [String: ResolvedPackageBuilder]() // Establish the manifest-declared package dependencies. - package.manifest.dependenciesRequired(for: packageBuilder.productFilter).forEach { dependency in + package.manifest.requiredDependencies().forEach { dependency in // FIXME: change this validation logic to use identity instead of location let dependencyLocation: String switch dependency { @@ -481,6 +484,7 @@ private func createResolvedPackages( } /// A generic builder for `Resolved` models. +// FIXME: can we deprecate this? seems like adding very little value private class ResolvedBuilder { /// The constructed object, available after the first call to `construct()`. private var _constructedObject: T? @@ -530,6 +534,7 @@ private final class ResolvedProductBuilder: ResolvedBuilder { } /// Builder for resolved target. +// FIXME: can we deprecate this? seems like adding very little value private final class ResolvedTargetBuilder: ResolvedBuilder { /// Enumeration to represent target dependencies. @@ -592,14 +597,12 @@ private final class ResolvedTargetBuilder: ResolvedBuilder { } /// Builder for resolved package. +// FIXME: can we deprecate this? seems like adding very little value private final class ResolvedPackageBuilder: ResolvedBuilder { /// The package reference. let package: Package - /// The product filter applied to the package. - let productFilter: ProductFilter - /// The targets in the package. var targets: [ResolvedTargetBuilder] = [] @@ -613,9 +616,8 @@ private final class ResolvedPackageBuilder: ResolvedBuilder { let allowedToOverride: Bool - init(_ package: Package, productFilter: ProductFilter, isAllowedToVendUnsafeProducts: Bool, allowedToOverride: Bool) { + init(_ package: Package, isAllowedToVendUnsafeProducts: Bool, allowedToOverride: Bool) { self.package = package - self.productFilter = productFilter self.isAllowedToVendUnsafeProducts = isAllowedToVendUnsafeProducts self.allowedToOverride = allowedToOverride } @@ -624,8 +626,8 @@ private final class ResolvedPackageBuilder: ResolvedBuilder { return ResolvedPackage( package: package, dependencies: try dependencies.map{ try $0.construct() }, - targets: try targets.map{ try $0.construct() }, - products: try products.map{ try $0.construct() } + targets: try self.targets.map{ try $0.construct() }, + products: try self.products.map{ try $0.construct() } ) } } diff --git a/Sources/PackageGraph/PackageGraphRoot.swift b/Sources/PackageGraph/PackageGraphRoot.swift index 1bca3aa683a..056581efc60 100644 --- a/Sources/PackageGraph/PackageGraphRoot.swift +++ b/Sources/PackageGraph/PackageGraphRoot.swift @@ -52,7 +52,7 @@ public struct PackageGraphRoot { // FIXME: This API behavior wrt to non-found manifests is fragile, but required by IDEs // it may lead to incorrect assumption in downstream code which may expect an error if a manifest was not found // we should refactor this API to more clearly return errors for inputs that do not have a corresponding manifest - public init(input: PackageGraphRootInput, manifests: [AbsolutePath: Manifest], explicitProduct: String? = nil) { + public init(input: PackageGraphRootInput, manifests: [AbsolutePath: Manifest]) { self.packages = input.packages.reduce(into: .init(), { partial, inputPath in if let manifest = manifests[inputPath] { let packagePath = manifest.path.parentDirectory @@ -60,35 +60,20 @@ public struct PackageGraphRoot { partial[identity] = (.root(identity: identity, path: packagePath), manifest) } }) - - // FIXME: Deprecate special casing once the manifest supports declaring used executable products. - // Special casing explicit products like this is necessary to pass the test suite and satisfy backwards compatibility. - // However, changing the dependencies based on the command line arguments may force pins to temporarily change, - // which can become a nuissance. - // Such pin switching can currently be worked around by declaring the executable product as a dependency of a dummy target. - // But in the future it might be worth providing a way of declaring them in the manifest without a dummy target, - // at which time the current special casing can be deprecated. - var adjustedDependencies = input.dependencies - if let product = explicitProduct { - for dependency in manifests.values.lazy.map({ $0.dependenciesRequired(for: .everything) }).joined() { - adjustedDependencies.append(dependency.filtered(by: .specific([product]))) - } - } - - self.dependencies = adjustedDependencies + + self.dependencies = input.dependencies } /// Returns the constraints imposed by root manifests + dependencies. public func constraints() throws -> [PackageContainerConstraint] { let constraints = self.packageReferences.map { - PackageContainerConstraint(package: $0, requirement: .unversioned, products: .everything) + PackageContainerConstraint(package: $0, requirement: .unversioned) } let depend = try dependencies.map{ PackageContainerConstraint( package: $0.createPackageRef(), - requirement: try $0.toConstraintRequirement(), - products: $0.productFilter + requirement: try $0.toConstraintRequirement() ) } return constraints + depend diff --git a/Sources/PackageGraph/PackageModel+Extensions.swift b/Sources/PackageGraph/PackageModel+Extensions.swift index 6baf229b7b0..e1c6f99f2fb 100644 --- a/Sources/PackageGraph/PackageModel+Extensions.swift +++ b/Sources/PackageGraph/PackageModel+Extensions.swift @@ -35,16 +35,18 @@ extension PackageDependency { extension Manifest { /// Constructs constraints of the dependencies in the raw package. - public func dependencyConstraints(productFilter: ProductFilter) throws -> [PackageContainerConstraint] { - return try dependenciesRequired(for: productFilter).map({ - return PackageContainerConstraint( + public func dependencyConstraints() throws -> [PackageContainerConstraint] { + return try self.requiredDependencies().map{ + PackageContainerConstraint( package: $0.createPackageRef(), - requirement: try $0.toConstraintRequirement(), - products: $0.productFilter) - }) + requirement: try $0.toConstraintRequirement()//, + //products: $0.productFilter + ) + } } } +/* extension PackageContainerConstraint { /// Constructs a structure of dependency nodes in a package. /// - returns: An array of ``DependencyResolutionNode`` @@ -67,3 +69,4 @@ extension PackageContainerConstraint { } } } +*/ diff --git a/Sources/PackageGraph/Pubgrub/Incompatibility.swift b/Sources/PackageGraph/Pubgrub/Incompatibility.swift index c29728c026f..93c4f997801 100644 --- a/Sources/PackageGraph/Pubgrub/Incompatibility.swift +++ b/Sources/PackageGraph/Pubgrub/Incompatibility.swift @@ -9,8 +9,8 @@ */ import Basics -import TSCBasic import PackageModel +import TSCBasic /// A set of terms that are incompatible with each other and can therefore not /// all be true at the same time. In dependency resolution, these are derived @@ -24,12 +24,12 @@ public struct Incompatibility: Equatable, Hashable { self.cause = cause } - public init(_ terms: Term..., root: DependencyResolutionNode, cause: Cause = .root) throws { + public init(_ terms: Term..., root: PackageReference, cause: Cause = .root) throws { let termSet = OrderedSet(terms) try self.init(termSet, root: root, cause: cause) } - public init(_ terms: OrderedSet, root: DependencyResolutionNode, cause: Cause) throws { + public init(_ terms: OrderedSet, root: PackageReference, cause: Cause) throws { if terms.isEmpty { self.init(terms: terms, cause: cause) return @@ -39,8 +39,8 @@ public struct Incompatibility: Equatable, Hashable { // always be selected. var terms = terms if terms.count > 1, cause.isConflict, - terms.contains(where: { $0.isPositive && $0.node == root }) { - terms = OrderedSet(terms.filter { !$0.isPositive || $0.node != root }) + terms.contains(where: { $0.isPositive && $0.package == root }) { + terms = OrderedSet(terms.filter { !$0.isPositive || $0.package != root }) } let normalizedTerms = try normalize(terms: terms.contents) @@ -96,7 +96,7 @@ extension Incompatibility { /// The incompatibility represents a package's dependency on another /// package. - case dependency(node: DependencyResolutionNode) + case dependency(package: PackageReference) /// The incompatibility was derived from two others during conflict /// resolution. @@ -133,24 +133,23 @@ extension Incompatibility { /// same incompatibility, but have these combined by intersecting their version /// requirements to a^1.5.0. fileprivate func normalize(terms: [Term]) throws -> [Term] { - - let dict = try terms.reduce(into: OrderedDictionary()) { + let dict = try terms.reduce(into: OrderedDictionary()) { res, term in // Don't try to intersect if this is the first time we're seeing this package. - guard let previous = res[term.node] else { - res[term.node] = (term.requirement, term.isPositive) + guard let previous = res[term.package] else { + res[term.package] = (term.requirement, term.isPositive) return } guard let intersection = term.intersect(withRequirement: previous.req, andPolarity: previous.polarity) else { throw InternalError(""" - Attempting to create an incompatibility with terms for \(term.node) \ + Attempting to create an incompatibility with terms for \(term.package) \ intersecting versions \(previous) and \(term.requirement). These are \ mutually exclusive and can't be intersected, making this incompatibility \ irrelevant. """) } - res[term.node] = (intersection.requirement, intersection.isPositive) + res[term.package] = (intersection.requirement, intersection.isPositive) } - return dict.map { Term(node: $0, requirement: $1.req, isPositive: $1.polarity) } + return dict.map { Term(package: $0, requirement: $1.req, isPositive: $1.polarity) } } diff --git a/Sources/PackageGraph/Pubgrub/PartialSolution.swift b/Sources/PackageGraph/Pubgrub/PartialSolution.swift index 044a1694dfa..2c2ccef5da3 100644 --- a/Sources/PackageGraph/Pubgrub/PartialSolution.swift +++ b/Sources/PackageGraph/Pubgrub/PartialSolution.swift @@ -9,28 +9,29 @@ */ import Basics +import PackageModel import TSCBasic import struct TSCUtility.Version /// The partial solution is a constantly updated solution used throughout the /// dependency resolution process, tracking know assignments. public struct PartialSolution { - var root: DependencyResolutionNode? + var root: PackageReference? - /// All known assigments. + /// All known assignments. public private(set) var assignments: [Assignment] /// All known decisions. - public private(set) var decisions: [DependencyResolutionNode: Version] = [:] + public private(set) var decisions: [PackageReference: Version] = [:] /// The intersection of all positive assignments for each package, minus any /// negative assignments that refer to that package. - public private(set) var _positive: OrderedDictionary = [:] + public private(set) var _positive: OrderedDictionary = [:] /// Union of all negative assignments for a package. /// /// Only present if a package has no positive assignment. - public private(set) var _negative: [DependencyResolutionNode: Term] = [:] + public private(set) var _negative: [PackageReference: Term] = [:] /// The current decision level. public var decisionLevel: Int { @@ -46,7 +47,7 @@ public struct PartialSolution { /// A list of all packages that have been assigned, but are not yet satisfied. public var undecided: [Term] { - return _positive.values.filter { !decisions.keys.contains($0.node) } + return _positive.values.filter { !decisions.keys.contains($0.package) } } /// Create a new derivation assignment and add it to the partial solution's @@ -59,9 +60,9 @@ public struct PartialSolution { /// Create a new decision assignment and add it to the partial solution's /// list of known assignments. - public mutating func decide(_ node: DependencyResolutionNode, at version: Version) { - decisions[node] = version - let term = Term(node, .exact(version)) + public mutating func decide(_ package: PackageReference, at version: Version) { + decisions[package] = version + let term = Term(package, .exact(version)) let decision = Assignment.decision(term, decisionLevel: decisionLevel) self.assignments.append(decision) register(decision) @@ -70,10 +71,10 @@ public struct PartialSolution { /// Populates the _positive and _negative poperties with the assignment. private mutating func register(_ assignment: Assignment) { let term = assignment.term - let pkg = term.node + let pkg = term.package if let positive = _positive[pkg] { - _positive[term.node] = positive.intersect(with: term) + _positive[term.package] = positive.intersect(with: term) return } @@ -93,7 +94,7 @@ public struct PartialSolution { var assignedTerm: Term? for assignment in assignments { - guard assignment.term.node == term.node else { + guard assignment.term.package == term.package else { continue } assignedTerm = assignedTerm.flatMap{ $0.intersect(with: assignment.term) } ?? assignment.term @@ -120,7 +121,7 @@ public struct PartialSolution { for (idx, remove) in toBeRemoved.reversed() { let assignment = assignments.remove(at: idx) if assignment.isDecision { - decisions.removeValue(forKey: remove.term.node) + decisions.removeValue(forKey: remove.term.package) } } @@ -139,7 +140,7 @@ public struct PartialSolution { /// Returns the set relation of the partial solution with the given term. func relation(with term: Term) -> Term.SetRelation { - let pkg = term.node + let pkg = term.package if let positive = _positive[pkg] { return positive.relation(with: term) } else if let negative = _negative[pkg] { diff --git a/Sources/PackageGraph/Pubgrub/PubgrubDependencyResolver.swift b/Sources/PackageGraph/Pubgrub/PubgrubDependencyResolver.swift index 0378e592604..84b6f100523 100644 --- a/Sources/PackageGraph/Pubgrub/PubgrubDependencyResolver.swift +++ b/Sources/PackageGraph/Pubgrub/PubgrubDependencyResolver.swift @@ -23,24 +23,24 @@ public struct PubgrubDependencyResolver { /// the mutable state that get computed internal final class State { /// The root package reference. - let root: DependencyResolutionNode + let root: PackageReference /// The list of packages that are overridden in the graph. A local package reference will /// always override any other kind of package reference and branch-based reference will override /// version-based reference. - let overriddenPackages: [PackageReference: (version: BoundVersion, products: ProductFilter)] + let overriddenPackages: [PackageReference: BoundVersion] /// A collection of all known incompatibilities matched to the packages they /// refer to. This means an incompatibility can occur several times. - public private(set) var incompatibilities: [DependencyResolutionNode: [Incompatibility]] = [:] + public private(set) var incompatibilities: [PackageReference: [Incompatibility]] = [:] /// The current best guess for a solution satisfying all requirements. public private(set) var solution: PartialSolution private let lock = Lock() - init(root: DependencyResolutionNode, - overriddenPackages: [PackageReference: (version: BoundVersion, products: ProductFilter)] = [:], + init(root: PackageReference, + overriddenPackages: [PackageReference: BoundVersion] = [:], solution: PartialSolution = PartialSolution()) { self.root = root self.overriddenPackages = overriddenPackages @@ -50,7 +50,7 @@ public struct PubgrubDependencyResolver { func addIncompatibility(_ incompatibility: Incompatibility, at location: LogLocation) { self.lock.withLock { // log("incompat: \(incompatibility) \(location)") - for package in incompatibility.terms.map({ $0.node }) { + for package in incompatibility.terms.map({ $0.package }) { if let incompats = self.incompatibilities[package] { if !incompats.contains(incompatibility) { self.incompatibilities[package]!.append(incompatibility) @@ -63,23 +63,23 @@ public struct PubgrubDependencyResolver { } /// Find all incompatibilities containing a positive term for a given package. - func positiveIncompatibilities(for node: DependencyResolutionNode) -> [Incompatibility]? { + func positiveIncompatibilities(for package: PackageReference) -> [Incompatibility]? { self.lock.withLock { - guard let all = self.incompatibilities[node] else { + guard let all = self.incompatibilities[package] else { return nil } return all.filter { - $0.terms.first { $0.node == node }!.isPositive + $0.terms.first { $0.package == package }!.isPositive } } } - func decide(_ node: DependencyResolutionNode, at version: Version) { - let term = Term(node, .exact(version)) + func decide(_ package: PackageReference, at version: Version) { + let term = Term(package, .exact(version)) self.lock.withLock { // FIXME: Shouldn't we check this _before_ making a decision? assert(term.isValidDecision(for: self.solution)) - self.solution.decide(node, at: version) + self.solution.decide(package, at: version) } } @@ -131,10 +131,10 @@ public struct PubgrubDependencyResolver { /// Execute the resolution algorithm to find a valid assignment of versions. public func solve(constraints: [Constraint]) -> Result<[DependencyResolver.Binding], Error> { - let root = DependencyResolutionNode.root(package: .root( + let root = PackageReference.root( identity: .plain(""), path: .root - )) + ) do { // strips state @@ -165,7 +165,7 @@ public struct PubgrubDependencyResolver { /// Find a set of dependencies that fit the given constraints. If dependency /// resolution is unable to provide a result, an error is thrown. /// - Warning: It is expected that the root package reference has been set before this is called. - internal func solve(root: DependencyResolutionNode, constraints: [Constraint]) throws -> (bindings: [DependencyResolver.Binding], state: State) { + internal func solve(root: PackageReference, constraints: [Constraint]) throws -> (bindings: [DependencyResolver.Binding], state: State) { // first process inputs let inputs = try self.processInputs(root: root, with: constraints) @@ -196,10 +196,9 @@ public struct PubgrubDependencyResolver { try self.run(state: state) let decisions = state.solution.assignments.filter { $0.isDecision } - var flattenedAssignments: [PackageReference: (binding: BoundVersion, products: ProductFilter)] = [:] - for assignment in decisions { - if assignment.term.node == state.root { - continue + var finalAssignments: [DependencyResolver.Binding] = try decisions.compactMap { assignment in + guard assignment.term.package != root else { + return nil } let boundVersion: BoundVersion @@ -210,32 +209,19 @@ public struct PubgrubDependencyResolver { throw InternalError("unexpected requirement value for assignment \(assignment.term)") } - let products = assignment.term.node.productFilter - // TODO: replace with async/await when available - let container = try temp_await { provider.getContainer(for: assignment.term.node.package, completion: $0) } - let identifier = try container.underlying.getUpdatedIdentifier(at: boundVersion) + let container = try temp_await { provider.getContainer(for: assignment.term.package, completion: $0) } + let updatedPackage = try container.underlying.getUpdatedIdentifier(at: boundVersion) - if var existing = flattenedAssignments[identifier] { - assert(existing.binding == boundVersion, "Two products in one package resolved to different versions: \(existing.products)@\(existing.binding) vs \(products)@\(boundVersion)") - existing.products.formUnion(products) - flattenedAssignments[identifier] = existing - } else { - flattenedAssignments[identifier] = (binding: boundVersion, products: products) - } + return (package: updatedPackage, binding: boundVersion) } - var finalAssignments: [DependencyResolver.Binding] - = flattenedAssignments.keys.sorted(by: { $0.name < $1.name }).map { package in - let details = flattenedAssignments[package]! - return (package: package, binding: details.binding, products: details.products) - } // Add overridden packages to the result. - for (package, override) in state.overriddenPackages { + for (package, overrideVersion) in state.overriddenPackages { // TODO: replace with async/await when available let container = try temp_await { provider.getContainer(for: package, completion: $0) } - let identifier = try container.underlying.getUpdatedIdentifier(at: override.version) - finalAssignments.append((identifier, override.version, override.products)) + let updatedPackage = try container.underlying.getUpdatedIdentifier(at: overrideVersion) + finalAssignments.append((updatedPackage, overrideVersion)) } self.delegate?.solved(result: finalAssignments) @@ -244,10 +230,10 @@ public struct PubgrubDependencyResolver { } private func processInputs( - root: DependencyResolutionNode, + root: PackageReference, with constraints: [Constraint] ) throws -> ( - overriddenPackages: [PackageReference: (version: BoundVersion, products: ProductFilter)], + overriddenPackages: [PackageReference: BoundVersion], rootIncompatibilities: [Incompatibility] ) { // The list of constraints that we'll be working with. We start with the input constraints @@ -258,12 +244,12 @@ public struct PubgrubDependencyResolver { // The list of packages that are overridden in the graph. A local package reference will // always override any other kind of package reference and branch-based reference will override // version-based reference. - var overriddenPackages: [PackageReference: (version: BoundVersion, products: ProductFilter)] = [:] + var overriddenPackages: [PackageReference: BoundVersion] = [:] // The list of version-based references reachable via local and branch-based references. // These are added as top-level incompatibilities since they always need to be statisfied. // Some of these might be overridden as we discover local and branch-based references. - var versionBasedDependencies: [DependencyResolutionNode: [VersionBasedConstraint]] = [:] + var versionBasedDependencies: [PackageReference: [VersionBasedConstraint]] = [:] // Process unversioned constraints in first phase. We go through all of the unversioned packages // and collect them and their dependencies. This gives us the complete list of unversioned @@ -273,32 +259,22 @@ public struct PubgrubDependencyResolver { constraints.remove(constraint) // Mark the package as overridden. - if var existing = overriddenPackages[constraint.package] { - assert(existing.version == .unversioned, "Overridden package is not unversioned: \(constraint.package)@\(existing.version)") - existing.products.formUnion(constraint.products) - overriddenPackages[constraint.package] = existing - } else { - overriddenPackages[constraint.package] = (version: .unversioned, products: constraint.products) - } + overriddenPackages[constraint.package] = .unversioned - for node in constraint.nodes() { - // Process dependencies of this package. - // - // We collect all version-based dependencies in a separate structure so they can - // be process at the end. This allows us to override them when there is a non-version - // based (unversioned/branch-based) constraint present in the graph. - // TODO: replace with async/await when available - let container = try temp_await { provider.getContainer(for: node.package, completion: $0) } - for dependency in try container.underlying.getUnversionedDependencies(productFilter: node.productFilter) { - if let versionedBasedConstraints = VersionBasedConstraint.constraints(dependency) { - for constraint in versionedBasedConstraints { - versionBasedDependencies[node, default: []].append(constraint) - } - } else if !overriddenPackages.keys.contains(dependency.package) { - // Add the constraint if its not already present. This will ensure we don't - // end up looping infinitely due to a cycle (which are diagnosed seperately). - constraints.append(dependency) - } + // Process dependencies of this package. + // + // We collect all version-based dependencies in a separate structure so they can + // be process at the end. This allows us to override them when there is a non-version + // based (unversioned/branch-based) constraint present in the graph. + // TODO: replace with async/await when available + let container = try temp_await { provider.getContainer(for: constraint.package, completion: $0) } + for dependency in try container.underlying.getUnversionedDependencies() { + if let versionedBasedConstraint = VersionBasedConstraint(dependency) { + versionBasedDependencies[constraint.package, default: []].append(versionedBasedConstraint) + } else if !overriddenPackages.keys.contains(dependency.package) { + // Add the constraint if its not already present. This will ensure we don't + // end up looping infinitely due to a cycle (which are diagnosed seperately). + constraints.append(dependency) } } } @@ -314,7 +290,7 @@ public struct PubgrubDependencyResolver { let package = constraint.package // Check if there is an existing value for this package in the overridden packages. - switch overriddenPackages[package]?.version { + switch overriddenPackages[package] { case .excluded?, .version?: // These values are not possible. throw InternalError("Unexpected value for overriden package \(package) in \(overriddenPackages)") @@ -331,7 +307,6 @@ public struct PubgrubDependencyResolver { } case nil: break - } // Process dependencies of this package, similar to the first phase but branch-based dependencies @@ -348,37 +323,26 @@ public struct PubgrubDependencyResolver { revisionForDependencies = pinRevision.identifier // Mark the package as overridden with the pinned revision and record the branch as well. - overriddenPackages[package] = (version: .revision(revisionForDependencies, branch: revision), products: constraint.products) + overriddenPackages[package] = .revision(revisionForDependencies, branch: revision) } else { revisionForDependencies = revision // Mark the package as overridden. - overriddenPackages[package] = (version: .revision(revision), products: constraint.products) + overriddenPackages[package] = .revision(revision) } - for node in constraint.nodes() { - var unprocessedDependencies = try container.underlying.getDependencies( - at: revisionForDependencies, - productFilter: constraint.products - ) - if let sharedRevision = node.revisionLock(revision: revision) { - unprocessedDependencies.append(sharedRevision) - } - for dependency in unprocessedDependencies { - switch dependency.requirement { - case .versionSet(let req): - for node in dependency.nodes() { - let versionedBasedConstraint = VersionBasedConstraint(node: node, req: req) - versionBasedDependencies[node, default: []].append(versionedBasedConstraint) - } - case .revision: - constraints.append(dependency) - case .unversioned: - throw DependencyResolverError.revisionDependencyContainsLocalPackage( - dependency: package.name, - localPackage: dependency.package.name - ) - } + for dependency in try container.underlying.getDependencies(at: revisionForDependencies) { + switch dependency.requirement { + case .versionSet(let requirement): + let versionedBasedConstraint = VersionBasedConstraint(package: dependency.package, requirement: requirement) + versionBasedDependencies[package, default: []].append(versionedBasedConstraint) + case .revision: + constraints.append(dependency) + case .unversioned: + throw DependencyResolverError.revisionDependencyContainsLocalPackage( + dependency: package.name, + localPackage: dependency.package.name + ) } } } @@ -387,13 +351,10 @@ public struct PubgrubDependencyResolver { // list. Add them to our version-based dependency list. for dependency in constraints { switch dependency.requirement { - case .versionSet(let req): - for node in dependency.nodes() { - let versionedBasedConstraint = VersionBasedConstraint(node: node, req: req) - // FIXME: It would be better to record where this constraint came from, instead of just - // using root. - versionBasedDependencies[root, default: []].append(versionedBasedConstraint) - } + case .versionSet(let requirement): + let versionedBasedConstraint = VersionBasedConstraint(package: dependency.package, requirement: requirement) + // FIXME: It would be better to record where this constraint came from, instead of just using root. + versionBasedDependencies[root, default: []].append(versionedBasedConstraint) case .revision, .unversioned: throw InternalError("Unexpected revision/unversioned requirement in the constraints list: \(constraints)") } @@ -401,15 +362,15 @@ public struct PubgrubDependencyResolver { // Finally, compute the root incompatibilities (which will be all version-based). var rootIncompatibilities: [Incompatibility] = [] - for (node, constraints) in versionBasedDependencies { + for (package, constraints) in versionBasedDependencies { for constraint in constraints { - if overriddenPackages.keys.contains(constraint.node.package) { continue } + if overriddenPackages.keys.contains(constraint.package) { continue } let incompat = try Incompatibility( Term(root, .exact("1.0.0")), - Term(not: constraint.node, constraint.requirement), + Term(not: constraint.package, constraint.requirement), root: root, - cause: .dependency(node: node) + cause: .dependency(package: package) ) rootIncompatibilities.append(incompat) } @@ -423,13 +384,13 @@ public struct PubgrubDependencyResolver { /// After this method returns `solution` is either populated with a list of /// final version assignments or an error is thrown. private func run(state: State) throws { - var next: DependencyResolutionNode? = state.root + var next: PackageReference? = state.root while let nxt = next { - try self.propagate(state: state, node: nxt) + try self.propagate(state: state, package: nxt) // initiate prefetch of known packages that will be used to make the decision on the next step - self.provider.prefetch(containers: state.solution.undecided.map { $0.node.package }) + self.provider.prefetch(containers: state.solution.undecided.map { $0.package }) // If decision making determines that no more decisions are to be // made, it returns nil to signal that version solving is done. @@ -442,8 +403,8 @@ public struct PubgrubDependencyResolver { /// partial solution. /// If a conflict is found, the conflicting incompatibility is returned to /// resolve the conflict on. - internal func propagate(state: State, node: DependencyResolutionNode) throws { - var changed: OrderedSet = [node] + internal func propagate(state: State, package: PackageReference) throws { + var changed: OrderedSet = [package] while !changed.isEmpty { let package = changed.removeFirst() @@ -500,7 +461,7 @@ public struct PubgrubDependencyResolver { self.delegate?.derived(term: unsatisfiedTerm.inverse) state.derive(unsatisfiedTerm.inverse, cause: incompatibility) - return .almostSatisfied(node: unsatisfiedTerm.node) + return .almostSatisfied(package: unsatisfiedTerm.package) } // Based on: @@ -561,7 +522,7 @@ public struct PubgrubDependencyResolver { let priorCause = _mostRecentSatisfier.cause! var newTerms = incompatibility.terms.filter { $0 != mostRecentTerm } - newTerms += priorCause.terms.filter { $0.node != _mostRecentSatisfier.term.node } + newTerms += priorCause.terms.filter { $0.package != _mostRecentSatisfier.term.package } if let _difference = difference { newTerms.append(_difference.inverse) @@ -590,8 +551,8 @@ public struct PubgrubDependencyResolver { /// Does a given incompatibility specify that version solving has entirely /// failed, meaning this incompatibility is either empty or only for the root /// package. - private func isCompleteFailure(_ incompatibility: Incompatibility, root: DependencyResolutionNode) -> Bool { - return incompatibility.terms.isEmpty || (incompatibility.terms.count == 1 && incompatibility.terms.first?.node == root) + private func isCompleteFailure(_ incompatibility: Incompatibility, root: PackageReference) -> Bool { + return incompatibility.terms.isEmpty || (incompatibility.terms.count == 1 && incompatibility.terms.first?.package == root) } private func computeCounts(for terms: [Term], completion: @escaping (Result<[Term: Int], Error>) -> Void) { @@ -604,7 +565,7 @@ public struct PubgrubDependencyResolver { terms.forEach { term in sync.enter() - provider.getContainer(for: term.node.package) { result in + provider.getContainer(for: term.package) { result in defer { sync.leave() } results[term] = result.flatMap { container in Result(catching: { try container.versionCount(term.requirement) }) } } @@ -619,7 +580,7 @@ public struct PubgrubDependencyResolver { } } - internal func makeDecision(state: State, completion: @escaping (Result) -> Void) { + internal func makeDecision(state: State, completion: @escaping (Result) -> Void) { // If there are no more undecided terms, version solving is complete. let undecided = state.solution.undecided guard !undecided.isEmpty else { @@ -636,18 +597,18 @@ public struct PubgrubDependencyResolver { let pkgTerm = undecided.min { counts[$0]! < counts[$1]! }! self.delegate?.willResolve(term: pkgTerm) // at this point the container is cached - let container = try self.provider.getCachedContainer(for: pkgTerm.node.package) + let container = try self.provider.getCachedContainer(for: pkgTerm.package) // Get the best available version for this package. guard let version = try container.getBestAvailableVersion(for: pkgTerm) else { state.addIncompatibility(try Incompatibility(pkgTerm, root: state.root, cause: .noAvailableVersion), at: .decisionMaking) - return completion(.success(pkgTerm.node)) + return completion(.success(pkgTerm.package)) } // Add all of this version's dependencies as incompatibilities. let depIncompatibilities = try container.incompatibilites( at: version, - node: pkgTerm.node, + package: pkgTerm.package, overriddenPackages: state.overriddenPackages, root: state.root ) @@ -663,17 +624,17 @@ public struct PubgrubDependencyResolver { // are satisfied because we _know_ that the terms matching // this package will be satisfied if we make this version // as a decision. - $0.node == pkgTerm.node || state.solution.satisfies($0) + $0.package == pkgTerm.package || state.solution.satisfies($0) } } // Decide this version if there was no conflict with its dependencies. if !haveConflict { self.delegate?.didResolve(term: pkgTerm, version: version, duration: start.distance(to: .now())) - state.decide(pkgTerm.node, at: version) + state.decide(pkgTerm.package, at: version) } - completion(.success(pkgTerm.node)) + completion(.success(pkgTerm.package)) } catch { completion(.failure(error)) } @@ -682,16 +643,16 @@ public struct PubgrubDependencyResolver { } private struct DiagnosticReportBuilder { - let rootNode: DependencyResolutionNode - let incompatibilities: [DependencyResolutionNode: [Incompatibility]] + let rootPackage: PackageReference + let incompatibilities: [PackageReference: [Incompatibility]] private var lines: [(number: Int, message: String)] = [] private var derivations: [Incompatibility: Int] = [:] private var lineNumbers: [Incompatibility: Int] = [:] private let provider: ContainerProvider - init(root: DependencyResolutionNode, incompatibilities: [DependencyResolutionNode: [Incompatibility]], provider: ContainerProvider) { - self.rootNode = root + init(root: PackageReference, incompatibilities: [PackageReference: [Incompatibility]], provider: ContainerProvider) { + self.rootPackage = root self.incompatibilities = incompatibilities self.provider = provider } @@ -849,7 +810,7 @@ private struct DiagnosticReportBuilder { private func description(for incompatibility: Incompatibility) throws -> String { switch incompatibility.cause { - case .dependency(node: _): + case .dependency(package: _): assert(incompatibility.terms.count == 2) let depender = incompatibility.terms.first! let dependee = incompatibility.terms.last! @@ -863,13 +824,13 @@ private struct DiagnosticReportBuilder { assert(incompatibility.terms.count == 1) let term = incompatibility.terms.first! assert(term.isPositive) - return "no versions of \(term.node.nameForDiagnostics) match the requirement \(term.requirement)" + return "no versions of '\(term.package.identity)' match the requirement \(term.requirement)" case .root: // FIXME: This will never happen I think. assert(incompatibility.terms.count == 1) let term = incompatibility.terms.first! assert(term.isPositive) - return "\(term.node.nameForDiagnostics) is \(term.requirement)" + return "'\(term.package.identity)' is \(term.requirement)" case .conflict: break case .versionBasedDependencyContainsUnversionedDependency(let versionedDependency, let unversionedDependency): @@ -886,16 +847,16 @@ private struct DiagnosticReportBuilder { let terms = incompatibility.terms if terms.count == 1 { let term = terms.first! - let prefix = try hasEffectivelyAnyRequirement(term) ? term.node.nameForDiagnostics : description(for: term, normalizeRange: true) + let prefix = try hasEffectivelyAnyRequirement(term) ? "'\(term.package.identity)'" : description(for: term, normalizeRange: true) return "\(prefix) " + (term.isPositive ? "cannot be used" : "is required") } else if terms.count == 2 { let term1 = terms.first! let term2 = terms.last! if term1.isPositive == term2.isPositive { if term1.isPositive { - return "\(term1.node.nameForDiagnostics) is incompatible with \(term2.node.nameForDiagnostics)" + return "'\(term1.package.identity)' is incompatible with '\(term2.package.identity)'" } else { - return "either \(term1.node.nameForDiagnostics) or \(term2)" + return "either '\(term1.package.identity)' or \(term2)" } } } @@ -926,7 +887,7 @@ private struct DiagnosticReportBuilder { return false case .range(let range): // container expected to be cached at this point - guard let container = try? provider.getCachedContainer(for: term.node.package) else { + guard let container = try? provider.getCachedContainer(for: term.package) else { return false } let bounds = try container.computeBounds(for: range) @@ -958,36 +919,36 @@ private struct DiagnosticReportBuilder { // FIXME: This is duplicated and wrong. private func isFailure(_ incompatibility: Incompatibility) -> Bool { - return incompatibility.terms.count == 1 && incompatibility.terms.first?.node.package.identity == .plain("") + return incompatibility.terms.count == 1 && incompatibility.terms.first?.package.identity == .plain("") } private func description(for term: Term, normalizeRange: Bool = false) throws -> String { - let name = term.node.nameForDiagnostics + let name = term.package.identity.description switch term.requirement { - case .any: return name - case .empty: return "no version of \(name)" + case .any: return "'\(name)'" + case .empty: return "no version of '\(name)'" case .exact(let version): // For the root package, don't output the useless version 1.0.0. - if term.node == rootNode { + if term.package == self.rootPackage { return "root" } - return "\(name) \(version)" + return "'\(name)' \(version)" case .range(let range): // container expected to be cached at this point - guard normalizeRange, let container = try? provider.getCachedContainer(for: term.node.package) else { - return "\(name) \(range.description)" + guard normalizeRange, let container = try? provider.getCachedContainer(for: term.package) else { + return "'\(name)' \(range.description)" } switch try container.computeBounds(for: range) { case (true, true): - return "\(name) \(range.description)" + return "'\(name)' \(range.description)" case (false, false): - return name + return "'\(name)'" case (true, false): - return "\(name) >= \(range.lowerBound)" + return "'\(name)' >= \(range.lowerBound)" case (false, true): - return "\(name) < \(range.upperBound)" + return "'\(name)' < \(range.upperBound)" } case .ranges(let ranges): let ranges = "{" + ranges.map { @@ -996,7 +957,7 @@ private struct DiagnosticReportBuilder { } return $0.lowerBound.description + "..<" + $0.upperBound.description }.joined(separator: ", ") + "}" - return "\(name) \(ranges)" + return "'\(name)' \(ranges)" } } @@ -1157,22 +1118,19 @@ private final class PubGrubPackageContainer { /// Returns the incompatibilities of a package at the given version. func incompatibilites( at version: Version, - node: DependencyResolutionNode, - overriddenPackages: [PackageReference: (version: BoundVersion, products: ProductFilter)], - root: DependencyResolutionNode + package: PackageReference, + overriddenPackages: [PackageReference: BoundVersion], + root: PackageReference ) throws -> [Incompatibility] { // FIXME: It would be nice to compute bounds for this as well. if !self.underlying.isToolsVersionCompatible(at: version) { let requirement = try self.computeIncompatibleToolsVersionBounds(fromVersion: version) let toolsVersion = try self.underlying.toolsVersion(for: version) - return [try Incompatibility(Term(node, requirement), root: root, cause: .incompatibleToolsVersion(toolsVersion))] + return [try Incompatibility(Term(package, requirement), root: root, cause: .incompatibleToolsVersion(toolsVersion))] } - var unprocessedDependencies = try self.underlying.getDependencies(at: version, productFilter: node.productFilter) - if let sharedVersion = node.versionLock(version: version) { - unprocessedDependencies.append(sharedVersion) - } var constraints: [PackageContainerConstraint] = [] + let unprocessedDependencies = try self.underlying.getDependencies(at: version) for dep in unprocessedDependencies { // Version-based packages are not allowed to contain unversioned dependencies. guard case .versionSet = dep.requirement else { @@ -1180,7 +1138,7 @@ private final class PubGrubPackageContainer { versionedDependency: package, unversionedDependency: dep.package ) - return [try Incompatibility(Term(node, .exact(version)), root: root, cause: cause)] + return [try Incompatibility(Term(package, .exact(version)), root: root, cause: cause)] } // Skip if this package is overriden. @@ -1207,23 +1165,22 @@ private final class PubGrubPackageContainer { // Since the pinned version is most likely to succeed, we don't compute bounds for its // incompatibilities. - return try Array(constraints.map { (constraint: PackageContainerConstraint) -> [Incompatibility] in - guard case .versionSet(let vs) = constraint.requirement else { + return try constraints.map { constraint in + guard case .versionSet(let versionSet) = constraint.requirement else { throw InternalError("Unexpected unversioned requirement: \(constraint)") } - return try constraint.nodes().map { dependencyNode in - var terms: OrderedSet = [] - terms.append(Term(node, .exact(version))) - terms.append(Term(not: dependencyNode, vs)) - return try Incompatibility(terms, root: root, cause: .dependency(node: node)) - } - }.joined()) + var terms: OrderedSet = [] + terms.append(Term(self.underlying.package, .exact(version))) + terms.append(Term(not: constraint.package, versionSet)) + return try Incompatibility(terms, root: root, cause: .dependency(package: self.underlying.package)) + } } - let (lowerBounds, upperBounds) = try self.computeBounds(for: node, - constraints: constraints, - startingWith: version, - products: node.productFilter) + let (lowerBounds, upperBounds) = try self.computeBounds( + for: package, + constraints: constraints, + startingWith: version + ) return try constraints.map { constraint in var terms: OrderedSet = [] @@ -1232,20 +1189,19 @@ private final class PubGrubPackageContainer { assert(lowerBound < upperBound) // We only have version-based requirements at this point. - guard case .versionSet(let vs) = constraint.requirement else { + guard case .versionSet(let versionSet) = constraint.requirement else { throw InternalError("Unexpected unversioned requirement: \(constraint)") } - for constraintNode in constraint.nodes() { - let requirement: VersionSetSpecifier = .range(lowerBound ..< upperBound) - terms.append(Term(node, requirement)) - terms.append(Term(not: constraintNode, vs)) + let requirement: VersionSetSpecifier = .range(lowerBound ..< upperBound) + terms.append(Term(self.underlying.package, requirement)) + terms.append(Term(not: constraint.package, versionSet)) - // Make a record for this dependency so we don't have to recompute the bounds when the selected version falls within the bounds. - self.emittedIncompatibilities[constraint.package] = requirement.union(emittedIncompatibilities[constraint.package] ?? .empty) - } + // Make a record for this dependency so we don't have to recompute the bounds when the selected version falls within the bounds. + self.emittedIncompatibilities[constraint.package] = requirement.union(emittedIncompatibilities[constraint.package] ?? .empty) - return try Incompatibility(terms, root: root, cause: .dependency(node: node)) + + return try Incompatibility(terms, root: root, cause: .dependency(package: self.underlying.package)) } } @@ -1256,10 +1212,9 @@ private final class PubGrubPackageContainer { /// above or below the given version. As with regular version ranges, the lower bound is /// inclusive and the upper bound is exclusive. private func computeBounds( - for node: DependencyResolutionNode, + for package: PackageReference, constraints: [PackageContainerConstraint], - startingWith firstVersion: Version, - products: ProductFilter + startingWith firstVersion: Version ) throws -> (lowerBounds: [PackageReference: Version], upperBounds: [PackageReference: Version]) { let preloadCount = 3 @@ -1273,7 +1228,7 @@ private final class PubGrubPackageContainer { for version in versions { DispatchQueue.sharedConcurrent.async(group: sync) { if self.underlying.isToolsVersionCompatible(at: version) { - _ = try? self.underlying.getDependencies(at: version, productFilter: products) + _ = try? self.underlying.getDependencies(at: version) } } } @@ -1305,7 +1260,7 @@ private final class PubGrubPackageContainer { result[constraint.package] = bound } else { // Get the dependencies at this version. - if let currentDependencies = try? self.underlying.getDependencies(at: version, productFilter: products) { + if let currentDependencies = try? self.underlying.getDependencies(at: version/*, productFilter: products*/) { // Record this version as the bound for our list of dependencies, if appropriate. if currentDependencies.first(where: { $0.package == constraint.package }) != constraint { result[constraint.package] = bound @@ -1328,7 +1283,7 @@ private final class PubGrubPackageContainer { let versions: [Version] = try self.underlying.versionsAscending() guard let idx = versions.firstIndex(of: firstVersion) else { - throw InternalError("from version \(firstVersion) not found in \(node.package.name)") + throw InternalError("from version \(firstVersion) not found in \(package.identity)") } let sync = DispatchGroup() @@ -1346,7 +1301,7 @@ private final class PubGrubPackageContainer { // timeout is a function of # of versions since we need to make several git operations per tag/version let timeout = DispatchTimeInterval.seconds(60 + versions.count) guard case .success = sync.wait(timeout: .now() + timeout) else { - throw StringError("timeout computing '\(node.package.name)' bounds") + throw StringError("timeout computing '\(package.identity)' bounds") } return (lowerBounds, upperBounds) @@ -1452,7 +1407,7 @@ internal enum LogLocation: String { extension PubgrubDependencyResolver { public enum PubgrubError: Swift.Error, CustomStringConvertible { - case _unresolvable(Incompatibility, [DependencyResolutionNode: [Incompatibility]]) + case _unresolvable(Incompatibility, [PackageReference: [Incompatibility]]) case unresolvable(String) public var description: String { @@ -1473,7 +1428,7 @@ extension PubgrubDependencyResolver { } } - var incompatibilities: [DependencyResolutionNode: [Incompatibility]]? { + var incompatibilities: [PackageReference: [Incompatibility]]? { switch self { case ._unresolvable(_, let incompatibilities): return incompatibilities @@ -1486,18 +1441,18 @@ extension PubgrubDependencyResolver { extension PubgrubDependencyResolver { private struct VersionBasedConstraint { - let node: DependencyResolutionNode + let package: PackageReference let requirement: VersionSetSpecifier - init(node: DependencyResolutionNode, req: VersionSetSpecifier) { - self.node = node - self.requirement = req + init(package: PackageReference, requirement: VersionSetSpecifier) { + self.package = package + self.requirement = requirement } - internal static func constraints(_ constraint: Constraint) -> [VersionBasedConstraint]? { + internal init?(_ constraint: Constraint) { switch constraint.requirement { - case .versionSet(let req): - return constraint.nodes().map { VersionBasedConstraint(node: $0, req: req) } + case .versionSet(let requirement): + self.init(package: constraint.package, requirement: requirement) case .revision: return nil case .unversioned: @@ -1509,7 +1464,7 @@ extension PubgrubDependencyResolver { private enum PropagationResult { case conflict - case almostSatisfied(node: DependencyResolutionNode) + case almostSatisfied(package: PackageReference) case none } @@ -1524,8 +1479,9 @@ private extension PackageRequirement { } } +/* private extension DependencyResolutionNode { var nameForDiagnostics: String { return "'\(package.name)'" } -} +}*/ diff --git a/Sources/PackageGraph/Pubgrub/Term.swift b/Sources/PackageGraph/Pubgrub/Term.swift index 9d9b4ecc910..a91ead0fb81 100644 --- a/Sources/PackageGraph/Pubgrub/Term.swift +++ b/Sources/PackageGraph/Pubgrub/Term.swift @@ -8,47 +8,49 @@ See http://swift.org/CONTRIBUTORS.txt for Swift project authors */ +import PackageModel + /// A term represents a statement about a package that may be true or false. public struct Term: Equatable, Hashable { - public let node: DependencyResolutionNode + public let package: PackageReference public let requirement: VersionSetSpecifier public let isPositive: Bool - public init(node: DependencyResolutionNode, requirement: VersionSetSpecifier, isPositive: Bool) { - self.node = node + public init(package: PackageReference, requirement: VersionSetSpecifier, isPositive: Bool) { + self.package = package self.requirement = requirement self.isPositive = isPositive } - public init(_ node: DependencyResolutionNode, _ requirement: VersionSetSpecifier) { - self.init(node: node, requirement: requirement, isPositive: true) + public init(_ package: PackageReference, _ requirement: VersionSetSpecifier) { + self.init(package: package, requirement: requirement, isPositive: true) } /// Create a new negative term. - public init(not node: DependencyResolutionNode, _ requirement: VersionSetSpecifier) { - self.init(node: node, requirement: requirement, isPositive: false) + public init(not package: PackageReference, _ requirement: VersionSetSpecifier) { + self.init(package: package, requirement: requirement, isPositive: false) } /// The same term with an inversed `isPositive` value. public var inverse: Term { return Term( - node: node, - requirement: requirement, - isPositive: !isPositive) + package: self.package, + requirement: self.requirement, + isPositive: !self.isPositive) } /// Check if this term satisfies another term, e.g. if `self` is true, /// `other` must also be true. public func satisfies(_ other: Term) -> Bool { // TODO: This probably makes more sense as isSatisfied(by:) instead. - guard self.node == other.node else { return false } + guard self.package == other.package else { return false } return self.relation(with: other) == .subset } /// Create an intersection with another term. public func intersect(with other: Term) -> Term? { - guard self.node == other.node else { return nil } - return intersect(withRequirement: other.requirement, andPolarity: other.isPositive) + guard self.package == other.package else { return nil } + return self.intersect(withRequirement: other.requirement, andPolarity: other.isPositive) } /// Create an intersection with a requirement and polarity returning a new @@ -84,7 +86,7 @@ public struct Term: Equatable, Hashable { return nil } - return Term(node: node, requirement: versionIntersection, isPositive: isPositive) + return Term(package: self.package, requirement: versionIntersection, isPositive: isPositive) } public func difference(with other: Term) -> Term? { @@ -97,7 +99,7 @@ public struct Term: Equatable, Hashable { /// - There has to be no decision for it. /// - The package version has to match all assignments. public func isValidDecision(for solution: PartialSolution) -> Bool { - for assignment in solution.assignments where assignment.term.node == node { + for assignment in solution.assignments where assignment.term.package == package { assert(!assignment.isDecision, "Expected assignment to be a derivation.") guard satisfies(assignment.term) else { return false } } @@ -106,7 +108,7 @@ public struct Term: Equatable, Hashable { // From: https://github.com/dart-lang/pub/blob/master/lib/src/solver/term.dart public func relation(with other: Term) -> SetRelation { - if self.node != other.node { + if self.package != other.package { assertionFailure("attempting to compute relation between different packages \(self) \(other)") return .error } @@ -165,7 +167,7 @@ public struct Term: Equatable, Hashable { extension Term: CustomStringConvertible { public var description: String { - let pkg = "\(node)" + let pkg = "\(package.identity)" let req = requirement.description if !isPositive { diff --git a/Sources/PackageLoading/ManifestJSONParser.swift b/Sources/PackageLoading/ManifestJSONParser.swift index 5721e188c33..9d211bc1584 100644 --- a/Sources/PackageLoading/ManifestJSONParser.swift +++ b/Sources/PackageLoading/ManifestJSONParser.swift @@ -119,7 +119,7 @@ enum ManifestJSONParser { let identity: String = try kindJSON.get("identity") let requirementJSON: JSON = try kindJSON.get("requirement") let requirement = try PackageDependency.Registry.Requirement(v4: requirementJSON) - return .registry(identity: .plain(identity), requirement: requirement, productFilter: .everything) + return .registry(identity: .plain(identity), requirement: requirement) } else { throw InternalError("Unknown dependency type \(kindJSON)") } @@ -138,8 +138,8 @@ enum ManifestJSONParser { at: url, name: name, identityResolver: identityResolver, - fileSystem: fileSystem) - + fileSystem: fileSystem + ) default: let requirement = try PackageDependency.SourceControl.Requirement(v4: requirementJSON) return try Self.makeSourceControlDependency( @@ -148,7 +148,8 @@ enum ManifestJSONParser { name: name, requirement: requirement, identityResolver: identityResolver, - fileSystem: fileSystem) + fileSystem: fileSystem + ) } } } @@ -168,10 +169,11 @@ enum ManifestJSONParser { throw ManifestParseError.invalidManifestFormat("'\(path)' is not a valid path for path-based dependencies; use relative or absolute path instead.", diagnosticFile: nil) } let identity = try identityResolver.resolveIdentity(for: path) - return .fileSystem(identity: identity, - nameForTargetDependencyResolutionOnly: name, - path: path, - productFilter: .everything) + return .fileSystem( + identity: identity, + nameForTargetDependencyResolutionOnly: name, + path: path + ) } private static func makeSourceControlDependency( @@ -203,8 +205,7 @@ enum ManifestJSONParser { identity: identity, nameForTargetDependencyResolutionOnly: name, path: localPath, - requirement: requirement, - productFilter: .everything + requirement: requirement ) } else if let url = URL(string: location){ // in the future this will check with the registries for the identity of the URL @@ -213,8 +214,7 @@ enum ManifestJSONParser { identity: identity, nameForTargetDependencyResolutionOnly: name, url: url, - requirement: requirement, - productFilter: .everything + requirement: requirement ) } else { throw StringError("invalid location: \(location)") diff --git a/Sources/PackageLoading/ManifestLoader.swift b/Sources/PackageLoading/ManifestLoader.swift index 99e0749085d..c87faa6d975 100644 --- a/Sources/PackageLoading/ManifestLoader.swift +++ b/Sources/PackageLoading/ManifestLoader.swift @@ -47,7 +47,7 @@ public protocol ManifestLoaderProtocol { packageKind: PackageReference.Kind, packageLocation: String, version: Version?, - revision: String?, + //revision: String?, toolsVersion: ToolsVersion, identityResolver: IdentityResolver, fileSystem: FileSystem, @@ -169,7 +169,7 @@ public final class ManifestLoader: ManifestLoaderProtocol { packageKind: .root(packageLocation), packageLocation: packageLocation.pathString, version: nil, - revision: nil, + //revision: nil, toolsVersion: toolsVersion, identityResolver: identityResolver, fileSystem: fileSystem, @@ -188,7 +188,7 @@ public final class ManifestLoader: ManifestLoaderProtocol { packageKind: PackageReference.Kind, packageLocation: String, version: Version?, - revision: String?, + //revision: String?, toolsVersion: ToolsVersion, identityResolver: IdentityResolver, fileSystem: FileSystem, @@ -203,7 +203,7 @@ public final class ManifestLoader: ManifestLoaderProtocol { packageKind: packageKind, packageLocation: packageLocation, version: version, - revision: revision, + //revision: revision, toolsVersion: toolsVersion, identityResolver: identityResolver, fileSystem: fileSystem, @@ -221,7 +221,7 @@ public final class ManifestLoader: ManifestLoaderProtocol { packageKind: PackageReference.Kind, packageLocation: String, version: Version?, - revision: String?, + //revision: String?, toolsVersion: ToolsVersion, identityResolver: IdentityResolver, fileSystem: FileSystem, @@ -278,7 +278,7 @@ public final class ManifestLoader: ManifestLoaderProtocol { defaultLocalization: parsedManifest.defaultLocalization, platforms: parsedManifest.platforms, version: version, - revision: revision, + //revision: revision, toolsVersion: toolsVersion, pkgConfig: parsedManifest.pkgConfig, providers: parsedManifest.providers, diff --git a/Sources/PackageLoading/PackageBuilder.swift b/Sources/PackageLoading/PackageBuilder.swift index d96994bdb13..cf806c47f64 100644 --- a/Sources/PackageLoading/PackageBuilder.swift +++ b/Sources/PackageLoading/PackageBuilder.swift @@ -215,9 +215,6 @@ public final class PackageBuilder { /// The manifest for the package being constructed. private let manifest: Manifest - /// The product filter to apply to the package. - private let productFilter: ProductFilter - /// The path of the package. private let packagePath: AbsolutePath @@ -260,7 +257,7 @@ public final class PackageBuilder { public init( identity: PackageIdentity, manifest: Manifest, - productFilter: ProductFilter, + //productFilter: ProductFilter, path: AbsolutePath, additionalFileRules: [FileRuleDescription] = [], binaryArtifacts: [BinaryArtifact], @@ -273,7 +270,6 @@ public final class PackageBuilder { ) { self.identity = identity self.manifest = manifest - self.productFilter = productFilter self.packagePath = path self.additionalFileRules = additionalFileRules self.binaryArtifacts = binaryArtifacts @@ -320,7 +316,7 @@ public final class PackageBuilder { let builder = PackageBuilder( identity: identity, manifest: manifest, - productFilter: .everything, + //productFilter: .everything, path: path, binaryArtifacts: [], // this will fail for packages with binary artifacts, but this API is deprecated and the replacement API was fixed xcTestMinimumDeploymentTargets: xcTestMinimumDeploymentTargets, @@ -585,7 +581,8 @@ public final class PackageBuilder { // Create potential targets. let potentialTargets: [PotentialModule] - potentialTargets = try manifest.targetsRequired(for: productFilter).map({ target in + //potentialTargets = try manifest.targetsRequired(for: productFilter).map({ target in + potentialTargets = try manifest.requiredTargets().map({ target in let path = try findPath(for: target) return PotentialModule(name: target.name, path: path, type: target.type) }) @@ -611,7 +608,7 @@ public final class PackageBuilder { // Create targets from the provided potential targets. private func createModules(_ potentialModules: [PotentialModule]) throws -> [Target] { // Find if manifest references a target which isn't present on disk. - let allVisibleModuleNames = manifest.visibleModuleNames(for: productFilter) + let allVisibleModuleNames = manifest.visibleModuleNames //manifest.visibleModuleNames(for: productFilter) let potentialModulesName = Set(potentialModules.map({ $0.name })) let missingModuleNames = allVisibleModuleNames.subtracting(potentialModulesName) if let missingModuleName = missingModuleNames.first { @@ -1218,14 +1215,14 @@ public final class PackageBuilder { // First add explicit products. - let filteredProducts: [ProductDescription] + /*let filteredProducts: [ProductDescription] switch productFilter { case .everything: filteredProducts = self.manifest.products case .specific(let set): filteredProducts = self.manifest.products.filter { set.contains($0.name) } - } - for product in filteredProducts { + }*/ + for product in manifest.products { let targets = try modulesFrom(targetNames: product.targets, product: product.name) // Perform special validations if this product is exporting // a system library target. @@ -1379,17 +1376,17 @@ private struct PotentialModule: Hashable { private extension Manifest { /// Returns the names of all the visible targets in the manifest. - func visibleModuleNames(for productFilter: ProductFilter) -> Set { - let names = targetsRequired(for: productFilter).flatMap({ target in - [target.name] + target.dependencies.compactMap({ + var visibleModuleNames: Set { + let names = self.requiredTargets().flatMap{ target in + [target.name] + target.dependencies.compactMap{ switch $0 { case .target(let name, _): return name case .byName, .product: return nil } - }) - }) + } + } return Set(names) } } diff --git a/Sources/PackageModel/Manifest.swift b/Sources/PackageModel/Manifest.swift index b479b165720..f27b443480c 100644 --- a/Sources/PackageModel/Manifest.swift +++ b/Sources/PackageModel/Manifest.swift @@ -58,7 +58,7 @@ public final class Manifest { public let version: Version? /// The revision this package was loaded from, if known. - public let revision: String? + //public let revision: String? /// The tools version declared in the manifest. public let toolsVersion: ToolsVersion @@ -97,10 +97,10 @@ public final class Manifest { public let providers: [SystemPackageProviderDescription]? /// Targets required for building particular product filters. - private var _requiredTargets = ThreadSafeKeyValueStore() + //private var _requiredTargets = ThreadSafeKeyValueStore() /// Dependencies required for building particular product filters. - private var _requiredDependencies = ThreadSafeKeyValueStore() + //private var _requiredDependencies = ThreadSafeKeyValueStore() public init( name: String, @@ -110,7 +110,7 @@ public final class Manifest { defaultLocalization: String? = nil, platforms: [PlatformDescription], version: TSCUtility.Version? = nil, - revision: String? = nil, + //revision: String? = nil, toolsVersion: ToolsVersion, pkgConfig: String? = nil, providers: [SystemPackageProviderDescription]? = nil, @@ -128,7 +128,7 @@ public final class Manifest { self.defaultLocalization = defaultLocalization self.platforms = platforms self.version = version - self.revision = revision + //self.revision = revision self.toolsVersion = toolsVersion self.pkgConfig = pkgConfig self.providers = providers @@ -140,7 +140,73 @@ public final class Manifest { self.targets = targets self.targetMap = Dictionary(targets.lazy.map({ ($0.name, $0) }), uniquingKeysWith: { $1 }) } +} + +extension Manifest { + + /// Returns the targets required for building the provided products. + public func requiredTargets(for productsFilter: [ProductDescription]? = .none) -> [TargetDescription] { + if case .root = self.packageKind { + return self.targets + } + + let products = productsFilter ?? self.products + + let targetsByName = Dictionary(targets.map({ ($0.name, $0) }), uniquingKeysWith: { $1 }) + let productTargetNames = products.flatMap({ $0.targets }) + + let dependentTargetNames = transitiveClosure(productTargetNames, successors: { targetName in + + if let target = targetsByName[targetName] { + let dependencies: [String] = target.dependencies.compactMap { dependency in + switch dependency { + case .target(let name, _), .byName(let name, _): + return targetsByName.keys.contains(name) ? name : nil + default: + return nil + } + } + + let plugins: [String] = target.pluginUsages?.compactMap { pluginUsage in + switch pluginUsage { + case .plugin(name: let name, package: nil): + return targetsByName.keys.contains(name) ? name : nil + default: + return nil + } + } ?? [] + + return dependencies + plugins + } + + return [] + }) + let requiredTargetNames = Set(productTargetNames).union(dependentTargetNames) + let requiredTargets = requiredTargetNames.compactMap{ targetsByName[$0] } + return requiredTargets + } + + public func requiredDependencies(for productsFilter: [ProductDescription]? = .none) -> [PackageDependency] { + if self.packageKind.isRoot || self.toolsVersion < .v5_2 { + return self.dependencies + } + + var requiredDependencies: Set = [] + + for target in self.requiredTargets(for: productsFilter) { + for targetDependency in target.dependencies { + if let dependency = self.packageDependency(referencedBy: targetDependency) { + requiredDependencies.insert(dependency.identity) + } + } + } + + return self.dependencies.filter { requiredDependencies.contains($0.identity) } + + } + + /* /// Returns the targets required for a particular product filter. public func targetsRequired(for productFilter: ProductFilter) -> [TargetDescription] { #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION @@ -274,7 +340,7 @@ public final class Manifest { return nil } } - } + }*/ /// Finds the package dependency referenced by the specified target dependency. /// - Returns: Returns `nil` if the dependency is a target dependency, if it is a product dependency but has no @@ -298,6 +364,7 @@ public final class Manifest { }) } + /* /// Registers a required product with a particular dependency if possible, or registers it as unknown. /// /// - Parameters: @@ -382,6 +449,7 @@ public final class Manifest { return false } } + */ } extension Manifest: Hashable { diff --git a/Sources/PackageModel/Manifest/PackageDependencyDescription.swift b/Sources/PackageModel/Manifest/PackageDependencyDescription.swift index 46f46ea3a99..4bdf65179d2 100644 --- a/Sources/PackageModel/Manifest/PackageDependencyDescription.swift +++ b/Sources/PackageModel/Manifest/PackageDependencyDescription.swift @@ -21,7 +21,6 @@ public enum PackageDependency: Equatable { public let identity: PackageIdentity public let nameForTargetDependencyResolutionOnly: String? public let path: AbsolutePath - public let productFilter: ProductFilter } public struct SourceControl: Equatable, Encodable { @@ -29,7 +28,6 @@ public enum PackageDependency: Equatable { public let nameForTargetDependencyResolutionOnly: String? public let location: Location public let requirement: Requirement - public let productFilter: ProductFilter public enum Requirement: Equatable, Hashable { case exact(Version) @@ -47,7 +45,6 @@ public enum PackageDependency: Equatable { public struct Registry: Equatable, Encodable { public let identity: PackageIdentity public let requirement: Requirement - public let productFilter: ProductFilter /// The dependency requirement. public enum Requirement: Equatable, Hashable { @@ -98,54 +95,38 @@ public enum PackageDependency: Equatable { } } - public var productFilter: ProductFilter { - switch self { - case .fileSystem(let settings): - return settings.productFilter - case .sourceControl(let settings): - return settings.productFilter - case .registry(let settings): - return settings.productFilter - } - } - public func filtered(by productFilter: ProductFilter) -> Self { switch self { case .fileSystem(let settings): return .fileSystem( identity: settings.identity, nameForTargetDependencyResolutionOnly: settings.nameForTargetDependencyResolutionOnly, - path: settings.path, - productFilter: productFilter + path: settings.path ) case .sourceControl(let settings): return .sourceControl( identity: settings.identity, nameForTargetDependencyResolutionOnly: settings.nameForTargetDependencyResolutionOnly, location: settings.location, - requirement: settings.requirement, - productFilter: productFilter + requirement: settings.requirement ) case .registry(let settings): return .registry( identity: settings.identity, - requirement: settings.requirement, - productFilter: productFilter + requirement: settings.requirement ) } } public static func fileSystem(identity: PackageIdentity, nameForTargetDependencyResolutionOnly: String?, - path: AbsolutePath, - productFilter: ProductFilter + path: AbsolutePath ) -> Self { .fileSystem( .init( identity: identity, nameForTargetDependencyResolutionOnly: nameForTargetDependencyResolutionOnly, - path: path, - productFilter: productFilter + path: path ) ) } @@ -153,59 +134,49 @@ public enum PackageDependency: Equatable { public static func localSourceControl(identity: PackageIdentity, nameForTargetDependencyResolutionOnly: String?, path: AbsolutePath, - requirement: SourceControl.Requirement, - productFilter: ProductFilter + requirement: SourceControl.Requirement ) -> Self { .sourceControl( identity: identity, nameForTargetDependencyResolutionOnly: nameForTargetDependencyResolutionOnly, location: .local(path), - requirement: requirement, - productFilter: productFilter + requirement: requirement ) } public static func remoteSourceControl(identity: PackageIdentity, nameForTargetDependencyResolutionOnly: String?, url: Foundation.URL, - requirement: SourceControl.Requirement, - productFilter: ProductFilter + requirement: SourceControl.Requirement ) -> Self { .sourceControl( identity: identity, nameForTargetDependencyResolutionOnly: nameForTargetDependencyResolutionOnly, location: .remote(url), - requirement: requirement, - productFilter: productFilter + requirement: requirement ) } public static func sourceControl(identity: PackageIdentity, nameForTargetDependencyResolutionOnly: String?, location: SourceControl.Location, - requirement: SourceControl.Requirement, - productFilter: ProductFilter + requirement: SourceControl.Requirement ) -> Self { .sourceControl( .init( identity: identity, nameForTargetDependencyResolutionOnly: nameForTargetDependencyResolutionOnly, location: location, - requirement: requirement, - productFilter: productFilter + requirement: requirement ) ) } - public static func registry(identity: PackageIdentity, - requirement: Registry.Requirement, - productFilter: ProductFilter - ) -> Self { + public static func registry(identity: PackageIdentity, requirement: Registry.Requirement) -> Self { .registry( .init( identity: identity, - requirement: requirement, - productFilter: productFilter + requirement: requirement ) ) } diff --git a/Sources/PackageRegistry/RegistryManager.swift b/Sources/PackageRegistry/RegistryManager.swift index ded77f82a3b..b9c82621976 100644 --- a/Sources/PackageRegistry/RegistryManager.swift +++ b/Sources/PackageRegistry/RegistryManager.swift @@ -169,7 +169,7 @@ public final class RegistryManager { packageKind: .registry(package.identity), packageLocation: package.locationString, version: version, - revision: nil, + //revision: nil, toolsVersion: .currentToolsVersion, identityResolver: self.identityResolver, fileSystem: fileSystem, diff --git a/Sources/SPMTestSupport/MockDependency.swift b/Sources/SPMTestSupport/MockDependency.swift index 00543f6329f..6473cf8bd0b 100644 --- a/Sources/SPMTestSupport/MockDependency.swift +++ b/Sources/SPMTestSupport/MockDependency.swift @@ -18,12 +18,10 @@ public struct MockDependency { public let deprecatedName: String? public let location: Location - public let products: ProductFilter - init(deprecatedName: String? = nil, location: Location, products: ProductFilter = .everything) { + init(deprecatedName: String? = nil, location: Location) { self.deprecatedName = deprecatedName self.location = location - self.products = products } // TODO: refactor this when adding registry support @@ -36,8 +34,7 @@ public struct MockDependency { return .fileSystem( identity: identity, deprecatedName: self.deprecatedName, - path: remappedPath, - productFilter: self.products + path: remappedPath ) case .localSourceControl(let path, let requirement): let absolutePath = baseURL.appending(path) @@ -47,8 +44,7 @@ public struct MockDependency { identity: identity, deprecatedName: self.deprecatedName, path: remappedPath, - requirement: requirement, - productFilter: self.products + requirement: requirement ) case .remoteSourceControl(let url, let requirement): let remappedURLString = identityResolver.mappedLocation(for: url.absoluteString) @@ -60,34 +56,33 @@ public struct MockDependency { identity: identity, deprecatedName: self.deprecatedName, url: remappedURL, - requirement: requirement, - productFilter: self.products + requirement: requirement ) } } - public static func fileSystem(path: String, products: ProductFilter = .everything) -> MockDependency { - MockDependency(location: .fileSystem(path: RelativePath(path)), products: products) + public static func fileSystem(path: String) -> MockDependency { + MockDependency(location: .fileSystem(path: RelativePath(path))) } - public static func sourceControl(path: String, requirement: Requirement, products: ProductFilter = .everything) -> MockDependency { - .sourceControl(path: RelativePath(path), requirement: requirement, products: products) + public static func sourceControl(path: String, requirement: Requirement) -> MockDependency { + .sourceControl(path: RelativePath(path), requirement: requirement) } - public static func sourceControl(path: RelativePath, requirement: Requirement, products: ProductFilter = .everything) -> MockDependency { - MockDependency(location: .localSourceControl(path: path, requirement: requirement), products: products) + public static func sourceControl(path: RelativePath, requirement: Requirement) -> MockDependency { + MockDependency(location: .localSourceControl(path: path, requirement: requirement)) } - public static func sourceControlWithDeprecatedName(name: String, path: String, requirement: Requirement, products: ProductFilter = .everything) -> MockDependency { - MockDependency(deprecatedName: name, location: .localSourceControl(path: RelativePath(path), requirement: requirement), products: products) + public static func sourceControlWithDeprecatedName(name: String, path: String, requirement: Requirement) -> MockDependency { + MockDependency(deprecatedName: name, location: .localSourceControl(path: RelativePath(path), requirement: requirement)) } - public static func sourceControl(url: String, requirement: Requirement, products: ProductFilter = .everything) -> MockDependency { - .sourceControl(url: URL(string: url)!, requirement: requirement, products: products) + public static func sourceControl(url: String, requirement: Requirement) -> MockDependency { + .sourceControl(url: URL(string: url)!, requirement: requirement) } - public static func sourceControl(url: URL, requirement: Requirement, products: ProductFilter = .everything) -> MockDependency { - MockDependency(location: .remoteSourceControl(url: url, requirement: requirement), products: products) + public static func sourceControl(url: URL, requirement: Requirement) -> MockDependency { + MockDependency(location: .remoteSourceControl(url: url, requirement: requirement)) } public enum Location { diff --git a/Sources/SPMTestSupport/MockManifestLoader.swift b/Sources/SPMTestSupport/MockManifestLoader.swift index 9aebd20b7e0..86af5bbc22c 100644 --- a/Sources/SPMTestSupport/MockManifestLoader.swift +++ b/Sources/SPMTestSupport/MockManifestLoader.swift @@ -53,7 +53,7 @@ public final class MockManifestLoader: ManifestLoaderProtocol { packageKind: PackageReference.Kind, packageLocation: String, version: Version?, - revision: String?, + //revision: String?, toolsVersion: ToolsVersion, identityResolver: IdentityResolver, fileSystem: FileSystem, @@ -110,7 +110,7 @@ extension ManifestLoader { packageKind: packageKind, packageLocation: packageLocation, version: nil, - revision: nil, + //revision: nil, toolsVersion: toolsVersion, identityResolver: identityResolver, fileSystem: fileSystem, diff --git a/Sources/SPMTestSupport/MockPackageContainer.swift b/Sources/SPMTestSupport/MockPackageContainer.swift index f542bca64ae..fc83a467dd6 100644 --- a/Sources/SPMTestSupport/MockPackageContainer.swift +++ b/Sources/SPMTestSupport/MockPackageContainer.swift @@ -40,19 +40,19 @@ public class MockPackageContainer: PackageContainer { return _versions } - public func getDependencies(at version: Version, productFilter: ProductFilter) -> [MockPackageContainer.Constraint] { + public func getDependencies(at version: Version) -> [MockPackageContainer.Constraint] { requestedVersions.insert(version) - return getDependencies(at: version.description, productFilter: productFilter) + return getDependencies(at: version.description) } - public func getDependencies(at revision: String, productFilter: ProductFilter) -> [MockPackageContainer.Constraint] { + public func getDependencies(at revision: String) -> [MockPackageContainer.Constraint] { return dependencies[revision]!.map { value in let (package, requirement) = value - return MockPackageContainer.Constraint(package: package, requirement: requirement, products: productFilter) + return MockPackageContainer.Constraint(package: package, requirement: requirement) } } - public func getUnversionedDependencies(productFilter: ProductFilter) -> [MockPackageContainer.Constraint] { + public func getUnversionedDependencies() -> [MockPackageContainer.Constraint] { return unversionedDeps } diff --git a/Sources/SPMTestSupport/PackageDependencyDescriptionExtensions.swift b/Sources/SPMTestSupport/PackageDependencyDescriptionExtensions.swift index 7bfc2a5e467..8502746cdbe 100644 --- a/Sources/SPMTestSupport/PackageDependencyDescriptionExtensions.swift +++ b/Sources/SPMTestSupport/PackageDependencyDescriptionExtensions.swift @@ -13,53 +13,54 @@ import PackageModel import TSCBasic public extension PackageDependency { - static func fileSystem(identity: PackageIdentity? = nil, - deprecatedName: String? = nil, - path: AbsolutePath, - productFilter: ProductFilter = .everything + static func fileSystem( + identity: PackageIdentity? = nil, + deprecatedName: String? = nil, + path: AbsolutePath ) -> Self { let identity = identity ?? PackageIdentity(path: path) - return .fileSystem(identity: identity, - nameForTargetDependencyResolutionOnly: deprecatedName, - path: path, - productFilter: productFilter) + return .fileSystem( + identity: identity, + nameForTargetDependencyResolutionOnly: deprecatedName, + path: path + ) } - - static func localSourceControl(identity: PackageIdentity? = nil, - deprecatedName: String? = nil, - path: AbsolutePath, - requirement: SourceControl.Requirement, - productFilter: ProductFilter = .everything + + static func localSourceControl( + identity: PackageIdentity? = nil, + deprecatedName: String? = nil, + path: AbsolutePath, + requirement: SourceControl.Requirement ) -> Self { let identity = identity ?? PackageIdentity(path: path) - return .localSourceControl(identity: identity, - nameForTargetDependencyResolutionOnly: deprecatedName, - path: path, - requirement: requirement, - productFilter: productFilter) + return .localSourceControl( + identity: identity, + nameForTargetDependencyResolutionOnly: deprecatedName, + path: path, + requirement: requirement + ) } - - static func remoteSourceControl(identity: PackageIdentity? = nil, - deprecatedName: String? = nil, - url: Foundation.URL, - requirement: SourceControl.Requirement, - productFilter: ProductFilter = .everything + + static func remoteSourceControl( + identity: PackageIdentity? = nil, + deprecatedName: String? = nil, + url: Foundation.URL, + requirement: SourceControl.Requirement ) -> Self { let identity = identity ?? PackageIdentity(url: url) - return .remoteSourceControl(identity: identity, - nameForTargetDependencyResolutionOnly: deprecatedName, - url: url, - requirement: requirement, - productFilter: productFilter) + return .remoteSourceControl( + identity: identity, + nameForTargetDependencyResolutionOnly: deprecatedName, + url: url, + requirement: requirement + ) } - - static func registry(identity: String, - requirement: Registry.Requirement, - productFilter: ProductFilter = .everything - ) -> Self { - return .registry(identity: .plain(identity), - requirement: requirement, - productFilter: productFilter) + + static func registry(identity: String, requirement: Registry.Requirement) -> Self { + return .registry( + identity: .plain(identity), + requirement: requirement + ) } } diff --git a/Sources/SPMTestSupport/misc.swift b/Sources/SPMTestSupport/misc.swift index e90976590a9..085f5a1e91d 100644 --- a/Sources/SPMTestSupport/misc.swift +++ b/Sources/SPMTestSupport/misc.swift @@ -224,7 +224,6 @@ public func loadPackageGraph( fs: FileSystem, manifests: [Manifest], binaryArtifacts: [BinaryArtifact] = [], - explicitProduct: String? = nil, shouldCreateMultipleTestProducts: Bool = false, createREPLProduct: Bool = false, useXCBuildFileRules: Bool = false, @@ -237,7 +236,7 @@ public func loadPackageGraph( let packages = Array(rootManifests.keys) let input = PackageGraphRootInput(packages: packages) - let graphRoot = PackageGraphRoot(input: input, manifests: rootManifests, explicitProduct: explicitProduct) + let graphRoot = PackageGraphRoot(input: input, manifests: rootManifests) return try PackageGraph.load( root: graphRoot, diff --git a/Sources/Workspace/FileSystemPackageContainer.swift b/Sources/Workspace/FileSystemPackageContainer.swift index c0f14409b93..d9a75f527a2 100644 --- a/Sources/Workspace/FileSystemPackageContainer.swift +++ b/Sources/Workspace/FileSystemPackageContainer.swift @@ -58,7 +58,7 @@ internal struct FileSystemPackageContainer: PackageContainer { packageKind: self.package.kind, packageLocation: path.pathString, version: nil, - revision: nil, + //revision: nil, toolsVersion: toolsVersion, identityResolver: self.identityResolver, fileSystem: self.fileSystem, @@ -69,8 +69,8 @@ internal struct FileSystemPackageContainer: PackageContainer { } } - public func getUnversionedDependencies(productFilter: ProductFilter) throws -> [PackageContainerConstraint] { - return try loadManifest().dependencyConstraints(productFilter: productFilter) + public func getUnversionedDependencies() throws -> [PackageContainerConstraint] { + return try loadManifest().dependencyConstraints() } public func getUpdatedIdentifier(at boundVersion: BoundVersion) throws -> PackageReference { @@ -118,11 +118,11 @@ internal struct FileSystemPackageContainer: PackageContainer { fatalError("This should never be called") } - public func getDependencies(at version: Version, productFilter: ProductFilter) throws -> [PackageContainerConstraint] { + public func getDependencies(at version: Version) throws -> [PackageContainerConstraint] { fatalError("This should never be called") } - public func getDependencies(at revision: String, productFilter: ProductFilter) throws -> [PackageContainerConstraint] { + public func getDependencies(at revision: String) throws -> [PackageContainerConstraint] { fatalError("This should never be called") } } diff --git a/Sources/Workspace/ResolverPrecomputationProvider.swift b/Sources/Workspace/ResolverPrecomputationProvider.swift index 5827396f28f..f120672013e 100644 --- a/Sources/Workspace/ResolverPrecomputationProvider.swift +++ b/Sources/Workspace/ResolverPrecomputationProvider.swift @@ -60,7 +60,7 @@ struct ResolverPrecomputationProvider: PackageContainerProvider { ) { queue.async { // Start by searching manifests from the Workspace's resolved dependencies. - if let manifest = self.dependencyManifests.dependencies.first(where: { _, managed, _ in managed.packageRef == package }) { + if let manifest = self.dependencyManifests.dependencies.first(where: { _, managed in managed.packageRef == package }) { let container = LocalPackageContainer( package: package, manifest: manifest.manifest, @@ -120,20 +120,20 @@ private struct LocalPackageContainer: PackageContainer { return try self.versionsDescending() } - func getDependencies(at version: Version, productFilter: ProductFilter) throws -> [PackageContainerConstraint] { + func getDependencies(at version: Version) throws -> [PackageContainerConstraint] { // Because of the implementation of `reversedVersions`, we should only get the exact same version. guard case .checkout(.version(version, revision: _)) = dependency?.state else { throw InternalError("expected version checkout state, but state was \(String(describing: dependency?.state))") } - return try manifest.dependencyConstraints(productFilter: productFilter) + return try manifest.dependencyConstraints() } - func getDependencies(at revisionString: String, productFilter: ProductFilter) throws -> [PackageContainerConstraint] { + func getDependencies(at revisionString: String) throws -> [PackageContainerConstraint] { // Return the dependencies if the checkout state matches the revision. let revision = Revision(identifier: revisionString) switch dependency?.state { case .checkout(.branch(_, revision: revision)), .checkout(.revision(revision)): - return try manifest.dependencyConstraints(productFilter: productFilter) + return try manifest.dependencyConstraints() default: throw ResolverPrecomputationError.differentRequirement( package: self.package, @@ -143,7 +143,7 @@ private struct LocalPackageContainer: PackageContainer { } } - func getUnversionedDependencies(productFilter: ProductFilter) throws -> [PackageContainerConstraint] { + func getUnversionedDependencies() throws -> [PackageContainerConstraint] { // Throw an error when the dependency is not unversioned to fail resolution. guard dependency?.isCheckout != true else { throw ResolverPrecomputationError.differentRequirement( @@ -153,7 +153,7 @@ private struct LocalPackageContainer: PackageContainer { ) } - return try manifest.dependencyConstraints(productFilter: productFilter) + return try manifest.dependencyConstraints() } // Gets the package reference from the managed dependency or computes it for root packages. diff --git a/Sources/Workspace/SourceControlPackageContainer.swift b/Sources/Workspace/SourceControlPackageContainer.swift index 6a3b824cc9b..af72aa4d2d8 100644 --- a/Sources/Workspace/SourceControlPackageContainer.swift +++ b/Sources/Workspace/SourceControlPackageContainer.swift @@ -60,7 +60,7 @@ internal final class SourceControlPackageContainer: PackageContainer, CustomStri private let currentToolsVersion: ToolsVersion /// The cached dependency information. - private var dependenciesCache = [String: [ProductFilter: (Manifest, [Constraint])]] () + private var dependenciesCache = [String: (Manifest, [Constraint])] () private var dependenciesCacheLock = Lock() private var knownVersionsCache = ThreadSafeBox<[Version: String]>() @@ -164,13 +164,13 @@ internal final class SourceControlPackageContainer: PackageContainer, CustomStri } } - public func getDependencies(at version: Version, productFilter: ProductFilter) throws -> [Constraint] { + public func getDependencies(at version: Version) throws -> [Constraint] { do { - return try self.getCachedDependencies(forIdentifier: version.description, productFilter: productFilter) { + return try self.getCachedDependencies(forIdentifier: version.description) { guard let tag = try self.knownVersions()[version] else { throw StringError("unknown tag \(version)") } - return try self.loadDependencies(tag: tag, version: version, productFilter: productFilter) + return try self.loadDependencies(tag: tag, version: version) }.1 } catch { throw GetDependenciesError( @@ -182,12 +182,12 @@ internal final class SourceControlPackageContainer: PackageContainer, CustomStri } } - public func getDependencies(at revision: String, productFilter: ProductFilter) throws -> [Constraint] { + public func getDependencies(at revision: String) throws -> [Constraint] { do { - return try self.getCachedDependencies(forIdentifier: revision, productFilter: productFilter) { + return try self.getCachedDependencies(forIdentifier: revision) { // resolve the revision identifier and return its dependencies. let revision = try repository.resolveRevision(identifier: revision) - return try self.loadDependencies(at: revision, productFilter: productFilter) + return try self.loadDependencies(at: revision) }.1 } catch { // Examine the error to see if we can come up with a more informative and actionable error message. We know that the revision is expected to be a branch name or a hash (tags are handled through a different code path). @@ -229,15 +229,14 @@ internal final class SourceControlPackageContainer: PackageContainer, CustomStri private func getCachedDependencies( forIdentifier identifier: String, - productFilter: ProductFilter, getDependencies: () throws -> (Manifest, [Constraint]) ) throws -> (Manifest, [Constraint]) { - if let result = (self.dependenciesCacheLock.withLock { self.dependenciesCache[identifier, default: [:]][productFilter] }) { + if let result = (self.dependenciesCacheLock.withLock { self.dependenciesCache[identifier] }) { return result } let result = try getDependencies() self.dependenciesCacheLock.withLock { - self.dependenciesCache[identifier, default: [:]][productFilter] = result + self.dependenciesCache[identifier] = result } return result } @@ -245,24 +244,22 @@ internal final class SourceControlPackageContainer: PackageContainer, CustomStri /// Returns dependencies of a container at the given revision. private func loadDependencies( tag: String, - version: Version? = nil, - productFilter: ProductFilter + version: Version? = nil ) throws -> (Manifest, [Constraint]) { let manifest = try self.loadManifest(tag: tag, version: version) - return (manifest, try manifest.dependencyConstraints(productFilter: productFilter)) + return (manifest, try manifest.dependencyConstraints()) } /// Returns dependencies of a container at the given revision. private func loadDependencies( at revision: Revision, - version: Version? = nil, - productFilter: ProductFilter + version: Version? = nil ) throws -> (Manifest, [Constraint]) { let manifest = try self.loadManifest(at: revision, version: version) - return (manifest, try manifest.dependencyConstraints(productFilter: productFilter)) + return (manifest, try manifest.dependencyConstraints()) } - public func getUnversionedDependencies(productFilter: ProductFilter) throws -> [Constraint] { + public func getUnversionedDependencies() throws -> [Constraint] { // We just return an empty array if requested for unversioned dependencies. return [] } @@ -328,18 +325,20 @@ internal final class SourceControlPackageContainer: PackageContainer, CustomStri // Load the manifest. // FIXME: this should not block return try temp_await { - self.manifestLoader.load(at: AbsolutePath.root, - packageIdentity: self.package.identity, - packageKind: self.package.kind, - packageLocation: self.package.locationString, - version: version, - revision: nil, - toolsVersion: toolsVersion, - identityResolver: self.identityResolver, - fileSystem: fileSystem, - diagnostics: nil, - on: .sharedConcurrent, - completion: $0) + self.manifestLoader.load( + at: AbsolutePath.root, + packageIdentity: self.package.identity, + packageKind: self.package.kind, + packageLocation: self.package.locationString, + version: version, + //revision: nil, + toolsVersion: toolsVersion, + identityResolver: self.identityResolver, + fileSystem: fileSystem, + diagnostics: nil, + on: .sharedConcurrent, + completion: $0 + ) } } diff --git a/Sources/Workspace/Workspace.swift b/Sources/Workspace/Workspace.swift index e09d5fe7c69..1409b23dacc 100644 --- a/Sources/Workspace/Workspace.swift +++ b/Sources/Workspace/Workspace.swift @@ -138,11 +138,11 @@ private struct WorkspaceDependencyResolverDelegate: DependencyResolverDelegate { } func willResolve(term: Term) { - self.workspaceDelegate.willComputeVersion(package: term.node.package.identity, location: term.node.package.locationString) + self.workspaceDelegate.willComputeVersion(package: term.package.identity, location: term.package.locationString) } func didResolve(term: Term, version: Version, duration: DispatchTimeInterval) { - self.workspaceDelegate.didComputeVersion(package: term.node.package.identity, location: term.node.package.locationString, version: version.description, duration: duration) + self.workspaceDelegate.didComputeVersion(package: term.package.identity, location: term.package.locationString, version: version.description, duration: duration) } // noop @@ -151,7 +151,7 @@ private struct WorkspaceDependencyResolverDelegate: DependencyResolverDelegate { func satisfied(term: Term, by assignment: Assignment, incompatibility: Incompatibility) {} func partiallySatisfied(term: Term, by assignment: Assignment, incompatibility: Incompatibility, difference: Term) {} func failedToResolve(incompatibility: Incompatibility) {} - func solved(result: [(package: PackageReference, binding: BoundVersion, products: ProductFilter)]) {} + func solved(result: [(package: PackageReference, binding: BoundVersion)]) {} } /// A workspace represents the state of a working project directory. @@ -615,7 +615,7 @@ extension Workspace { } // If any products are required, the rest of the package graph will supply those constraints. - let constraint = PackageContainerConstraint(package: dependency.packageRef, requirement: requirement, products: .nothing) + let constraint = PackageContainerConstraint(package: dependency.packageRef, requirement: requirement) // Run the resolution. try self.resolve( @@ -751,7 +751,7 @@ extension Workspace { let resolver = try self.createResolver(pinsMap: pinsMap) self.activeResolver = resolver - let updateResults = resolveDependencies( + let updateResults = self.resolveDependencies( resolver: resolver, constraints: updateConstraints, diagnostics: diagnostics @@ -763,7 +763,7 @@ extension Workspace { guard !diagnostics.hasErrors else { return nil } if dryRun { - return diagnostics.wrap { return try computePackageStateChanges(root: graphRoot, resolvedDependencies: updateResults, updateBranches: true) } + return diagnostics.wrap { return try self.computePackageStateChanges(root: graphRoot, resolvedDependencies: updateResults, updateBranches: true) } } // Update the checkouts based on new dependency resolution. @@ -818,7 +818,6 @@ extension Workspace { @discardableResult public func loadPackageGraph( rootInput root: PackageGraphRootInput, - explicitProduct: String? = nil, createMultipleTestProducts: Bool = false, createREPLProduct: Bool = false, forceResolvedVersions: Bool = false, @@ -827,7 +826,6 @@ extension Workspace { ) throws -> PackageGraph { try self.loadPackageGraph( rootInput: root, - explicitProduct: explicitProduct, createMultipleTestProducts: createMultipleTestProducts, createREPLProduct: createREPLProduct, forceResolvedVersions: forceResolvedVersions, @@ -839,7 +837,6 @@ extension Workspace { @discardableResult public func loadPackageGraph( rootInput root: PackageGraphRootInput, - explicitProduct: String? = nil, createMultipleTestProducts: Bool = false, createREPLProduct: Bool = false, forceResolvedVersions: Bool = false, @@ -852,13 +849,11 @@ extension Workspace { if forceResolvedVersions { manifests = try self.resolveBasedOnResolvedVersionsFile( root: root, - explicitProduct: explicitProduct, diagnostics: observabilityScope.makeDiagnosticsEngine() ) } else { manifests = try self.resolve( root: root, - explicitProduct: explicitProduct, forceResolution: false, constraints: [], diagnostics: observabilityScope.makeDiagnosticsEngine() @@ -890,12 +885,10 @@ extension Workspace { @discardableResult public func loadPackageGraph( rootPath: AbsolutePath, - explicitProduct: String? = nil, diagnostics: DiagnosticsEngine ) throws -> PackageGraph { try self.loadPackageGraph( rootPath: rootPath, - explicitProduct: explicitProduct, observabilityScope: ObservabilitySystem(diagnosticEngine: diagnostics).topScope ) } @@ -903,12 +896,10 @@ extension Workspace { @discardableResult public func loadPackageGraph( rootPath: AbsolutePath, - explicitProduct: String? = nil, observabilityScope: ObservabilityScope ) throws -> PackageGraph { try self.loadPackageGraph( rootInput: PackageGraphRootInput(packages: [rootPath]), - explicitProduct: explicitProduct, observabilityScope: observabilityScope ) } @@ -1037,7 +1028,7 @@ extension Workspace { let builder = PackageBuilder( identity: identity, manifest: manifest, - productFilter: .everything, + //productFilter: .everything, path: path, binaryArtifacts: binaryArtifacts, xcTestMinimumDeploymentTargets: MinimumDeploymentTarget.default.xcTestMinimumDeploymentTargets, @@ -1333,13 +1324,13 @@ extension Workspace { let root: PackageGraphRoot /// The dependency manifests in the transitive closure of root manifest. - let dependencies: [(manifest: Manifest, dependency: ManagedDependency, productFilter: ProductFilter)] + let dependencies: [(manifest: Manifest, dependency: ManagedDependency)] let workspace: Workspace fileprivate init( root: PackageGraphRoot, - dependencies: [(manifest: Manifest, dependency: ManagedDependency, productFilter: ProductFilter)], + dependencies: [(manifest: Manifest, dependency: ManagedDependency)], workspace: Workspace ) { self.root = root @@ -1392,24 +1383,24 @@ extension Workspace { var inputIdentities: Set = [] let inputNodes: [GraphLoadingNode] = self.root.packages.map{ identity, package in inputIdentities.insert(package.reference) - let node = GraphLoadingNode(identity: identity, manifest: package.manifest, productFilter: .everything) + let node = GraphLoadingNode(identity: identity, manifest: package.manifest) return node } + self.root.dependencies.compactMap{ dependency in let package = dependency.createPackageRef() inputIdentities.insert(package) return manifestsMap[dependency.identity].map { manifest in - GraphLoadingNode(identity: dependency.identity, manifest: manifest, productFilter: dependency.productFilter) + GraphLoadingNode(identity: dependency.identity, manifest: manifest) } } // FIXME: this is dropping legitimate packages with equal identities and should be revised as part of the identity work var requiredIdentities: Set = [] _ = transitiveClosure(inputNodes) { node in - return node.manifest.dependenciesRequired(for: node.productFilter).compactMap{ dependency in + return node.manifest.requiredDependencies().compactMap{ dependency in let package = dependency.createPackageRef() requiredIdentities.insert(package) return manifestsMap[dependency.identity].map { manifest in - GraphLoadingNode(identity: dependency.identity, manifest: manifest, productFilter: dependency.productFilter) + GraphLoadingNode(identity: dependency.identity, manifest: manifest) } } } @@ -1440,7 +1431,7 @@ extension Workspace { func dependencyConstraints() throws -> [PackageContainerConstraint] { var allConstraints = [PackageContainerConstraint]() - for (externalManifest, managedDependency, productFilter) in dependencies { + for (externalManifest, managedDependency) in dependencies { // For edited packages, add a constraint with unversioned requirement so the // resolver doesn't try to resolve it. switch managedDependency.state { @@ -1453,13 +1444,13 @@ extension Workspace { ) let constraint = PackageContainerConstraint( package: ref, - requirement: .unversioned, - products: productFilter) + requirement: .unversioned + ) allConstraints.append(constraint) case .checkout, .local: break } - allConstraints += try externalManifest.dependencyConstraints(productFilter: productFilter) + allConstraints += try externalManifest.dependencyConstraints() } return allConstraints } @@ -1469,7 +1460,7 @@ extension Workspace { public func editedPackagesConstraints() -> [PackageContainerConstraint] { var constraints = [PackageContainerConstraint]() - for (_, managedDependency, productFilter) in dependencies { + for (_, managedDependency) in dependencies { switch managedDependency.state { case .checkout, .local: continue case .edited: break @@ -1482,8 +1473,8 @@ extension Workspace { ) let constraint = PackageContainerConstraint( package: ref, - requirement: .unversioned, - products: productFilter) + requirement: .unversioned + ) constraints.append(constraint) } return constraints @@ -1551,12 +1542,6 @@ extension Workspace { diagnostics: DiagnosticsEngine, automaticallyAddManagedDependencies: Bool = false ) throws -> DependencyManifests { - // Utility Just because a raw tuple cannot be hashable. - struct Key: Hashable { - let identity: PackageIdentity - let productFilter: ProductFilter - } - // Make a copy of dependencies as we might mutate them in the for loop. let dependenciesToCheck = Array(self.state.dependencies) // Remove any managed dependency which has become a root. @@ -1590,10 +1575,10 @@ extension Workspace { // Creates a map of loaded manifests. We do this to avoid reloading the shared nodes. var loadedManifests = firstLevelManifests // Compute the transitive closure of available dependencies. - let input = topLevelManifests.map { identity, manifest in KeyedPair(manifest, key: Key(identity: identity, productFilter: .everything)) } - let allManifestsWithPossibleDuplicates = try topologicalSort(input) { pair in + let input = topLevelManifests.map { identity, manifest in KeyedPair(manifest, key: identity) } + let allManifests = try topologicalSort(input) { pair in // optimization: preload manifest we know about in parallel - let dependenciesRequired = pair.item.dependenciesRequired(for: pair.key.productFilter) + let dependenciesRequired = pair.item.requiredDependencies() // prepopulate managed dependencies if we are asked to do so // FIXME: this seems like hack, needs further investigation why this is needed if automaticallyAddManagedDependencies { @@ -1605,47 +1590,38 @@ extension Workspace { let dependenciesToLoad = dependenciesRequired.map{ $0.createPackageRef() }.filter { !loadedManifests.keys.contains($0.identity) } let dependenciesManifests = try temp_await { self.loadManagedManifests(for: dependenciesToLoad, diagnostics: diagnostics, completion: $0) } dependenciesManifests.forEach { loadedManifests[$0.key] = $0.value } - return pair.item.dependenciesRequired(for: pair.key.productFilter).compactMap{ dependency in + return pair.item.requiredDependencies().compactMap{ dependency in loadedManifests[dependency.identity].flatMap { // we also compare the location as this function may attempt to load // dependencies that have the same identity but from a different location // which is an error case we diagnose an report about in the GraphLoading part which // is prepared to handle the case where not all manifest are available $0.packageLocation == dependency.locationString ? - KeyedPair($0, key: Key(identity: dependency.identity, productFilter: dependency.productFilter)) : nil + KeyedPair($0, key: dependency.identity) : nil } } } - // merge the productFilter of the same package (by identity) - var deduplication = [PackageIdentity: Int]() - var allManifests = [(identity: PackageIdentity, manifest: Manifest, productFilter: ProductFilter)]() - for pair in allManifestsWithPossibleDuplicates { - if let index = deduplication[pair.key.identity] { - let productFilter = allManifests[index].productFilter.merge(pair.key.productFilter) - allManifests[index] = (pair.key.identity, pair.item, productFilter) - } else { - deduplication[pair.key.identity] = allManifests.count - allManifests.append((pair.key.identity, pair.item, pair.key.productFilter)) - } - } - - let dependencyManifests = allManifests.filter{ !root.manifests.values.contains($0.manifest) } + let dependencyManifests: OrderedDictionary = allManifests + .filter{ !root.manifests.values.contains($0.item) } + .reduce(into: .init(), { partial, item in + partial[item.key] = item.item + }) // TODO: this check should go away when introducing explicit overrides // check for overrides attempts with same name but different path let rootManifestsByName = Array(root.manifests.values).spm_createDictionary{ ($0.name, $0) } - dependencyManifests.forEach { identity, manifest, _ in + dependencyManifests.forEach { identity, manifest in if let override = rootManifestsByName[manifest.name], override.packageLocation != manifest.packageLocation { diagnostics.emit(error: "unable to override package '\(manifest.name)' because its identity '\(PackageIdentity(urlString: manifest.packageLocation))' doesn't match override's identity (directory name) '\(PackageIdentity(urlString: override.packageLocation))'") } } - let dependencies = try dependencyManifests.map{ identity, manifest, productFilter -> (Manifest, ManagedDependency, ProductFilter) in + let dependencies = try dependencyManifests.map{ identity, manifest -> (Manifest, ManagedDependency) in guard let dependency = self.state.dependencies[identity] else { throw InternalError("dependency not found for \(identity) at \(manifest.packageLocation)") } - return (manifest, dependency, productFilter) + return (manifest, dependency) } return DependencyManifests(root: root, dependencies: dependencies, workspace: self) @@ -1739,18 +1715,19 @@ extension Workspace { // Load the manifest. // The delegate callback is only passed any diagnostics emitted during the parsing of the manifest, but they are also forwarded up to the caller. let manifestLoadingDiagnostics = DiagnosticsEngine(handlers: [{ diagnostics.emit($0) }], defaultLocation: diagnostics.defaultLocation) - manifestLoader.load(at: packagePath, - packageIdentity: packageIdentity, - packageKind: packageKind, - packageLocation: packageLocation, - version: version, - revision: nil, - toolsVersion: toolsVersion, - identityResolver: self.identityResolver, - fileSystem: localFileSystem, - diagnostics: manifestLoadingDiagnostics, - on: .sharedConcurrent) { result in - + manifestLoader.load( + at: packagePath, + packageIdentity: packageIdentity, + packageKind: packageKind, + packageLocation: packageLocation, + version: version, + //revision: nil, + toolsVersion: toolsVersion, + identityResolver: self.identityResolver, + fileSystem: localFileSystem, + diagnostics: manifestLoadingDiagnostics, + on: .sharedConcurrent + ) { result in switch result { // Diagnostics.fatalError indicates that a more specific diagnostic has already been added. case .failure(Diagnostics.fatalError): @@ -1938,7 +1915,7 @@ extension Workspace { private func parseArtifacts(from manifests: DependencyManifests) throws -> (local: [ManagedArtifact], remote: [RemoteArtifact]) { let packageAndManifests: [(reference: PackageReference, manifest: Manifest)] = manifests.root.packages.values + // Root package and manifests. - manifests.dependencies.map({ manifest, managed, _ in (managed.packageRef, manifest) }) // Dependency package and manifests. + manifests.dependencies.map({ manifest, managed in (managed.packageRef, manifest) }) // Dependency package and manifests. var localArtifacts: [ManagedArtifact] = [] var remoteArtifacts: [RemoteArtifact] = [] @@ -2227,22 +2204,13 @@ extension Workspace { try self.resolveBasedOnResolvedVersionsFile(root: root, diagnostics: diagnostics) } - /// Resolves the dependencies according to the entries present in the Package.resolved file. - /// - /// This method bypasses the dependency resolution and resolves dependencies - /// according to the information in the resolved file. - public func resolveBasedOnResolvedVersionsFile(root: PackageGraphRootInput, diagnostics: DiagnosticsEngine) throws { - try self.resolveBasedOnResolvedVersionsFile(root: root, explicitProduct: .none, diagnostics: diagnostics) - } - /// Resolves the dependencies according to the entries present in the Package.resolved file. /// /// This method bypasses the dependency resolution and resolves dependencies /// according to the information in the resolved file. @discardableResult - fileprivate func resolveBasedOnResolvedVersionsFile( + public func resolveBasedOnResolvedVersionsFile( root: PackageGraphRootInput, - explicitProduct: String?, diagnostics: DiagnosticsEngine ) throws -> DependencyManifests { // Ensure the cache path exists. @@ -2250,7 +2218,7 @@ extension Workspace { // FIXME: this should not block let rootManifests = try temp_await { self.loadRootManifests(packages: root.packages, diagnostics: diagnostics, completion: $0) } - let graphRoot = PackageGraphRoot(input: root, manifests: rootManifests, explicitProduct: explicitProduct) + let graphRoot = PackageGraphRoot(input: root, manifests: rootManifests) // Load the pins store or abort now. guard let pinsStore = diagnostics.wrap({ try self.pinsStore.load() }), !diagnostics.hasErrors else { @@ -2322,7 +2290,6 @@ extension Workspace { @discardableResult fileprivate func resolve( root: PackageGraphRootInput, - explicitProduct: String? = nil, forceResolution: Bool, constraints: [PackageContainerConstraint], diagnostics: DiagnosticsEngine, @@ -2339,7 +2306,7 @@ extension Workspace { let rootManifestsMinimumToolsVersion = rootManifests.values.map{ $0.toolsVersion }.min() ?? ToolsVersion.currentToolsVersion // Load the current manifests. - let graphRoot = PackageGraphRoot(input: root, manifests: rootManifests, explicitProduct: explicitProduct) + let graphRoot = PackageGraphRoot(input: root, manifests: rootManifests) let currentManifests = try self.loadDependencyManifests(root: graphRoot, diagnostics: diagnostics) guard !diagnostics.hasErrors else { return currentManifests @@ -2426,7 +2393,6 @@ extension Workspace { // we have the manifest files of all the dependencies. return try self.resolve( root: root, - explicitProduct: explicitProduct, forceResolution: forceResolution, constraints: constraints, diagnostics: diagnostics, @@ -2443,7 +2409,6 @@ extension Workspace { // try again with pins reset return try self.resolve( root: root, - explicitProduct: explicitProduct, forceResolution: forceResolution, constraints: constraints, diagnostics: diagnostics, @@ -2486,7 +2451,7 @@ extension Workspace { @discardableResult fileprivate func updateDependenciesCheckouts( root: PackageGraphRoot, - updateResults: [(PackageReference, BoundVersion, ProductFilter)], + updateResults: [(PackageReference, BoundVersion)], updateBranches: Bool = false, diagnostics: DiagnosticsEngine ) -> [(PackageReference, PackageStateChange)] { @@ -2513,9 +2478,9 @@ extension Workspace { diagnostics.wrap { switch state { case .added(let state): - _ = try self.updateDependency(package: packageRef, requirement: state.requirement, productFilter: state.products) + _ = try self.updateDependency(package: packageRef, requirement: state.requirement) case .updated(let state): - _ = try self.updateDependency(package: packageRef, requirement: state.requirement, productFilter: state.products) + _ = try self.updateDependency(package: packageRef, requirement: state.requirement) case .removed, .unchanged: break } } @@ -2531,8 +2496,7 @@ extension Workspace { private func updateDependency( package: PackageReference, - requirement: PackageStateChange.Requirement, - productFilter: ProductFilter + requirement: PackageStateChange.Requirement ) throws -> AbsolutePath { let checkoutState: CheckoutState @@ -2601,7 +2565,7 @@ extension Workspace { let computedConstraints = try root.constraints() + // Include constraints from the manifests in the graph root. - root.manifests.values.flatMap{ try $0.dependencyConstraints(productFilter: .everything) } + + root.manifests.values.flatMap{ try $0.dependencyConstraints() } + dependencyManifests.dependencyConstraints() + constraints @@ -2700,12 +2664,12 @@ extension Workspace { } } } + public struct State: Equatable { public let requirement: Requirement - public let products: ProductFilter - public init(requirement: Requirement, products: ProductFilter) { + + public init(requirement: Requirement) { self.requirement = requirement - self.products = products } } @@ -2747,7 +2711,7 @@ extension Workspace { /// Computes states of the packages based on last stored state. fileprivate func computePackageStateChanges( root: PackageGraphRoot, - resolvedDependencies: [(PackageReference, BoundVersion, ProductFilter)], + resolvedDependencies: [(PackageReference, BoundVersion)], updateBranches: Bool ) throws -> [(PackageReference, PackageStateChange)] { // Load pins store and managed dependencies. @@ -2755,7 +2719,7 @@ extension Workspace { var packageStateChanges: [PackageIdentity: (PackageReference, PackageStateChange)] = [:] // Set the states from resolved dependencies results. - for (packageRef, binding, products) in resolvedDependencies { + for (packageRef, binding) in resolvedDependencies { // Get the existing managed dependency for this package ref, if any. // first find by identity only since edit location may be different by design @@ -2783,11 +2747,11 @@ extension Workspace { case .local, .edited: packageStateChanges[packageRef.identity] = (packageRef, .unchanged) case .checkout: - let newState = PackageStateChange.State(requirement: .unversioned, products: products) + let newState = PackageStateChange.State(requirement: .unversioned) packageStateChanges[packageRef.identity] = (packageRef, .updated(newState)) } } else { - let newState = PackageStateChange.State(requirement: .unversioned, products: products) + let newState = PackageStateChange.State(requirement: .unversioned) packageStateChanges[packageRef.identity] = (packageRef, .added(newState)) } @@ -2824,11 +2788,11 @@ extension Workspace { packageStateChanges[packageRef.identity] = (packageRef, .unchanged) } else { // Otherwise, we need to update this dependency to this revision. - let newState = PackageStateChange.State(requirement: .revision(revision, branch: branch), products: products) + let newState = PackageStateChange.State(requirement: .revision(revision, branch: branch)) packageStateChanges[packageRef.identity] = (packageRef, .updated(newState)) } } else { - let newState = PackageStateChange.State(requirement: .revision(revision, branch: branch), products: products) + let newState = PackageStateChange.State(requirement: .revision(revision, branch: branch)) packageStateChanges[packageRef.identity] = (packageRef, .added(newState)) } @@ -2837,11 +2801,11 @@ extension Workspace { if case .checkout(let checkoutState) = currentDependency.state, case .version(version, _) = checkoutState { packageStateChanges[packageRef.identity] = (packageRef, .unchanged) } else { - let newState = PackageStateChange.State(requirement: .version(version), products: products) + let newState = PackageStateChange.State(requirement: .version(version)) packageStateChanges[packageRef.identity] = (packageRef, .updated(newState)) } } else { - let newState = PackageStateChange.State(requirement: .version(version), products: products) + let newState = PackageStateChange.State(requirement: .version(version)) packageStateChanges[packageRef.identity] = (packageRef, .added(newState)) } } @@ -2879,7 +2843,7 @@ extension Workspace { resolver: PubgrubDependencyResolver, constraints: [PackageContainerConstraint], diagnostics: DiagnosticsEngine - ) -> [(package: PackageReference, binding: BoundVersion, products: ProductFilter)] { + ) -> [(package: PackageReference, binding: BoundVersion)] { os_signpost(.begin, log: .swiftpm, name: SignpostName.resolution) let result = resolver.solve(constraints: constraints) diff --git a/Tests/BuildTests/BuildPlanTests.swift b/Tests/BuildTests/BuildPlanTests.swift index 27272e75277..7500e557f02 100644 --- a/Tests/BuildTests/BuildPlanTests.swift +++ b/Tests/BuildTests/BuildPlanTests.swift @@ -2313,7 +2313,8 @@ final class BuildPlanTests: XCTestCase { TargetDescription(name: "PkgB", dependencies: ["swiftlib"]), ]), ], - explicitProduct: "exe", + // FIXME: tomer + //explicitProduct: "exe", observabilityScope: observability.topScope ) XCTAssertNoDiagnostics(observability.diagnostics) diff --git a/Tests/PackageGraphPerformanceTests/DependencyResolverPerfTests.swift b/Tests/PackageGraphPerformanceTests/DependencyResolverPerfTests.swift index 621b376c9e2..b497b868ed4 100644 --- a/Tests/PackageGraphPerformanceTests/DependencyResolverPerfTests.swift +++ b/Tests/PackageGraphPerformanceTests/DependencyResolverPerfTests.swift @@ -138,9 +138,8 @@ private extension MockPackageContainer.Constraint { guard case .dictionary(let dict) = json else { fatalError() } guard case .string(let identifier)? = dict["identifier"] else { fatalError() } guard let requirement = dict["requirement"] else { fatalError() } - let products: ProductFilter = try! JSON(dict).get("products") let ref = PackageReference.localSourceControl(identity: .plain(identifier), path: .root) - self.init(package: ref, versionRequirement: VersionSetSpecifier(requirement), products: products) + self.init(package: ref, versionRequirement: VersionSetSpecifier(requirement)) } } diff --git a/Tests/PackageGraphTests/PubgrubTests.swift b/Tests/PackageGraphTests/PubgrubTests.swift index 33edda5000c..62dc706a164 100644 --- a/Tests/PackageGraphTests/PubgrubTests.swift +++ b/Tests/PackageGraphTests/PubgrubTests.swift @@ -60,9 +60,8 @@ let bRef = PackageReference.localSourceControl(identity: .plain("b"), path: .roo let cRef = PackageReference.localSourceControl(identity: .plain("c"), path: .root) let rootRef = PackageReference.root(identity: PackageIdentity("root"), path: .root) -let rootNode = DependencyResolutionNode.root(package: rootRef) -let rootCause = try! Incompatibility(Term(rootNode, .exact(v1)), root: rootNode) -let _cause = try! Incompatibility("cause@0.0.0", root: rootNode) +let rootCause = try! Incompatibility(Term(rootRef, .exact(v1)), root: rootRef) +let _cause = try! Incompatibility("cause@0.0.0", root: rootRef) final class PubgrubTests: XCTestCase { func testTermInverse() { @@ -137,10 +136,10 @@ final class PubgrubTests: XCTestCase { Term("¬a@1.0.0")) // Check difference. - let anyA = Term(.empty(package: "a"), .any) + let anyA = Term("a", .any) XCTAssertNil(Term("a^1.0.0").difference(with: anyA)) - let notEmptyA = Term(not: .empty(package: "a"), .empty) + let notEmptyA = Term(not: "a", .empty) XCTAssertNil(Term("a^1.0.0").difference(with: notEmptyA)) } @@ -189,16 +188,14 @@ final class PubgrubTests: XCTestCase { } func testIncompatibilityNormalizeTermsOnInit() throws { - let i1 = try Incompatibility(Term("a^1.0.0"), Term("a^1.5.0"), Term("¬b@1.0.0"), - root: rootNode) + let i1 = try Incompatibility(Term("a^1.0.0"), Term("a^1.5.0"), Term("¬b@1.0.0"), root: rootRef) XCTAssertEqual(i1.terms.count, 2) - let a1 = i1.terms.first { $0.node.package == "a" } - let b1 = i1.terms.first { $0.node.package == "b" } + let a1 = i1.terms.first { $0.package == "a" } + let b1 = i1.terms.first { $0.package == "b" } XCTAssertEqual(a1?.requirement, v1_5Range) XCTAssertEqual(b1?.requirement, .exact(v1)) - let i2 = try Incompatibility(Term("¬a^1.0.0"), Term("a^2.0.0"), - root: rootNode) + let i2 = try Incompatibility(Term("¬a^1.0.0"), Term("a^2.0.0"), root: rootRef) XCTAssertEqual(i2.terms.count, 1) let a2 = i2.terms.first XCTAssertEqual(a2?.requirement, v2Range) @@ -210,40 +207,40 @@ final class PubgrubTests: XCTestCase { .derivation("b@2.0.0", cause: _cause, decisionLevel: 0), .derivation("a^1.0.0", cause: _cause, decisionLevel: 0) ]) - let a1 = s1._positive.first { $0.key.package.identity == PackageIdentity("a") }?.value + let a1: Term? = s1._positive.first { $0.key.identity == PackageIdentity("a") }?.value XCTAssertEqual(a1?.requirement, v1_5Range) - let b1 = s1._positive.first { $0.key.package.identity == PackageIdentity("b") }?.value + let b1: Term? = s1._positive.first { $0.key.identity == PackageIdentity("b") }?.value XCTAssertEqual(b1?.requirement, .exact(v2)) let s2 = PartialSolution(assignments: [ .derivation("¬a^1.5.0", cause: _cause, decisionLevel: 0), .derivation("a^1.0.0", cause: _cause, decisionLevel: 0) ]) - let a2 = s2._positive.first { $0.key.package.identity == PackageIdentity("a") }?.value + let a2: Term? = s2._positive.first { $0.key.identity == PackageIdentity("a") }?.value XCTAssertEqual(a2?.requirement, .range(v1..2. Both should have the same // effect though. builder.serve("a", at: v1) - builder.serve("a", at: v2, with: ["a": ["b": (.versionSet(v1Range), .specific(["b"]))]]) - builder.serve("b", at: v1, with: ["b": ["a": (.versionSet(v1Range), .specific(["a"]))]]) + builder.serve("a", at: v2, with: ["b": (.versionSet(v1Range))]) + builder.serve("b", at: v1, with: ["a": (.versionSet(v1Range))]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "a": (.versionSet(v1to3Range), .specific(["a"])), + "a": (.versionSet(v1to3Range)), ]) let result = resolver.solve(constraints: dependencies) @@ -471,12 +465,12 @@ final class PubgrubTests: XCTestCase { func testResolutionConflictResolutionWithAPartialSatisfier() { builder.serve("foo", at: v1) builder.serve("foo", at: v1_1, with: [ - "foo": ["left": (.versionSet(v1Range), .specific(["left"]))], - "foo": ["right": (.versionSet(v1Range), .specific(["right"]))] + "left": (.versionSet(v1Range)), + "right": (.versionSet(v1Range)) ]) - builder.serve("left", at: v1, with: ["left": ["shared": (.versionSet(v1Range), .specific(["shared"]))]]) - builder.serve("right", at: v1, with: ["right": ["shared": (.versionSet(v1Range), .specific(["shared"]))]]) - builder.serve("shared", at: v1, with: ["shared": ["target": (.versionSet(v1Range), .specific(["target"]))]]) + builder.serve("left", at: v1, with: ["shared": (.versionSet(v1Range))]) + builder.serve("right", at: v1, with: ["shared": (.versionSet(v1Range))]) + builder.serve("shared", at: v1, with: ["target": (.versionSet(v1Range))]) builder.serve("shared", at: v2) builder.serve("target", at: v1) builder.serve("target", at: v2) @@ -487,8 +481,8 @@ final class PubgrubTests: XCTestCase { let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.versionSet(v1Range), .specific(["foo"])), - "target": (.versionSet(v2Range), .specific(["target"])), + "foo": (.versionSet(v1Range)), + "target": (.versionSet(v2Range)), ]) let result = resolver.solve(constraints: dependencies) @@ -499,11 +493,11 @@ final class PubgrubTests: XCTestCase { } func testCycle1() { - builder.serve("foo", at: v1_1, with: ["foo": ["foo": (.versionSet(v1Range), .specific(["foo"]))]]) + builder.serve("foo", at: v1_1, with: ["foo": (.versionSet(v1Range))]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.versionSet(v1Range), .specific(["foo"])) + "foo": (.versionSet(v1Range)) ]) let result = resolver.solve(constraints: dependencies) @@ -513,14 +507,14 @@ final class PubgrubTests: XCTestCase { } func testCycle2() { - builder.serve("foo", at: v1_1, with: ["foo": ["bar": (.versionSet(v1Range), .specific(["bar"]))]]) - builder.serve("bar", at: v1, with: ["bar": ["baz": (.versionSet(v1Range), .specific(["baz"]))]]) - builder.serve("baz", at: v1, with: ["baz": ["bam": (.versionSet(v1Range), .specific(["bam"]))]]) - builder.serve("bam", at: v1, with: ["bam": ["baz": (.versionSet(v1Range), .specific(["baz"]))]]) + builder.serve("foo", at: v1_1, with: ["bar": (.versionSet(v1Range))]) + builder.serve("bar", at: v1, with: ["baz": (.versionSet(v1Range))]) + builder.serve("baz", at: v1, with: ["bam": (.versionSet(v1Range))]) + builder.serve("bam", at: v1, with: ["baz": (.versionSet(v1Range))]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.versionSet(v1Range), .specific(["foo"])), + "foo": (.versionSet(v1Range)), ]) let result = resolver.solve(constraints: dependencies) @@ -534,18 +528,18 @@ final class PubgrubTests: XCTestCase { func testLocalPackageCycle() { builder.serve("foo", at: .unversioned, with: [ - "foo": ["bar": (.unversioned, .specific(["bar"]))], + "bar": (.unversioned), ]) builder.serve("bar", at: .unversioned, with: [ - "bar": ["baz": (.unversioned, .specific(["baz"]))], + "baz": (.unversioned), ]) builder.serve("baz", at: .unversioned, with: [ - "baz": ["foo": (.unversioned, .specific(["foo"]))], + "foo": (.unversioned), ]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.unversioned, .specific(["foo"])), + "foo": (.unversioned), ]) let result = resolver.solve(constraints: dependencies) @@ -558,18 +552,18 @@ final class PubgrubTests: XCTestCase { func testBranchBasedPackageCycle() { builder.serve("foo", at: .revision("develop"), with: [ - "foo": ["bar": (.revision("develop"), .specific(["bar"]))], + "bar": (.revision("develop")), ]) builder.serve("bar", at: .revision("develop"), with: [ - "bar": ["baz": (.revision("develop"), .specific(["baz"]))], + "baz": (.revision("develop")), ]) builder.serve("baz", at: .revision("develop"), with: [ - "baz": ["foo": (.revision("develop"), .specific(["foo"]))], + "foo": (.revision("develop")), ]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.revision("develop"), .specific(["foo"])), + "foo": (.revision("develop")), ]) let result = resolver.solve(constraints: dependencies) @@ -583,7 +577,7 @@ final class PubgrubTests: XCTestCase { func testNonExistentPackage() { let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "package": (.versionSet(.exact(v1)), .specific(["package"])), + "package": (.versionSet(.exact(v1))), ]) let result = resolver.solve(constraints: dependencies) @@ -597,8 +591,8 @@ final class PubgrubTests: XCTestCase { let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.unversioned, .specific(["foo"])), - "bar": (.versionSet(v1Range), .specific(["bar"])) + "foo": (.unversioned), + "bar": (.versionSet(v1Range)) ]) let result = resolver.solve(constraints: dependencies) @@ -610,7 +604,7 @@ final class PubgrubTests: XCTestCase { func testUnversioned2() { builder.serve("foo", at: .unversioned, with: [ - "foo": ["bar": (.versionSet(.range(v1..<"1.2.0")), .specific(["bar"]))] + "bar": (.versionSet(.range(v1..<"1.2.0"))) ]) builder.serve("bar", at: v1) builder.serve("bar", at: v1_1) @@ -620,8 +614,8 @@ final class PubgrubTests: XCTestCase { let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.unversioned, .specific(["foo"])), - "bar": (.versionSet(v1Range), .specific(["bar"])) + "foo": (.unversioned), + "bar": (.versionSet(v1Range)) ]) let result = resolver.solve(constraints: dependencies) @@ -634,13 +628,13 @@ final class PubgrubTests: XCTestCase { func testUnversioned3() { builder.serve("foo", at: .unversioned) builder.serve("bar", at: v1, with: [ - "bar": ["foo": (.versionSet(.exact(v1)), .specific(["foo"]))] + "foo": (.versionSet(.exact(v1))) ]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.unversioned, .specific(["foo"])), - "bar": (.versionSet(v1Range), .specific(["bar"])) + "foo": (.unversioned), + "bar": (.versionSet(v1Range)) ]) let result = resolver.solve(constraints: dependencies) @@ -653,13 +647,13 @@ final class PubgrubTests: XCTestCase { func testUnversioned4() { builder.serve("foo", at: .unversioned) builder.serve("bar", at: .revision("master"), with: [ - "bar": ["foo": (.versionSet(v1Range), .specific(["foo"]))] + "foo": (.versionSet(v1Range)) ]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.unversioned, .specific(["foo"])), - "bar": (.revision("master"), .specific(["bar"])) + "foo": (.unversioned), + "bar": (.revision("master")) ]) let result = resolver.solve(constraints: dependencies) @@ -673,13 +667,13 @@ final class PubgrubTests: XCTestCase { builder.serve("foo", at: .unversioned) builder.serve("foo", at: .revision("master")) builder.serve("bar", at: .revision("master"), with: [ - "bar": ["foo": (.revision("master"), .specific(["foo"]))] + "foo": (.revision("master")) ]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.unversioned, .specific(["foo"])), - "bar": (.revision("master"), .specific(["bar"])) + "foo": (.unversioned), + "bar": (.revision("master")) ]) let result = resolver.solve(constraints: dependencies) @@ -691,15 +685,15 @@ final class PubgrubTests: XCTestCase { func testUnversioned7() { builder.serve("local", at: .unversioned, with: [ - "local": ["remote": (.unversioned, .specific(["remote"]))] + "remote": (.unversioned) ]) builder.serve("remote", at: .unversioned) builder.serve("remote", at: v1) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "local": (.unversioned, .specific(["local"])), - "remote": (.versionSet(v1Range), .specific(["remote"])), + "local": (.unversioned), + "remote": (.versionSet(v1Range)), ]) let result = resolver.solve(constraints: dependencies) @@ -711,20 +705,18 @@ final class PubgrubTests: XCTestCase { func testUnversioned8() { builder.serve("entry", at: .unversioned, with: [ - "entry": [ - "remote": (.versionSet(v1Range), .specific(["remote"])), - "local": (.unversioned, .specific(["local"])), - ] + "remote": (.versionSet(v1Range)), + "local": (.unversioned), ]) builder.serve("local", at: .unversioned, with: [ - "local": ["remote": (.unversioned, .specific(["remote"]))] + "remote": (.unversioned) ]) builder.serve("remote", at: .unversioned) builder.serve("remote", at: v1) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "entry": (.unversioned, .specific(["entry"])), + "entry": (.unversioned), ]) let result = resolver.solve(constraints: dependencies) @@ -737,20 +729,18 @@ final class PubgrubTests: XCTestCase { func testUnversioned9() { builder.serve("entry", at: .unversioned, with: [ - "entry": [ - "local": (.unversioned, .specific(["local"])), - "remote": (.versionSet(v1Range), .specific(["remote"])), - ] + "local": (.unversioned), + "remote": (.versionSet(v1Range)), ]) builder.serve("local", at: .unversioned, with: [ - "local": ["remote": (.unversioned, .specific(["remote"]))] + "remote": (.unversioned) ]) builder.serve("remote", at: .unversioned) builder.serve("remote", at: v1) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "entry": (.unversioned, .specific(["entry"])), + "entry": (.unversioned), ]) let result = resolver.solve(constraints: dependencies) @@ -762,13 +752,13 @@ final class PubgrubTests: XCTestCase { } func testResolutionWithSimpleBranchBasedDependency() { - builder.serve("foo", at: .revision("master"), with: ["foo": ["bar": (.versionSet(v1Range), .specific(["bar"]))]]) + builder.serve("foo", at: .revision("master"), with: ["bar": (.versionSet(v1Range))]) builder.serve("bar", at: v1) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.revision("master"), .specific(["foo"])), - "bar": (.versionSet(v1Range), .specific(["bar"])) + "foo": (.revision("master")), + "bar": (.versionSet(v1Range)) ]) let result = resolver.solve(constraints: dependencies) @@ -779,12 +769,12 @@ final class PubgrubTests: XCTestCase { } func testResolutionWithSimpleBranchBasedDependency2() { - builder.serve("foo", at: .revision("master"), with: ["foo": ["bar": (.versionSet(v1Range), .specific(["bar"]))]]) + builder.serve("foo", at: .revision("master"), with: ["bar": (.versionSet(v1Range))]) builder.serve("bar", at: v1) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.revision("master"), .specific(["foo"])), + "foo": (.revision("master")), ]) let result = resolver.solve(constraints: dependencies) @@ -796,12 +786,12 @@ final class PubgrubTests: XCTestCase { func testResolutionWithOverridingBranchBasedDependency() { builder.serve("foo", at: .revision("master")) - builder.serve("bar", at: v1, with: ["bar": ["foo": (.versionSet(v1Range), .specific(["foo"]))]]) + builder.serve("bar", at: v1, with: ["foo": (.versionSet(v1Range))]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.revision("master"), .specific(["foo"])), - "bar": (.versionSet(.exact(v1)), .specific(["bar"])), + "foo": (.revision("master")), + "bar": (.versionSet(.exact(v1))), ]) let result = resolver.solve(constraints: dependencies) @@ -814,12 +804,12 @@ final class PubgrubTests: XCTestCase { func testResolutionWithOverridingBranchBasedDependency2() { builder.serve("foo", at: .revision("master")) - builder.serve("bar", at: v1, with: ["bar": ["foo": (.versionSet(v1Range), .specific(["foo"]))]]) + builder.serve("bar", at: v1, with: ["foo": (.versionSet(v1Range))]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "bar": (.versionSet(.exact(v1)), .specific(["bar"])), - "foo": (.revision("master"), .specific(["foo"])), + "bar": (.versionSet(.exact(v1))), + "foo": (.revision("master")), ]) let result = resolver.solve(constraints: dependencies) @@ -830,17 +820,17 @@ final class PubgrubTests: XCTestCase { } func testResolutionWithOverridingBranchBasedDependency3() { - builder.serve("foo", at: .revision("master"), with: ["foo": ["bar": (.revision("master"), .specific(["bar"]))]]) + builder.serve("foo", at: .revision("master"), with: ["bar": (.revision("master"))]) builder.serve("bar", at: .revision("master")) builder.serve("bar", at: v1) - builder.serve("baz", at: .revision("master"), with: ["baz": ["bar": (.versionSet(v1Range), .specific(["bar"]))]]) + builder.serve("baz", at: .revision("master"), with: ["bar": (.versionSet(v1Range))]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.revision("master"), .specific(["foo"])), - "baz": (.revision("master"), .specific(["baz"])), + "foo": (.revision("master")), + "baz": (.revision("master")), ]) let result = resolver.solve(constraints: dependencies) @@ -856,7 +846,7 @@ final class PubgrubTests: XCTestCase { let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.revision("master"), .specific(["foo"])) + "foo": (.revision("master")) ]) let result = resolver.solve(constraints: dependencies) @@ -864,14 +854,14 @@ final class PubgrubTests: XCTestCase { } func testResolutionWithRevisionConflict() { - builder.serve("foo", at: .revision("master"), with: ["foo": ["bar": (.revision("master"), .specific(["bar"]))]]) + builder.serve("foo", at: .revision("master"), with: ["bar": (.revision("master"))]) builder.serve("bar", at: .version(v1)) builder.serve("bar", at: .revision("master")) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "bar": (.versionSet(v1Range), .specific(["bar"])), - "foo": (.revision("master"), .specific(["foo"])), + "bar": (.versionSet(v1Range)), + "foo": (.revision("master")), ]) let result = resolver.solve(constraints: dependencies) @@ -885,17 +875,17 @@ final class PubgrubTests: XCTestCase { builder.serve("swift-nio", at: v1) builder.serve("swift-nio", at: .revision("master")) builder.serve("swift-nio-ssl", at: .revision("master"), with: [ - "swift-nio-ssl": ["swift-nio": (.versionSet(v2Range), .specific(["swift-nio"]))], + "swift-nio": (.versionSet(v2Range)), ]) builder.serve("foo", at: "1.0.0", with: [ - "foo": ["swift-nio": (.versionSet(v1Range), .specific(["swift-nio"]))], + "swift-nio": (.versionSet(v1Range)), ]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.versionSet(v1Range), .specific(["foo"])), - "swift-nio": (.revision("master"), .specific(["swift-nio"])), - "swift-nio-ssl": (.revision("master"), .specific(["swift-nio-ssl"])), + "foo": (.versionSet(v1Range)), + "swift-nio": (.revision("master")), + "swift-nio-ssl": (.revision("master")), ]) let result = resolver.solve(constraints: dependencies) @@ -910,29 +900,25 @@ final class PubgrubTests: XCTestCase { builder.serve("swift-nio", at: v1) builder.serve("swift-nio", at: .revision("master")) builder.serve("swift-nio-ssl", at: .revision("master"), with: [ - "swift-nio-ssl": ["swift-nio": (.versionSet(v2Range), .specific(["swift-nio"]))], + "swift-nio": (.versionSet(v2Range)), ]) builder.serve("nio-postgres", at: .revision("master"), with: [ - "nio-postgres": [ - "swift-nio": (.revision("master"), .specific(["swift-nio"])), - "swift-nio-ssl": (.revision("master"), .specific(["swift-nio-ssl"])), - ] + "swift-nio": (.revision("master")), + "swift-nio-ssl": (.revision("master")), ]) builder.serve("http-client", at: v1, with: [ - "http-client": [ - "swift-nio": (.versionSet(v1Range), .specific(["swift-nio"])), - "boring-ssl": (.versionSet(v1Range), .specific(["boring-ssl"])), - ] + "swift-nio": (.versionSet(v1Range)), + "boring-ssl": (.versionSet(v1Range)), ]) builder.serve("boring-ssl", at: v1, with: [ - "boring-ssl": ["swift-nio": (.versionSet(v1Range), .specific(["swift-nio"]))], + "swift-nio": (.versionSet(v1Range)), ]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "nio-postgres": (.revision("master"), .specific(["nio-postgres"])), - "http-client": (.versionSet(v1Range), .specific(["https-client"])), - "boring-ssl": (.versionSet(v1Range), .specific(["boring-ssl"])), + "nio-postgres": (.revision("master")), + "http-client": (.versionSet(v1Range)), + "boring-ssl": (.versionSet(v1Range)), ]) let result = resolver.solve(constraints: dependencies) @@ -947,12 +933,12 @@ final class PubgrubTests: XCTestCase { func testNonVersionDependencyInVersionDependency2() { builder.serve("foo", at: v1_1, with: [ - "foo": ["bar": (.revision("master"), .specific(["bar"]))] + "bar": (.revision("master")) ]) builder.serve("foo", at: v1) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.versionSet(v1Range), .specific(["foo"])), + "foo": (.versionSet(v1Range)), ]) let result = resolver.solve(constraints: dependencies) @@ -962,26 +948,26 @@ final class PubgrubTests: XCTestCase { } func testTrivialPinStore() throws { - builder.serve("a", at: v1, with: ["a": ["b": (.versionSet(v1Range), .specific(["b"]))]]) + builder.serve("a", at: v1, with: ["b": (.versionSet(v1Range))]) builder.serve("a", at: v1_1) builder.serve("b", at: v1) builder.serve("b", at: v1_1) builder.serve("b", at: v2) let dependencies = builder.create(dependencies: [ - "a": (.versionSet(v1Range), .specific(["a"])), + "a": (.versionSet(v1Range)), ]) let pinsStore = builder.create(pinsStore: [ - "a": (.version(v1), .specific(["a"])), - "b": (.version(v1), .specific(["b"])), + "a": (.version(v1)), + "b": (.version(v1)), ]) let resolver = builder.create(pinsMap: pinsStore.pinsMap) - let result = try resolver.solve(root: rootNode, constraints: dependencies) + let result = try resolver.solve(root: rootRef, constraints: dependencies) // Since a was pinned, we shouldn't have computed bounds for its incomaptibilities. - let aIncompat = result.state.positiveIncompatibilities(for: .product("a", package: builder.reference(for: "a")))![0] + let aIncompat = result.state.positiveIncompatibilities(for: builder.reference(for: "a"))![0] XCTAssertEqual(aIncompat.terms[0].requirement, .exact("1.0.0")) AssertResult(Result.success(result.bindings), [ @@ -993,22 +979,22 @@ final class PubgrubTests: XCTestCase { func testPartialPins() { // This checks that we can drop pins that are not valid anymore but still keep the ones // which fit the constraints. - builder.serve("a", at: v1, with: ["a": ["b": (.versionSet(v1Range), .specific(["b"]))]]) + builder.serve("a", at: v1, with: ["b": (.versionSet(v1Range))]) builder.serve("a", at: v1_1) builder.serve("b", at: v1) builder.serve("b", at: v1_1) - builder.serve("c", at: v1, with: ["c": ["b": (.versionSet(.range(v1_1..= 3.2.1 contains incompatible tools version (\(ToolsVersion.v4)) and root depends on 'a' 3.2.0..<4.0.0. 'a' < 3.2.1 cannot be used because 'a' < 3.2.1 depends on 'b' 1.0.0..<2.0.0. - 'b' >= 1.0.0 cannot be used because 'b' 1.0.0 contains incompatible tools version (\(ToolsVersion.v3)) and no versions of 'b' match the requirement 1.0.1..<2.0.0. + 'b' >= 1.0.0 cannot be used because no versions of 'b' match the requirement 1.0.1..<2.0.0 and 'b' 1.0.0 contains incompatible tools version (\(ToolsVersion.v3)). """) } func testConflict4() { builder.serve("foo", at: v1, with: [ - "foo": ["shared": (.versionSet(.range("2.0.0"..<"3.0.0")), .specific(["shared"]))], + "shared": (.versionSet(.range("2.0.0"..<"3.0.0"))), ]) builder.serve("bar", at: v1, with: [ - "bar": ["shared": (.versionSet(.range("2.9.0"..<"4.0.0")), .specific(["shared"]))], + "shared": (.versionSet(.range("2.9.0"..<"4.0.0"))), ]) builder.serve("shared", at: "2.5.0") builder.serve("shared", at: "3.5.0") let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "bar": (.versionSet(.exact(v1)), .specific(["bar"])), - "foo": (.versionSet(.exact(v1)), .specific(["foo"])), + "bar": (.versionSet(.exact(v1))), + "foo": (.versionSet(.exact(v1))), ]) let result = resolver.solve(constraints: dependencies) @@ -1629,22 +1608,22 @@ final class PubGrubDiagnosticsTests: XCTestCase { func testConflict5() { builder.serve("a", at: v1, with: [ - "a": ["b": (.versionSet(.exact("1.0.0")), .specific(["b"]))], + "b": (.versionSet(.exact("1.0.0"))), ]) builder.serve("a", at: "2.0.0", with: [ - "a": ["b": (.versionSet(.exact("2.0.0")), .specific(["b"]))], + "b": (.versionSet(.exact("2.0.0"))), ]) builder.serve("b", at: "1.0.0", with: [ - "b": ["a": (.versionSet(.exact("2.0.0")), .specific(["a"]))], + "a": (.versionSet(.exact("2.0.0"))), ]) builder.serve("b", at: "2.0.0", with: [ - "b": ["a": (.versionSet(.exact("1.0.0")), .specific(["a"]))], + "a": (.versionSet(.exact("1.0.0"))), ]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "b": (.versionSet(.range("0.0.0"..<"5.0.0")), .specific(["b"])), - "a": (.versionSet(.range("0.0.0"..<"5.0.0")), .specific(["a"])), + "b": (.versionSet(.range("0.0.0"..<"5.0.0"))), + "a": (.versionSet(.range("0.0.0"..<"5.0.0"))), ]) let result = resolver.solve(constraints: dependencies) @@ -1658,35 +1637,24 @@ final class PubGrubDiagnosticsTests: XCTestCase { """) } + /* func testProductsCannotResolveToDifferentVersions() { builder.serve("root", at: .unversioned, with: [ - "root": [ - "intermediate_a": (.versionSet(v1Range), .specific(["Intermediate A"])), - "intermediate_b": (.versionSet(v1Range), .specific(["Intermediate B"])) - ] + "intermediate_a": (.versionSet(v1Range)), + "intermediate_b": (.versionSet(v1Range)) ]) builder.serve("intermediate_a", at: v1, with: [ - "Intermediate A": [ - "transitive": (.versionSet(.exact(v1)), .specific(["Product A"])) - ] + "transitive": (.versionSet(.exact(v1))) ]) builder.serve("intermediate_b", at: v1, with: [ - "Intermediate B": [ - "transitive": (.versionSet(.exact(v1_1)), .specific(["Product B"])) - ] - ]) - builder.serve("transitive", at: v1, with: [ - "Product A": [:], - "Product B": [:] - ]) - builder.serve("transitive", at: v1_1, with: [ - "Product A": [:], - "Product B": [:] + "transitive": (.versionSet(.exact(v1_1))) ]) + builder.serve("transitive", at: v1, with: [:]) + builder.serve("transitive", at: v1_1, with: [:]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "root": (.unversioned, .everything) + "root": (.unversioned) ]) let result = resolver.solve(constraints: dependencies) @@ -1698,22 +1666,22 @@ final class PubGrubDiagnosticsTests: XCTestCase { 'intermediate_b' practically depends on 'transitive' 1.1.0 because 'intermediate_b' depends on 'transitive' 1.1.0 and 'transitive' >= 1.1.0 depends on 'transitive' 1.1.0. """ ) - } + }*/ } final class PubGrubBacktrackTests: XCTestCase { func testBacktrack1() { builder.serve("a", at: v1) builder.serve("a", at: "2.0.0", with: [ - "a": ["b": (.versionSet(.exact("1.0.0")), .specific(["b"]))], + "b": (.versionSet(.exact("1.0.0"))), ]) builder.serve("b", at: "1.0.0", with: [ - "b": ["a": (.versionSet(.exact("1.0.0")), .specific(["a"]))], + "a": (.versionSet(.exact("1.0.0"))), ]) let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "a": (.versionSet(.range("1.0.0"..<"3.0.0")), .specific(["a"])), + "a": (.versionSet(.range("1.0.0"..<"3.0.0"))), ]) let result = resolver.solve(constraints: dependencies) @@ -1726,14 +1694,14 @@ final class PubGrubBacktrackTests: XCTestCase { func testBacktrack2() { builder.serve("a", at: v1) builder.serve("a", at: "2.0.0", with: [ - "a": ["c": (.versionSet(.range("1.0.0"..<"2.0.0")), .specific(["c"]))], + "c": (.versionSet(.range("1.0.0"..<"2.0.0"))), ]) builder.serve("b", at: "1.0.0", with: [ - "b": ["c": (.versionSet(.range("2.0.0"..<"3.0.0")), .specific(["c"]))], + "c": (.versionSet(.range("2.0.0"..<"3.0.0"))), ]) builder.serve("b", at: "2.0.0", with: [ - "b": ["c": (.versionSet(.range("3.0.0"..<"4.0.0")), .specific(["c"]))], + "c": (.versionSet(.range("3.0.0"..<"4.0.0"))), ]) builder.serve("c", at: "1.0.0") @@ -1742,8 +1710,8 @@ final class PubGrubBacktrackTests: XCTestCase { let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "a": (.versionSet(.range("1.0.0"..<"3.0.0")), .specific(["a"])), - "b": (.versionSet(.range("1.0.0"..<"3.0.0")), .specific(["b"])), + "a": (.versionSet(.range("1.0.0"..<"3.0.0"))), + "b": (.versionSet(.range("1.0.0"..<"3.0.0"))), ]) let result = resolver.solve(constraints: dependencies) @@ -1757,24 +1725,22 @@ final class PubGrubBacktrackTests: XCTestCase { func testBacktrack3() { builder.serve("a", at: "1.0.0", with: [ - "a": ["x": (.versionSet(.range("1.0.0"..<"5.0.0")), .specific(["x"]))], + "x": (.versionSet(.range("1.0.0"..<"5.0.0"))), ]) builder.serve("b", at: "1.0.0", with: [ - "b": ["x": (.versionSet(.range("0.0.0"..<"2.0.0")), .specific(["x"]))], + "x": (.versionSet(.range("0.0.0"..<"2.0.0"))), ]) builder.serve("c", at: "1.0.0") builder.serve("c", at: "2.0.0", with: [ - "c": [ - "a": (.versionSet(.range("0.0.0"..<"5.0.0")), .specific(["a"])), - "b": (.versionSet(.range("0.0.0"..<"5.0.0")), .specific(["b"])), - ] + "a": (.versionSet(.range("0.0.0"..<"5.0.0"))), + "b": (.versionSet(.range("0.0.0"..<"5.0.0"))), ]) builder.serve("x", at: "0.0.0") builder.serve("x", at: "2.0.0") builder.serve("x", at: "1.0.0", with: [ - "x": ["y": (.versionSet(.exact(v1)), .specific(["y"]))], + "y": (.versionSet(.exact(v1))), ]) builder.serve("y", at: "1.0.0") @@ -1782,8 +1748,8 @@ final class PubGrubBacktrackTests: XCTestCase { let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "c": (.versionSet(.range("1.0.0"..<"3.0.0")), .specific(["c"])), - "y": (.versionSet(.range("2.0.0"..<"3.0.0")), .specific(["y"])), + "c": (.versionSet(.range("1.0.0"..<"3.0.0"))), + "y": (.versionSet(.range("2.0.0"..<"3.0.0"))), ]) let result = resolver.solve(constraints: dependencies) @@ -1796,24 +1762,22 @@ final class PubGrubBacktrackTests: XCTestCase { func testBacktrack4() { builder.serve("a", at: "1.0.0", with: [ - "a": ["x": (.versionSet(.range("1.0.0"..<"5.0.0")), .specific(["x"]))], + "x": (.versionSet(.range("1.0.0"..<"5.0.0"))), ]) builder.serve("b", at: "1.0.0", with: [ - "b": ["x": (.versionSet(.range("0.0.0"..<"2.0.0")), .specific(["x"]))], + "x": (.versionSet(.range("0.0.0"..<"2.0.0"))), ]) builder.serve("c", at: "1.0.0") builder.serve("c", at: "2.0.0", with: [ - "c": [ - "a": (.versionSet(.range("0.0.0"..<"5.0.0")), .specific(["a"])), - "b": (.versionSet(.range("0.0.0"..<"5.0.0")), .specific(["b"])), - ] + "a": (.versionSet(.range("0.0.0"..<"5.0.0"))), + "b": (.versionSet(.range("0.0.0"..<"5.0.0"))), ]) builder.serve("x", at: "0.0.0") builder.serve("x", at: "2.0.0") builder.serve("x", at: "1.0.0", with: [ - "x": ["y": (.versionSet(.exact(v1)), .specific(["y"]))], + "y": (.versionSet(.exact(v1))), ]) builder.serve("y", at: "1.0.0") @@ -1821,8 +1785,8 @@ final class PubGrubBacktrackTests: XCTestCase { let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "c": (.versionSet(.range("1.0.0"..<"3.0.0")), .specific(["c"])), - "y": (.versionSet(.range("2.0.0"..<"3.0.0")), .specific(["y"])), + "c": (.versionSet(.range("1.0.0"..<"3.0.0"))), + "y": (.versionSet(.range("2.0.0"..<"3.0.0"))), ]) let result = resolver.solve(constraints: dependencies) @@ -1835,30 +1799,30 @@ final class PubGrubBacktrackTests: XCTestCase { func testBacktrack5() { builder.serve("foo", at: "1.0.0", with: [ - "foo": ["bar": (.versionSet(.exact("1.0.0")), .specific(["bar"]))], + "bar": (.versionSet(.exact("1.0.0"))), ]) builder.serve("foo", at: "2.0.0", with: [ - "foo": ["bar": (.versionSet(.exact("2.0.0")), .specific(["bar"]))], + "bar": (.versionSet(.exact("2.0.0"))), ]) builder.serve("foo", at: "3.0.0", with: [ - "foo": ["bar": (.versionSet(.exact("3.0.0")), .specific(["bar"]))], + "bar": (.versionSet(.exact("3.0.0"))), ]) builder.serve("bar", at: "1.0.0", with: [ - "bar": ["baz": (.versionSet(.range("0.0.0"..<"3.0.0")), .specific(["baz"]))], + "baz": (.versionSet(.range("0.0.0"..<"3.0.0"))), ]) builder.serve("bar", at: "2.0.0", with: [ - "bar": ["baz": (.versionSet(.exact("3.0.0")), .specific(["baz"]))], + "baz": (.versionSet(.exact("3.0.0"))), ]) builder.serve("bar", at: "3.0.0", with: [ - "bar": ["baz": (.versionSet(.exact("3.0.0")), .specific(["baz"]))], + "baz": (.versionSet(.exact("3.0.0"))), ]) builder.serve("baz", at: "1.0.0") let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "foo": (.versionSet(.range("1.0.0"..<"4.0.0")), .specific(["foo"])), + "foo": (.versionSet(.range("1.0.0"..<"4.0.0"))), ]) let result = resolver.solve(constraints: dependencies) @@ -1874,19 +1838,19 @@ final class PubGrubBacktrackTests: XCTestCase { builder.serve("a", at: "1.0.0") builder.serve("a", at: "2.0.0") builder.serve("b", at: "1.0.0", with: [ - "b": ["a": (.versionSet(.exact("1.0.0")), .specific(["a"]))], + "a": (.versionSet(.exact("1.0.0"))), ]) builder.serve("c", at: "1.0.0", with: [ - "c": ["b": (.versionSet(.range("0.0.0"..<"3.0.0")), .specific(["b"]))], + "b": (.versionSet(.range("0.0.0"..<"3.0.0"))), ]) builder.serve("d", at: "1.0.0") builder.serve("d", at: "2.0.0") let resolver = builder.create() let dependencies = builder.create(dependencies: [ - "a": (.versionSet(.range("1.0.0"..<"4.0.0")), .specific(["a"])), - "c": (.versionSet(.range("1.0.0"..<"4.0.0")), .specific(["c"])), - "d": (.versionSet(.range("1.0.0"..<"4.0.0")), .specific(["d"])), + "a": (.versionSet(.range("1.0.0"..<"4.0.0"))), + "c": (.versionSet(.range("1.0.0"..<"4.0.0"))), + "d": (.versionSet(.range("1.0.0"..<"4.0.0"))), ]) let result = resolver.solve(constraints: dependencies) @@ -1975,12 +1939,12 @@ private func AssertError( // FIXME: this is not thread-safe public class MockContainer: PackageContainer { - public typealias Dependency = (container: PackageReference, requirement: PackageRequirement, productFilter: ProductFilter) + public typealias Dependency = (container: PackageReference, requirement: PackageRequirement) public var package: PackageReference var manifestName: PackageReference? - var dependencies: [String: [String: [Dependency]]] + var dependencies: [String: [Dependency]] public var unversionedDeps: [PackageContainerConstraint] = [] @@ -2027,30 +1991,26 @@ public class MockContainer: PackageContainer { return version } - public func getDependencies(at version: Version, productFilter: ProductFilter) throws -> [PackageContainerConstraint] { - return try getDependencies(at: version.description, productFilter: productFilter) + public func getDependencies(at version: Version) throws -> [PackageContainerConstraint] { + return try getDependencies(at: version.description) } - public func getDependencies(at revision: String, productFilter: ProductFilter) throws -> [PackageContainerConstraint] { + public func getDependencies(at revision: String) throws -> [PackageContainerConstraint] { guard let revisionDependencies = dependencies[revision] else { throw _MockLoadingError.unknownRevision } - var filteredDependencies: [MockContainer.Dependency] = [] - for (product, productDependencies) in revisionDependencies where productFilter.contains(product) { - filteredDependencies.append(contentsOf: productDependencies) + return revisionDependencies.map{ value in + let (package, requirement) = value + return PackageContainerConstraint(package: package, requirement: requirement) } - return filteredDependencies.map({ value in - let (package, requirement, filter) = value - return PackageContainerConstraint(package: package, requirement: requirement, products: filter) - }) } - public func getUnversionedDependencies(productFilter: ProductFilter) throws -> [PackageContainerConstraint] { + public func getUnversionedDependencies() throws -> [PackageContainerConstraint] { // FIXME: This is messy, remove unversionedDeps property. if !unversionedDeps.isEmpty { return unversionedDeps } - return try getDependencies(at: PackageRequirement.unversioned.description, productFilter: productFilter) + return try getDependencies(at: PackageRequirement.unversioned.description) } public func getUpdatedIdentifier(at boundVersion: BoundVersion) throws -> PackageReference { @@ -2073,29 +2033,21 @@ public class MockContainer: PackageContainer { public convenience init( package: PackageReference, - unversionedDependencies: [(package: PackageReference, requirement: PackageRequirement, productFilter: ProductFilter)] + unversionedDependencies: [(package: PackageReference, requirement: PackageRequirement)] ) { self.init(package: package) self.unversionedDeps = unversionedDependencies - .map { PackageContainerConstraint(package: $0.package, requirement: $0.requirement, products: $0.productFilter) } + .map { PackageContainerConstraint(package: $0.package, requirement: $0.requirement) } } public convenience init( package: PackageReference, - dependenciesByVersion: [Version: [String: [( - package: PackageReference, - requirement: VersionSetSpecifier, - productFilter: ProductFilter - )]]]) { - var dependencies: [String: [String: [Dependency]]] = [:] - for (version, productDependencies) in dependenciesByVersion { - if dependencies[version.description] == nil { - dependencies[version.description] = [:] - } - for (product, deps) in productDependencies { - dependencies[version.description, default: [:]][product] = deps.map({ - ($0.package, .versionSet($0.requirement), $0.productFilter) - }) + dependenciesByVersion: [Version: [(package: PackageReference, requirement: VersionSetSpecifier)]] + ) { + var dependencies: [String: [Dependency]] = [:] + for (version, deps) in dependenciesByVersion { + dependencies[version.description] = deps.map{ + ($0.package, .versionSet($0.requirement)) } } self.init(package: package, dependencies: dependencies) @@ -2103,7 +2055,7 @@ public class MockContainer: PackageContainer { public init( package: PackageReference, - dependencies: [String: [String: [Dependency]]] = [:] + dependencies: [String: [Dependency]] = [:] ) { self.package = package self.dependencies = dependencies @@ -2155,11 +2107,9 @@ class DependencyGraphBuilder { return newReference } - func create( - dependencies: OrderedDictionary - ) -> [PackageContainerConstraint] { + func create(dependencies: OrderedDictionary) -> [PackageContainerConstraint] { return dependencies.map { - PackageContainerConstraint(package: reference(for: $0), requirement: $1.0, products: $1.1) + PackageContainerConstraint(package: reference(for: $0), requirement: $1) } } @@ -2167,7 +2117,7 @@ class DependencyGraphBuilder { _ package: String, at version: Version, toolsVersion: ToolsVersion? = nil, - with dependencies: KeyValuePairs> = [:] + with dependencies: KeyValuePairs = [:] ) { serve(package, at: .version(version), toolsVersion: toolsVersion, with: dependencies) } @@ -2176,7 +2126,7 @@ class DependencyGraphBuilder { _ package: String, at version: BoundVersion, toolsVersion: ToolsVersion? = nil, - with dependencies: KeyValuePairs> = [:] + with dependencies: KeyValuePairs = [:] ) { let packageReference = reference(for: package) let container = self.containers[package] ?? MockContainer(package: packageReference) @@ -2187,25 +2137,20 @@ class DependencyGraphBuilder { container.appendVersion(version) - if container.dependencies[version.description] == nil { - container.dependencies[version.description] = [:] - } - for (product, filteredDependencies) in dependencies { - let packageDependencies: [MockContainer.Dependency] = filteredDependencies.map { - (container: reference(for: $0), requirement: $1.0, products: $1.1) - } - container.dependencies[version.description, default: [:]][product, default: []] += packageDependencies + let packageDependencies = dependencies.map { + (container: reference(for: $0), requirement: $1) } + container.dependencies[version.description] = packageDependencies self.containers[package] = container } /// Creates a pins store with the given pins. - func create(pinsStore pins: [String: (CheckoutState, ProductFilter)]) -> PinsStore { + func create(pinsStore pins: [String: CheckoutState]) -> PinsStore { let fs = InMemoryFileSystem() let store = try! PinsStore(pinsFile: AbsolutePath("/tmp/Package.resolved"), workingDirectory: .root, fileSystem: fs, mirrors: .init()) - for (package, pin) in pins { - store.pin(packageRef: reference(for: package), state: pin.0) + for (package, pinState) in pins { + store.pin(packageRef: reference(for: package), state: pinState) } try! store.saveState(toolsVersion: ToolsVersion.currentToolsVersion) @@ -2265,9 +2210,11 @@ extension Term: ExpressibleByStringLiteral { guard case let .versionSet(vs) = requirement! else { fatalError() } - self.init(node: .product(packageReference.name, package: packageReference), - requirement: vs, - isPositive: isPositive) + self.init( + package: packageReference, + requirement: vs, + isPositive: isPositive + ) } } diff --git a/Tests/PackageLoadingTests/PD_4_2_LoadingTests.swift b/Tests/PackageLoadingTests/PD_4_2_LoadingTests.swift index 78b763c78a2..bf87d26b2e5 100644 --- a/Tests/PackageLoadingTests/PD_4_2_LoadingTests.swift +++ b/Tests/PackageLoadingTests/PD_4_2_LoadingTests.swift @@ -815,7 +815,7 @@ class PackageDescription4_2LoadingTests: PackageDescriptionLoadingTests { packageKind: .fileSystem(manifestPath.parentDirectory), packageLocation: manifestPath.pathString, version: nil, - revision: nil, + //revision: nil, toolsVersion: .v4_2, identityResolver: identityResolver, fileSystem: localFileSystem, @@ -834,7 +834,7 @@ class PackageDescription4_2LoadingTests: PackageDescriptionLoadingTests { packageKind: .fileSystem(manifestPath.parentDirectory), packageLocation: manifestPath.pathString, version: nil, - revision: nil, + //revision: nil, toolsVersion: .v4_2, identityResolver: identityResolver, fileSystem: localFileSystem, @@ -899,7 +899,7 @@ class PackageDescription4_2LoadingTests: PackageDescriptionLoadingTests { packageKind: .fileSystem(manifestPath.parentDirectory), packageLocation: manifestPath.pathString, version: nil, - revision: nil, + //revision: nil, toolsVersion: .v4_2, identityResolver: identityResolver, fileSystem: localFileSystem, diff --git a/Tests/PackageLoadingTests/PackageBuilderTests.swift b/Tests/PackageLoadingTests/PackageBuilderTests.swift index d326b084331..aaa446ce037 100644 --- a/Tests/PackageLoadingTests/PackageBuilderTests.swift +++ b/Tests/PackageLoadingTests/PackageBuilderTests.swift @@ -2391,7 +2391,6 @@ final class PackageBuilderTester { let builder = PackageBuilder( identity: PackageIdentity(urlString: manifest.packageLocation), manifest: manifest, - productFilter: .everything, path: path, binaryArtifacts: binaryArtifacts, xcTestMinimumDeploymentTargets: Self.xcTestMinimumDeploymentTargets, diff --git a/Tests/PackageModelTests/ManifestTests.swift b/Tests/PackageModelTests/ManifestTests.swift index 2022370f101..55465a32a9d 100644 --- a/Tests/PackageModelTests/ManifestTests.swift +++ b/Tests/PackageModelTests/ManifestTests.swift @@ -36,7 +36,7 @@ class ManifestTests: XCTestCase { targets: targets ) - XCTAssertEqual(manifest.targetsRequired(for: .everything).map({ $0.name }).sorted(), [ + XCTAssertEqual(manifest.requiredTargets().map({ $0.name }).sorted(), [ "Bar", "Baz", "Foo", @@ -91,7 +91,7 @@ class ManifestTests: XCTestCase { targets: targets ) - XCTAssertEqual(manifest.dependenciesRequired(for: .everything).map({ $0.identity.description }).sorted(), [ + XCTAssertEqual(manifest.requiredDependencies().map({ $0.identity.description }).sorted(), [ "bar1", "bar2", "bar3", @@ -108,7 +108,8 @@ class ManifestTests: XCTestCase { targets: targets ) - XCTAssertEqual(manifest.dependenciesRequired(for: .specific(["Foo"])).map({ $0.identity.description }).sorted(), [ + // FIXME: tomer + XCTAssertEqual(manifest.requiredDependencies(/*for: .specific(["Foo"])*/).map({ $0.identity.description }).sorted(), [ "bar1", // Foo → Foo1 → Bar1 "bar2", // Foo → Foo1 → Foo2 → Bar2 "bar3", // Foo → Foo1 → Bar1 → could be from any package due to pre‐5.2 tools version. @@ -125,7 +126,7 @@ class ManifestTests: XCTestCase { targets: targets ) - XCTAssertEqual(manifest.dependenciesRequired(for: .everything).map({ $0.identity.description }).sorted(), [ + XCTAssertEqual(manifest.requiredDependencies().map({ $0.identity.description }).sorted(), [ "bar1", "bar2", "bar3", diff --git a/Tests/WorkspaceTests/ManifestSourceGenerationTests.swift b/Tests/WorkspaceTests/ManifestSourceGenerationTests.swift index 34030135cd1..a414509a24c 100644 --- a/Tests/WorkspaceTests/ManifestSourceGenerationTests.swift +++ b/Tests/WorkspaceTests/ManifestSourceGenerationTests.swift @@ -38,7 +38,7 @@ class ManifestSourceGenerationTests: XCTestCase { packageKind: .root(packageDir), packageLocation: packageDir.pathString, version: nil, - revision: nil, + //revision: nil, toolsVersion: toolsVersion, identityResolver: identityResolver, fileSystem: fs, @@ -63,7 +63,7 @@ class ManifestSourceGenerationTests: XCTestCase { packageKind: .root(packageDir), packageLocation: packageDir.pathString, version: nil, - revision: nil, + //revision: nil, toolsVersion: toolsVersion, identityResolver: identityResolver, fileSystem: fs, diff --git a/Tests/WorkspaceTests/PackageContainerProviderTests.swift b/Tests/WorkspaceTests/PackageContainerProviderTests.swift index 21a767e415b..a7e7309c279 100644 --- a/Tests/WorkspaceTests/PackageContainerProviderTests.swift +++ b/Tests/WorkspaceTests/PackageContainerProviderTests.swift @@ -289,7 +289,7 @@ class PackageContainerProviderTests: XCTestCase { let container = try provider.getContainer(for: ref, skipUpdate: false) as! SourceControlPackageContainer let revision = try container.getRevision(forTag: "1.0.0") do { - _ = try container.getDependencies(at: revision.identifier, productFilter: .nothing) + _ = try container.getDependencies(at: revision.identifier) } catch let error as SourceControlPackageContainer.GetDependenciesError { let error = error.underlyingError as! UnsupportedToolsVersion XCTAssertMatch(error.description, .and(.prefix("package '\(PackageIdentity(path: repoPath))' @"), .suffix("is using Swift tools version 3.1.0 which is no longer supported; consider using '// swift-tools-version:4.0' to specify the current tools version"))) @@ -389,6 +389,8 @@ class PackageContainerProviderTests: XCTestCase { XCTAssertEqual(v, ["2.0.1", "1.3.0", "1.2.0", "1.1.0", "1.0.4", "1.0.2", "1.0.1", "1.0.0"]) } + + /* // FIXME: tomer func testDependencyConstraints() throws { #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION #else @@ -522,7 +524,7 @@ class PackageContainerProviderTests: XCTestCase { ] ) } - } + }*/ func testMissingBranchDiagnostics() throws { try testWithTemporaryDirectory { tmpDir in @@ -568,7 +570,7 @@ class PackageContainerProviderTests: XCTestCase { let container = try containerProvider.getContainer(for: packageRef, skipUpdate: false) as! SourceControlPackageContainer // Simulate accessing a fictitious dependency on the `master` branch, and check that we get back the expected error. - do { _ = try container.getDependencies(at: "master", productFilter: .everything) } + do { _ = try container.getDependencies(at: "master") } catch let error as SourceControlPackageContainer.GetDependenciesError { // We expect to get an error message that mentions main. XCTAssertMatch(error.description, .and(.prefix("could not find a branch named ‘master’"), .suffix("(did you mean ‘main’?)"))) @@ -576,7 +578,7 @@ class PackageContainerProviderTests: XCTestCase { } // Simulate accessing a fictitious dependency on some random commit that doesn't exist, and check that we get back the expected error. - do { _ = try container.getDependencies(at: "535f4cb5b4a0872fa691473e82d7b27b9894df00", productFilter: .everything) } + do { _ = try container.getDependencies(at: "535f4cb5b4a0872fa691473e82d7b27b9894df00") } catch let error as SourceControlPackageContainer.GetDependenciesError { // We expect to get an error message about the specific commit. XCTAssertMatch(error.description, .prefix("could not find the commit 535f4cb5b4a0872fa691473e82d7b27b9894df00")) @@ -585,6 +587,7 @@ class PackageContainerProviderTests: XCTestCase { } } + /* // FIXME: tomer func testRepositoryPackageContainerCache() throws { // From rdar://problem/65284674 // RepositoryPackageContainer used to erroneously cache dependencies based only on version, @@ -651,7 +654,7 @@ class PackageContainerProviderTests: XCTestCase { XCTAssertNotEqual(forNothing, forProduct) #endif } - } + }*/ } extension PackageContainerProvider { diff --git a/Tests/WorkspaceTests/WorkspaceTests.swift b/Tests/WorkspaceTests/WorkspaceTests.swift index 2e8b415505a..ed369bb4282 100644 --- a/Tests/WorkspaceTests/WorkspaceTests.swift +++ b/Tests/WorkspaceTests/WorkspaceTests.swift @@ -69,8 +69,9 @@ final class WorkspaceTests: XCTestCase { ) let deps: [MockDependency] = [ - .sourceControl(path: "./Quix", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Quix"])), - .sourceControl(path: "./Baz", requirement: .exact("1.0.0"), products: .specific(["Baz"])), + // FIXME: tomer + .sourceControl(path: "./Quix", requirement: .upToNextMajor(from: "1.0.0")/*, products: .specific(["Quix"])*/), + .sourceControl(path: "./Baz", requirement: .exact("1.0.0")/*, products: .specific(["Baz"])*/), ] try workspace.checkPackageGraph(roots: ["Foo"], deps: deps) { graph, diagnostics in PackageGraphTester(graph) { result in @@ -607,16 +608,17 @@ final class WorkspaceTests: XCTestCase { ] ) + // FIXME: tomer let dependencies: [PackageDependency] = [ .localSourceControl( path: workspace.packagesDir.appending(component: "Bar"), - requirement: .upToNextMajor(from: "1.0.0"), - productFilter: .specific(["Bar"]) + requirement: .upToNextMajor(from: "1.0.0")//, + //productFilter: .specific(["Bar"]) ), .localSourceControl( path: workspace.packagesDir.appending(component: "Foo"), - requirement: .upToNextMajor(from: "1.0.0"), - productFilter: .specific(["Foo"]) + requirement: .upToNextMajor(from: "1.0.0")//, + //productFilter: .specific(["Foo"]) ), ] @@ -685,7 +687,8 @@ final class WorkspaceTests: XCTestCase { // Resolve when A = 1.0.0. do { let deps: [MockDependency] = [ - .sourceControl(path: "./A", requirement: .exact("1.0.0"), products: .specific(["A"])), + // FIXME: tomer + .sourceControl(path: "./A", requirement: .exact("1.0.0")/*, products: .specific(["A"])*/), ] try workspace.checkPackageGraph(deps: deps) { graph, diagnostics in PackageGraphTester(graph) { result in @@ -708,7 +711,8 @@ final class WorkspaceTests: XCTestCase { // Resolve when A = 1.0.1. do { let deps: [MockDependency] = [ - .sourceControl(path: "./A", requirement: .exact("1.0.1"), products: .specific(["A"])), + // FIXME: tomer + .sourceControl(path: "./A", requirement: .exact("1.0.1")/*, products: .specific(["A"])*/), ] try workspace.checkPackageGraph(deps: deps) { graph, diagnostics in PackageGraphTester(graph) { result in @@ -779,8 +783,9 @@ final class WorkspaceTests: XCTestCase { ) let deps: [MockDependency] = [ - .sourceControl(path: "./A", requirement: .exact("1.0.0"), products: .specific(["A"])), - .sourceControl(path: "./B", requirement: .exact("1.0.0"), products: .specific(["B"])), + // FIXME: tomer + .sourceControl(path: "./A", requirement: .exact("1.0.0")/*, products: .specific(["A"])*/), + .sourceControl(path: "./B", requirement: .exact("1.0.0")/*, products: .specific(["B"])*/), ] try workspace.checkPackageGraph(deps: deps) { _, diagnostics in testDiagnostics(diagnostics) { result in @@ -1384,7 +1389,8 @@ final class WorkspaceTests: XCTestCase { // Do an intial run, capping at Foo at 1.0.0. let deps: [MockDependency] = [ - .sourceControl(path: "./Foo", requirement: .exact("1.0.0"), products: .specific(["Foo"])), + // FIXME: tomer + .sourceControl(path: "./Foo", requirement: .exact("1.0.0")/*, products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTester(graph) { result in @@ -1469,7 +1475,8 @@ final class WorkspaceTests: XCTestCase { // Do an intial run, capping at Foo at 1.0.0. let deps: [MockDependency] = [ - .sourceControl(path: "./Foo", requirement: .exact("1.0.0"), products: .specific(["Foo"])), + // FIXME: tomer + .sourceControl(path: "./Foo", requirement: .exact("1.0.0")/*, products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in @@ -1486,10 +1493,11 @@ final class WorkspaceTests: XCTestCase { // Run update. try workspace.checkUpdateDryRun(roots: ["Root"]) { changes, diagnostics in XCTAssertNoDiagnostics(diagnostics) + // FIXME: tomer #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION - let stateChange = Workspace.PackageStateChange.updated(.init(requirement: .version(Version("1.5.0")), products: .specific(["Foo"]))) + let stateChange = Workspace.PackageStateChange.updated(.init(requirement: .version(Version("1.5.0"))/*, products: .specific(["Foo"])*/)) #else - let stateChange = Workspace.PackageStateChange.updated(.init(requirement: .version(Version("1.5.0")), products: .everything)) + let stateChange = Workspace.PackageStateChange.updated(.init(requirement: .version(Version("1.5.0"))/*, products: .everything*/)) #endif let path = AbsolutePath("/tmp/ws/pkgs/Foo") @@ -1576,9 +1584,10 @@ final class WorkspaceTests: XCTestCase { ] ) - // Do an intial run, capping at Foo at 1.0.0. + // Do an initial run, capping at Foo at 1.0.0. let deps: [MockDependency] = [ - .sourceControl(path: "./Foo", requirement: .exact("1.0.0"), products: .specific(["Foo"])), + // FIXME: tomer + .sourceControl(path: "./Foo", requirement: .exact("1.0.0")/*, products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -1883,7 +1892,8 @@ final class WorkspaceTests: XCTestCase { // We request Bar via revision. let deps: [MockDependency] = [ - .sourceControl(path: "./Bar", requirement: .revision(barRevision), products: .specific(["Bar"])), + // FIXME: tomer + .sourceControl(path: "./Bar", requirement: .revision(barRevision)/*, products: .specific(["Bar"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTester(graph) { result in @@ -1960,7 +1970,7 @@ final class WorkspaceTests: XCTestCase { // Check failure. workspace.checkResolve(pkg: "Foo", roots: ["Root"], version: "1.3.0") { diagnostics in testDiagnostics(diagnostics) { result in - result.check(diagnostic: .contains("'Foo' 1.3.0"), severity: .error) + result.check(diagnostic: .contains("'foo' 1.3.0"), severity: .error) } } workspace.checkManagedDependencies { result in @@ -2335,7 +2345,8 @@ final class WorkspaceTests: XCTestCase { ) let deps: [MockDependency] = [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Foo"])), + // FIXME: tomer + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")/*, products: .specific(["Foo"])*/), ] let ws = try workspace.getOrCreateWorkspace() @@ -2428,7 +2439,8 @@ final class WorkspaceTests: XCTestCase { ) let deps: [MockDependency] = [ - .sourceControl(path: "./Foo", requirement: .exact("1.0.0"), products: .specific(["Foo"])), + // FIXME: tomer + .sourceControl(path: "./Foo", requirement: .exact("1.0.0")/*, products: .specific(["Foo"])*/), ] // Load the graph. try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in @@ -2573,7 +2585,8 @@ final class WorkspaceTests: XCTestCase { } let deps: [MockDependency] = [ - .fileSystem(path: "./Foo", products: .specific(["Foo"])), + // FIXME: tomer + .fileSystem(path: "./Foo"/*), products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTester(graph) { result in @@ -2647,8 +2660,9 @@ final class WorkspaceTests: XCTestCase { identity: settings.identity, nameForTargetDependencyResolutionOnly: settings.nameForTargetDependencyResolutionOnly, location: settings.location, - requirement: .exact("1.5.0"), - productFilter: settings.productFilter + requirement: .exact("1.5.0")//, + // FIXME: tomer + //productFilter: settings.productFilter ) workspace.manifestLoader.manifests[fooKey] = Manifest( @@ -2745,11 +2759,12 @@ final class WorkspaceTests: XCTestCase { // Try resolving a bad graph. let deps: [MockDependency] = [ - .sourceControl(path: "./Bar", requirement: .exact("1.1.0"), products: .specific(["Bar"])), + // FIXME: tomer + .sourceControl(path: "./Bar", requirement: .exact("1.1.0")/*, products: .specific(["Bar"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in testDiagnostics(diagnostics) { result in - result.check(diagnostic: .contains("'Bar' 1.1.0"), severity: .error) + result.check(diagnostic: .contains("'bar' 1.1.0"), severity: .error) } } } @@ -2988,7 +3003,8 @@ final class WorkspaceTests: XCTestCase { // Override with local package and run update. let deps: [MockDependency] = [ - .fileSystem(path: "./Bar", products: .specific(["Bar"])), + // FIXME: tomer + .fileSystem(path: "./Bar"/*, products: .specific(["Bar"])*/), ] try workspace.checkUpdate(roots: ["Foo"], deps: deps) { diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3076,7 +3092,8 @@ final class WorkspaceTests: XCTestCase { // without running swift package update. var deps: [MockDependency] = [ - .sourceControl(path: "./Foo", requirement: .branch("develop"), products: .specific(["Foo"])), + // FIXME: tomer + .sourceControl(path: "./Foo", requirement: .branch("develop")/*, products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTester(graph) { result in @@ -3090,7 +3107,8 @@ final class WorkspaceTests: XCTestCase { } deps = [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Foo"])), + // FIXME: tomer + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")/*, products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3100,7 +3118,8 @@ final class WorkspaceTests: XCTestCase { } deps = [ - .sourceControl(path: "./Foo", requirement: .branch("develop"), products: .specific(["Foo"])), + // FIXME: tomer + .sourceControl(path: "./Foo", requirement: .branch("develop")/*, products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3145,7 +3164,8 @@ final class WorkspaceTests: XCTestCase { // without running swift package update. var deps: [MockDependency] = [ - .fileSystem(path: "./Foo", products: .specific(["Foo"])), + // FIXME: tomer + .fileSystem(path: "./Foo"/*, products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTester(graph) { result in @@ -3159,7 +3179,8 @@ final class WorkspaceTests: XCTestCase { } deps = [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Foo"])), + // FIXME: tomer + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")/*, products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3169,7 +3190,8 @@ final class WorkspaceTests: XCTestCase { } deps = [ - .fileSystem(path: "./Foo", products: .specific(["Foo"])), + // FIXME: tomer + .fileSystem(path: "./Foo"/*, products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3225,7 +3247,8 @@ final class WorkspaceTests: XCTestCase { // different locations works correctly. var deps: [MockDependency] = [ - .fileSystem(path: "./Foo", products: .specific(["Foo"])), + // FIXME: tomer + .fileSystem(path: "./Foo"/*, products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTester(graph) { result in @@ -3239,7 +3262,8 @@ final class WorkspaceTests: XCTestCase { } deps = [ - .fileSystem(path: "./Foo2", products: .specific(["Foo"])), + // FIXME: tomer + .fileSystem(path: "./Foo2"/*, products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3295,7 +3319,8 @@ final class WorkspaceTests: XCTestCase { // different locations works correctly. var deps: [MockDependency] = [ - .fileSystem(path: "./Foo", products: .specific(["Foo"])), + // FIXME: tomer + .fileSystem(path: "./Foo"/*, products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTester(graph) { result in @@ -3313,7 +3338,8 @@ final class WorkspaceTests: XCTestCase { } deps = [ - .fileSystem(path: "./Nested/Foo", products: .specific(["Foo"])), + // FIXME: tomer + .fileSystem(path: "./Nested/Foo"/*, products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3359,7 +3385,8 @@ final class WorkspaceTests: XCTestCase { ) let deps: [MockDependency] = [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Foo"])), + // FIXME: tomer + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")/*, products: .specific(["Foo"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -3398,7 +3425,8 @@ final class WorkspaceTests: XCTestCase { ], products: [], dependencies: [ - .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Foo"])), + // FIXME: tomer + .sourceControl(path: "./Foo", requirement: .upToNextMajor(from: "1.0.0")/*, products: .specific(["Foo"])*/), ], toolsVersion: pair.0 ), @@ -3518,7 +3546,8 @@ final class WorkspaceTests: XCTestCase { ) let deps: [MockDependency] = [ - .sourceControl(path: "./Bam", requirement: .upToNextMajor(from: "1.0.0"), products: .specific(["Bar"])), + // FIXME: tomer + .sourceControl(path: "./Bam", requirement: .upToNextMajor(from: "1.0.0")/*, products: .specific(["Bar"])*/), ] try workspace.checkPackageGraph(roots: ["Foo"], deps: deps) { graph, diagnostics in @@ -3622,7 +3651,8 @@ final class WorkspaceTests: XCTestCase { // dependencies. var deps: [MockDependency] = [ - .sourceControl(path: "./Bar", requirement: .exact("1.0.0"), products: .specific(["Bar"])), + // FIXME: tomer + .sourceControl(path: "./Bar", requirement: .exact("1.0.0")/*, products: .specific(["Bar"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTester(graph) { result in @@ -3646,7 +3676,8 @@ final class WorkspaceTests: XCTestCase { } deps = [ - .sourceControl(path: "./Bar", requirement: .exact("1.1.0"), products: .specific(["Bar"])), + // FIXME: tomer + .sourceControl(path: "./Bar", requirement: .exact("1.1.0")/*, products: .specific(["Bar"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { graph, diagnostics in PackageGraphTester(graph) { result in @@ -3712,7 +3743,8 @@ final class WorkspaceTests: XCTestCase { // Load the initial graph. let deps: [MockDependency] = [ - .sourceControl(path: "./Bar", requirement: .revision("develop"), products: .specific(["Bar"])), + // FIXME: tomer + .sourceControl(path: "./Bar", requirement: .revision("develop")/*, products: .specific(["Bar"])*/), ] try workspace.checkPackageGraph(roots: ["Root"], deps: deps) { _, diagnostics in XCTAssertNoDiagnostics(diagnostics) @@ -4008,7 +4040,8 @@ final class WorkspaceTests: XCTestCase { ) let deps: [MockDependency] = [ - .sourceControl(path: "./bazzz", requirement: .exact("1.0.0"), products: .specific(["Baz"])), + // FIXME: tomer + .sourceControl(path: "./bazzz", requirement: .exact("1.0.0")/*, products: .specific(["Baz"])*/), ] try workspace.checkPackageGraphFailure(roots: ["Overridden/bazzz-master"], deps: deps) { diagnostics in @@ -8276,7 +8309,7 @@ final class WorkspaceTests: XCTestCase { packageKind: PackageReference.Kind, packageLocation: String, version: Version?, - revision: String?, + //revision: String?, toolsVersion: ToolsVersion, identityResolver: IdentityResolver, fileSystem: FileSystem,