Skip to content

Add PackageIdentity type #3057

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Nov 18, 2020
Merged

Add PackageIdentity type #3057

merged 10 commits into from
Nov 18, 2020

Conversation

mattt
Copy link
Contributor

@mattt mattt commented Nov 16, 2020

Motivation:

See #3032

Modifications:

  • Replaced PackageReference.PackageIdentity with top-level PackageIdentity type
  • Replaced existing calls to PackageReference.computeIdentity to initialization of new PackageIdentity type.
  • Changed access level of PackageReference.computeDefaultName to internal, limiting its use outside of PackageModel module.
  • Extracted testPackageReference into new, separate test case
  • Updated package identity to be configurable via top-level _useLegacyIdentities variable. This acts as a setter for a static internal property on PackageIdentity that configures how package identity is calculated via dependency injection.

Result:

This PR shouldn't affect current behavior. Rather, it serves to codify existing determinations of package identity and to tee up subsequent PRs to accommodate the new package identity semantics required for package registry support.

import TSCBasic
import TSCUtility

//@warn_unqualified_access
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside: I wish @warn_unqualified_access was available for top-level variable declarations (not just functions).

@mattt

This comment has been minimized.

}
}

internal protocol PackageIdentityProvider: LosslessStringConvertible {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the identity provider also has to provide equality for package identities, not just an initializer. For the "real" new implementation of identity we will need a staggered comparison that's not just comparing strings.

Copy link
Contributor Author

@mattt mattt Nov 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we require PackageIdentityProvider to be Equatable, then it can only be used as a generic constraint, because it has Self requirements in ==. Can you think of a reasonable / non-terrible way to work around this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just add a comparison function that's unrelated to Equatable. I think what we want to be able to do is compare two PackageIdentity instances using a comparison operation vended by PackageIdentityProvider.

Copy link
Contributor

@neonichu neonichu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks great!

I would just make the identity provider a bit more powerful as mentioned.

/// in a process called package resolution.
///
/// External package dependencies are located by a URL
/// (which may be an implicit `file://` URL in the form of a file path).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this description also mention path-based external dependencies? They do not use file://, which is only used when the local path contains an actual local Git repository and not just an unversioned package. Or is package identity only a thing for actual remote packages (not root or local)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I was trying to get at — my conceit here is that a file path is actually a file:/// URL with an implicit scheme. Any package dependency, local or remote, is described by a URL: local use file:/// URLs and remote use any other scheme. CanonicalPackageIdentity distinguishes between local from remote by preserving a leading slash (for example, you couldn't shadow a remote URL by having a root directory named /github.com/). Does that all make sense?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood, but I think that's too subtle and confusing of a way to represent it. And checking the file system for whether a particular path has a .git isn't a good way to do it either. I think there should be a clear way to represent that a package is either an unversioned take-it-as-given path in the file system or a repository that just happens to be in the local file system. Historically there has been value in using no scheme for the former and file: for the latter. I think it would be a mistake to conflate them, even it's through an extra slash character.

Copy link
Contributor

@tomerd tomerd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks great, thanks @mattt

there are two question @abertelrud brought up that should be answered but I hope they are straight forward by exposing the identity on the ref

@abertelrud
Copy link
Contributor

abertelrud commented Nov 17, 2020

Right, I don't think they are significant issues (since local packages are supported via scheme-less URLs and are distinct from file:// URLs) but since clients will need to adapt, I'm trying to identify what the downstream changes will need to be. From the unit tests it looks as if it can mostly be handled by instantiating a PackageIdentity from the URL strings. I think the only remaining question is how a client that wanted to display a package's display name before fetching that package would do so. For the short term it could show the description of the package identity but since that is an opaque value with unspecified format it might not be visually appealing.

@tomerd
Copy link
Contributor

tomerd commented Nov 17, 2020

@swift-ci please smoke test

Distinguish between path and URL initializers at call sites
@mattt
Copy link
Contributor Author

mattt commented Nov 17, 2020

@abertelrud @tomerd @neonichu Thanks for reviewing my changes. I just pushed 766ea50, which is responsive to this discussion thread. This commit takes the additional step to distinguish between PackageIdentity values constructed from absolute paths and URLs (per @abertelrud 's comment). Right now, the url version takes a String, but that could be migrated to Foundation.URL or some other URL type in the future.

Does this seem like the right change for this PR?

@mattt
Copy link
Contributor Author

mattt commented Nov 17, 2020

@swift-ci please smoke test

@mattt mattt requested a review from abertelrud November 17, 2020 19:03
@mattt mattt requested review from tomerd and neonichu November 17, 2020 19:03
@abertelrud
Copy link
Contributor

Thanks, @mattt! I'll take a look at the new diffs right away, but that sounds like the right API from a client's perspective.

Copy link
Contributor

@abertelrud abertelrud left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @mattt, this looks good to me know. I realize that separate URL and AbsolutePath initializers for package identity are maybe tedious, but I think it will really help clients keep things straight. In one client I worked on, this confusion, where everything was just a string, was a source of at least one bug.

@abertelrud
Copy link
Contributor

Thanks again for these diffs, @mattt. I'm adapting some of the downstream dependencies to it and will do some testing to avoid regressions. I plan to wrap that up by tonight. Are you OK with holding off until tomorrow to merge?

@mattt
Copy link
Contributor Author

mattt commented Nov 17, 2020

Absolutely. Thanks for taking a look at the downstream consumers. Let me know if anything comes up in your review.

@abertelrud
Copy link
Contributor

Great, thanks @mattt. The changes that are technically needed to keep compiling turn out to be fairly minimal, and similar to unit test changes in this PR... the later changes to adapt to the change in package identity will be more interesting (but of course very useful!). But that's for after this PR lands.

@abertelrud
Copy link
Contributor

abertelrud commented Nov 18, 2020

@mattt this seems to work fine downstream, after adapting some of the client code. All ready to merge as far as you're concerned?

@abertelrud abertelrud self-assigned this Nov 18, 2020
@mattt
Copy link
Contributor Author

mattt commented Nov 18, 2020

@abertelrud I just gave everything another once-over, and I think this is ready to merge. Feel free to do that whenever you're ready.

I'd like to continue our conversation from https://github.com/apple/swift-package-manager/pull/3057/files#r525394175, but that's not a blocker here.

@abertelrud
Copy link
Contributor

Great, thanks! Merging.

@abertelrud abertelrud merged commit e887924 into swiftlang:main Nov 18, 2020
@tomerd
Copy link
Contributor

tomerd commented Nov 18, 2020

🥳 🎊

@mattt mattt deleted the package-identity branch November 18, 2020 20:49
federicobucchi pushed a commit to federicobucchi/swift-package-manager that referenced this pull request Jan 6, 2021
* Replace PackageReference.PackageIdentity with top-level PackageIdentity type

* Change access level of PackageReference.computeDefaultName to internal

* Extract testPackageReference into new PackageIdentityTests file

* Allow package identity to be configurable via dependency injection

Rename PackageIdentityTests to LegacyPackageIdentityTests

* Revert change to access level of computeDefaultName, making it public

* Remove LosslessStringConvertible conformance

* Add documentation comment for provider type property

* Add initializer that takes an AbsolutePath parameter

* Remove commented @warn_unqualified_access attribute

* Add argument label to public PackageIdentity initializers

Distinguish between path and URL initializers at call sites
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants