URLs as Swift Package Identifiers

Thank you for weighing in on this thread, @John_McCall. I'm very happy to respond to any concerns you and the rest of the Core Team have.

Our proposal absolutely allows for packages to relocate. If your package is hosted at github.com/mona/LinkedList, it could be renamed (github.com/mona/SwiftLinkedList), moved to a new org (github.com/OctoCorp/LinkedList), or an entirely new domain (mona.dev/LinkedList). All a maintainer / registry needs to do is establish a relationship between these packages, using HTTP redirects and/or rel="canonical" links. These are the same semantics we have on the web, and they've worked well.

So long as these redirections form a directed, acyclic graph, Swift Package Manager can unambiguously resolve old and new locations for packages.

What our proposal does require is that packages remain available at existing URLs once published. This ensures that dependent packages don't break when one of their dependencies move.

For example, if a dependency graph contains both github.com/mona/LinkedList (:octopus:) and mona.dev/LinkedList (:woman_technologist:), which are the same package. This can resolve one of two ways:

  • mona.dev/LinkedList (:woman_technologist:) redirects to github.com/mona/LinkedList (:octopus:); Swift Package Manager treats github.com/mona/LinkedList (:octopus:) as the package identity.
  • github.com/mona/LinkedList (:octopus:) lists mona.dev/LinkedList (:woman_technologist:) as the canonical location of the package; Swift Package Manager treats mona.dev/LinkedList (:woman_technologist:) as the package identity

If a package's dependency graph contains only mona.dev/LinkedList (:woman_technologist:), then everything works as expected; this is the base case.

If a package's dependency graph contains only github.com/mona/LinkedList (:octopus:), that continues to work, even if mona.dev/LinkedList (:woman_technologist:) is set as the canonical location. This may or may not be communicated to the user ("`Info: github.com/mona/LinkedList has been moved to mona.dev/LinkedList; please update your package manifest accordingly"). SPM could even add tooling to automate updating dependency declarations.


Any other identity scheme is going to have to deal with these same problems. Adopting reverse-DNS, for example, only shifts the problem of relocation to renaming. The reason we chose to use URLs in our proposal is that we can leverage the familiar, robust infrastructure of URLs and HTTP semantics rather than reinvent the wheel with an additional layer of abstraction.

Technically, our proposal identifies packages using URIs not URLs. I've used these terms interchangeably because the distinction hasn't been important.

Essentially, package URIs are URLs without the scheme (https://); our proposal normalizes to remove the .git as well. What you end up with is package identities like github.com/mona/LinkedList or mona.dev/LinkedList. To properly namespace packages in another scheme, you'd encode about as much information (com.github.mona.LinkedList or dev.mona.LinkedList). All things being equal, I'd rather go with URLs, which are more useful and familiar, and don't require us to invent a new layer of abstraction.

The same would be true of other schemes like reverse-DNS. You can't currently import com.github.mona.LinkedList.

In the original post on this thread, we describe how our proposal dovetails nicely with this proposal by Proposed syntax by Rahul Malik, Ankit Aggarwal, and David Hart:

Using anything other than URLs / URIs would require Swift scripts to additionally specify a registry to resolve the package identity.

@package(name: "com.github.mona.LinkedList", from: "1.1.0", registry: "https://swift.pkg.github.com")
import LinkedList
4 Likes