SwiftPackageIndex / SwiftPackageIndex-Server

The Swift Package Index is the place to find Swift packages!
https://swiftpackageindex.com
Apache License 2.0
557 stars 46 forks source link

The dependency count on the package page should exclude any test dependencies #1300

Open daveverwer opened 3 years ago

daveverwer commented 3 years ago

For example, SpanGrid should show 1 rather than 2 as it currently shows:

Screenshot 2021-10-18 at 12 50 56@2x
let package = Package(
    name: "SpanGrid",
    platforms: [
        .iOS(.v14),
        .tvOS(.v14),
        .macOS(.v11),
        .watchOS(.v7),
    ],
    products: [
        .library(name: "SpanGrid", targets: ["SpanGrid"]),
    ],
    dependencies: [
        .package(name: "SnapshotTesting",
                 url: "https://github.com/pointfreeco/swift-snapshot-testing.git", from: "1.9.0"),

        .package(name: "swift-log",
                 url: "https://github.com/apple/swift-log.git", from: "1.4.2"),
    ],
    targets: [
        .target(
            name: "SpanGrid",
            dependencies: [
                .product(name: "Logging", package: "swift-log"),
            ],
            path: "Sources"
        ),
        .testTarget(
            name: "SpanGridTests",
            dependencies: [
                .product(name: "SnapshotTesting", package: "SnapshotTesting"),
                .target(name: "SpanGrid"),
            ],
            path: "Tests",
            exclude: [ "__Snapshots__" ]
        ),
    ]
)

We can show test dependencies in the detailed view, but I think the main number on the main page should be package dependencies only, if we can manage it.

finestructure commented 2 years ago

I can't find where we've discussed this nor any notes of mine, so I'll try to recap briefly why this is difficult.

We're currently leveraging the fact that our builders resolve dependencies as part of their build. This is an expensive operation, which means this is a really cheap way to get all dependencies for a package. We get them from the resulting file Package.resolved.

However, this file does not include any details on what target triggered the inclusion, i.e. it is not possible to determine if a dependency has been pulled in from a test target.

We do have a test target list and their dependencies available via the package manifest, so in theory we could determine if a) a dependency is a leaf of a test target and b) it is an exclusive leaf (i.e. not also pulled in via a non-test target).

However, we'd end up rewriting SPM's dependency resolution algorithm in SPI, and that's not a trivial undertaking. *)

I've spend around 2 days staring at SPM's dependency resolution in order to figure out if we could fork it and pass through a "test target origin" flag or something similar that would populate an testExclusive field in Package.resolved but I'm none the wiser how to do that.

I'm sure it's possible and I'm convinced this is the best place to actually do it, whether in a fork that we'd maintain or, ideally, by upstreaming it into SPM. Our best route is probably to ask if there's appetite to add this by someone on the SPM team or give us a large dose of help getting started doing it ourselves.

*) One thing making this a littler simpler is that we wouldn't need to deal with version resolution. I.e. we could just assume the listed dependencies would resolve - they're sort of intended dependencies.