i think we are once again running aground the overloaded terminology surrounding “package”, because you are talking about the package identifier string passed to the swift compiler, and the swift compiler knows nothing about versioning.
but the SPM does know about versioning, and not only does it know about versioning, it aggressively pushes a particular 1-to-1 semver-based packaging and distribution paradigm that simply does not scale. it has nominal support for things like local filesystem dependencies, but these are relegated to the realm of “local testing and iteration” and utterly banned from participating in wider semver world.
using SPM’s definition of a “package”, our mutual friends really do develop one humongous giga-package, since all of that code shares a history. it doesn’t make sense to simultaneously depend on one subset of that code base at cl/XXX and another subset of that code base at cl/YYY - it’s all the same repo! but it does make sense for an SPM project to depend on two upstream “packages” without expecting any chronological relationship between those two “packages”. indeed, that is the entire function of semantic versioning.
you are entirely correct. i would go so far as to say the number of such monorepos is likely zero. this is one of the reasons i say SPM does not scale. SPM currently believes in one package with one manifest in one repository, and this cannot continue.
which brings me to this quote i recall from the previous review thread:
i think that when an SPM “project” reaches a certain size, it also becomes unavoidable that we need to stop thinking of ourselves as writing a “package”, we must start thinking of ourselves as writing many “packages” that share a repository and version series, and using the swift package manager to “manage” N > 1 packages. and it is unfortunate that SPM today does not truly support this level of sophistication.
and i think the reason SPM cannot support this kind of organization, is because of an awful decision we made several years back, to identify a package by the URL of its repository, and to use that repository to model a dependency on a package.
dependencies:
[
.package(url: "https://github.com/SDGGiesbrecht/swift-markdown",
.upToNextMinor(from: "0.50700.0")),
]
targets:
[
.target(name: "MarkdownParser", dependencies:
[
.product(name: "Markdown", package: "swift-markdown"),
]),
]
and in this mental model, there is no room to decouple the repository from the package. from a target dependency perspective, the "swift-markdown" identifier defined by the package manifest’s name field represents the “package”. but from a dependency resolution perspective, the "https://github.com/SDGGiesbrecht/swift-markdown" repository URL represents the “package”.
which one is the real “package”? up until now, we did not care, because a package and a git repository were the same thing. but now we must care.