# URLs as Swift Package Identifiers

**URL:** <https://forums.swift.org/t/urls-as-swift-package-identifiers/43404>\
**Category:** Discussion\
**Tags:** packagemanager\
**Created:** [December 28, 2020, 10:27pm UTC](https://forums.swift.org/t/urls-as-swift-package-identifiers/43404 "2020-12-28T22:27:18Z")\
**Posts on this page:** 1\
**Showing post:** 98

<div class="post-metadata">

**Author:** ![mattt](https://avatars.discourse-cdn.com/v4/letter/m/46a35a/32.png) [@mattt](https://forums.swift.org/u/mattt)\
**Post date:** [January 21, 2021, 12:35pm UTC](https://forums.swift.org/t/urls-as-swift-package-identifiers/43404/98 "2021-01-21T12:35:18Z")

</div>

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.

> [@John\_McCall](#):
>
> However, if we unconditionally trust that URL to tell us where to find the package, projects can never change anything about how they host packages without changing the identity of those packages. That seems like a problem, a large enough one that I would state its converse as a basic requirement:
> 
> > Projects must be able to change the basic details of how and where they host packages without changing the fundamental identity of those packages

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](https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections) and/or [`rel="canonical"` links](https://developers.google.com/search/docs/advanced/crawling/consolidate-duplicate-urls). 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` (🐙) and `mona.dev/LinkedList` (👩‍💻), which are the same package. This can resolve one of two ways:

- `mona.dev/LinkedList` (👩‍💻) redirects to `github.com/mona/LinkedList` (🐙); Swift Package Manager treats `github.com/mona/LinkedList` (🐙) as the package identity.
- `github.com/mona/LinkedList` (🐙) lists `mona.dev/LinkedList` (👩‍💻) as the canonical location of the package; Swift Package Manager treats `mona.dev/LinkedList` (👩‍💻) as the package identity

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

If a package's dependency graph contains only `github.com/mona/LinkedList` (🐙), that continues to work, even if `mona.dev/LinkedList` (👩‍💻) is set as the canonical location. This may or may not be communicated to the user ("`Info: [github.com/mona/LinkedList](http://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.

> [@John\_McCall](#):
>
> URLs also have a number of unique disadvantages, like that they contain quite a lot of information and structure that's primarily useful for web clients and servers rather than adding any disambiguation for the project. We would probably feel strongly pressured to hard-code shortenings for presumptively-common URL schemas like `https://github.com/(\w+)/(\w+).git` into Swift's symbol mangling to avoid drastic build time / binary size impact. That seems inappropriate; Swift as a project should not be directly favoring one hosting strategy over another.

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.

> [@John\_McCall](#):
>
> URLs are also not naturally embeddable in source code, e.g. as qualifiers on `import` directives. It seems appropriate for us to consider the potential for such things rather than ruling them out.

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](https://forums.swift.org/t/swiftpm-support-for-swift-scripts/33126):

> [@mattt](#):
>
> ### Importing external modules without a package manifest
> 
> Developers enjoy using Swift as a scripting language, but wish there were an easier way to import external dependencies in a standalone file, without the overhead of the package manifest and directory structure. Various solutions have been explored through community projects like swift-sh, Beak, and Marathon, and discussions on the Swift forums.
> 
> For example, running the command `swift path/to/file.swift` with the following file would automatically resolve and download the `LinkedList` dependency before building and running the script executable.
> 
> ```swift
> // Proposed syntax by Rahul Malik, Ankit Aggarwal, and David Hart
> // See: https://forums.swift.org/t/swiftpm-support-for-swift-scripts/33126
> @package(url: "https://github.com/mona/LinkedList", from: "1.1.0")
> import LinkedList
> 
> // Variation with hypothetical module aliasing
> @package(url: "https://github.com/OctoCorp/linkedlist", from: "0.1.0")
> import LinkedList as OctoCorpLinkedList
> 
> print("Hello, world!")
> 
> ```

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

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

```

---

_[View the full topic](https://forums.swift.org/t/urls-as-swift-package-identifiers/43404)._
