Hello Rick, thanks for the great proposal! Strong +1 from me :-)
— Martin > Am 27.04.2017 um 02:25 schrieb Rick Ballard via swift-evolution > <[email protected]>: > > Hi all, > > We have a proposal we'd like feedback on to revise how Swift Package Manager > dependency resolution, updating, and pinning works. These changes weren't > planned in the roadmap we published a few months ago, but it's become clear > since then that we have some holes in our dependency resolution behavior that > need fixing. We've also come to the conclusion that our original design for > pinning was overcomplicated and should be revised. > > Please give us your feedback; we're hoping to submit this proposal for > official review next week. > > The current draft of the proposal can be found at > https://github.com/rballard/swift-evolution/commit/e5e7ce76f29c855aa7162ed3733b09e701d662d6 > > <https://github.com/rballard/swift-evolution/commit/e5e7ce76f29c855aa7162ed3733b09e701d662d6>. > I'm also including it below. > > Thanks, > > - Rick > > Package Manager Revised Dependency Resolution > > Proposal: SE-NNNN > <https://github.com/rballard/swift-evolution/blob/e5e7ce76f29c855aa7162ed3733b09e701d662d6/proposals/NNNN-package-manager-revised-dependency-resolution.md> > Author: Rick Ballard <https://github.com/rballard> > Review Manager: TBD > Status: Draft in progress > Bug: TBD > > <https://github.com/rballard/swift-evolution/blob/e5e7ce76f29c855aa7162ed3733b09e701d662d6/proposals/NNNN-package-manager-revised-dependency-resolution.md#introduction>Introduction > > This proposal makes the package manager's dependency resolution behavior > clearer and more intuitive. It removes the pinning commands (swift package > pin & swift package unpin), replaces the swift package fetch command with a > new swift package resolve command with improved behavior, and replaces the > optional Package.pins file with a Package.resolved file which is always > created during dependency resolution. > > > <https://github.com/rballard/swift-evolution/blob/e5e7ce76f29c855aa7162ed3733b09e701d662d6/proposals/NNNN-package-manager-revised-dependency-resolution.md#motivation>Motivation > > When SE-0145 Package Manager Version Pinning > <https://github.com/apple/swift-evolution/blob/master/proposals/0145-package-manager-version-pinning.md> > was proposed, it was observed that the proposal was overly complex. In > particular, it introduced a configuration option allowing some packages to > have autopinning on (the default), while others turned it off; this option > affected the behavior of other commands (like swift package update, which has > a --repinflag that does nothing for packages that use autopinning). This > configuration option has proved to be unnecessarily confusing. > > In the existing design, when autopinning is on (which is true by default) the > swift package pin command can't be used to pin packages at specific revisions > while allowing other packages to be updated. In particular, if you edit your > package's version requirements in the Package.swift manifest, there is no way > to resolve your package graph to conform to those new requirements without > automatically repinning all packages to the latest allowable versions. Thus, > specific, intentional pins can not be preserved without turning off > autopinning. > > The problems here stem from trying to use one mechanism (pinning) to solve > two different use cases: wanting to record and share resolved dependency > versions, vs wanting to keep a badly-behaved package at a specific version. > We think the package manager could be simplified by splitting these two use > cases out into different mechanisms ("resolved versions" vs "pinning"), > instead of using an "autopinning" option which makes these two features > mutually-exclusive and confusing. > > Additionally, some dependency resolution behaviors were not well-specified > and do not behave well. The package manager is lax about detecting changes to > the versions specified in the Package.swift manifest or Package.pinspinfile, > and fails to automatically update packages when needed, or to issue errors if > the version requirements are unsatisfiable, until the user explicitly runs > swift package update, or until a new user without an existing checkout > attempts to build. We'd like to clarify and revise the rules around when and > how the package manager performs dependency resolution. > > > <https://github.com/rballard/swift-evolution/blob/e5e7ce76f29c855aa7162ed3733b09e701d662d6/proposals/NNNN-package-manager-revised-dependency-resolution.md#proposed-solution>Proposed > solution > > The pinning feature will be removed. This removes the swift package pin and > swift package unpin commands, the --repin flag to swift package update, and > use of the Package.pins file. > > In a future version of the package manager we may re-introduce pinning. If we > do, pins will only be recorded in the Package.pins file when explicitly set > with swift package pin, and any pinned dependencies will not be updated by > the swift package update command; instead, they would need to be unpinned to > be updated. This would be a purely additive feature which packages could use > in addition to the resolved versions feature when desired. > > A new "resolved versions" feature will be added, which behaves very similarly > to how pinning previously behaved when autopinning was on. The version of > every resolved dependency will be recorded in a Package.resolved file in the > top-level package, and when this file is present in the top-level package it > will be used when performing dependency resolution, rather than the package > manager finding the latest eligible version of each package. swift package > updatewill update all dependencies to the latest eligible versions and update > the Package.resolved file accordingly. > > Resolved versions will always be recorded by the package manager. Some users > may chose to add the Package.resolved file to their package's .gitignore > file. When this file is checked in, it allows a team to coordinate on what > versions of the dependencies they should use. If this file is gitignored, > each user will seperately choose when to get new versions based on when they > run the swift package update command, and new users will start with the > latest eligible version of each dependency. Either way, for a package which > is a dependency of other packages (e.g. a library package), that package's > Package.resolved file will not have any effect on its client packages. > > The existing swift package fetch command will be deprecated, removed from the > help message, and removed completely in a future release of the Package > Manager. In its place, a new swift package resolve command will be added. The > behavior of resolve will be to resolve dependencies, taking into account the > current version restrictions in the Package.swift manifest and > Package.resolved resolved versions file, and issuing an error if the graph > cannot be resolved. For packages which have previously resolved versions > recorded in the Package.resolved file, the resolvecommand will resolve to > those versions as long as they are still eligible. If the resolved versions > file changes (e.g. because a teammate pushed a new version of the file) the > next resolve command will update packages to match that file. After a > successful resolve command, the checked out versions of all dependencies and > the versions recorded in the resolved versions file will match. In most cases > the resolve command will perform no changes unless the Package.swiftmanifest > or Package.resolved file have changed. > > The following commands will implicitly invoke the swift package resolve > functionality before running, and will cancel with an error if dependencies > cannot be resolved: > > swift build > swift test > swift package generate-xcodeproj > The swift package show-dependencies command will also implicitly invoke swift > package resolve, but it will show whatever information about the dependency > graph is available even if the resolve fails. > > The swift package edit command will implicitly invoke swift package resolve, > but if the resolve fails yet did identify and fetch a package with the > package name the command supplied, the command will allow that package to be > edited anyway. This is useful if you wish to use the edit command to edit > version requirements and fix an unresolvable dependency graph. swift package > unedit will unedit the package and then perform a resolve. > > > <https://github.com/rballard/swift-evolution/blob/e5e7ce76f29c855aa7162ed3733b09e701d662d6/proposals/NNNN-package-manager-revised-dependency-resolution.md#detailed-design>Detailed > design > > The resolve command is allowed to automatically add new dependencies to the > resolved versions file, and to remove dependencies which are no longer in the > dependency graph. It can also automatically update the recorded versions of > any package whose previously-resolved version is no longer allowed by the > version requirements from the Package.swiftmanifests. When changed version > requirements force a dependency to be automatically re-resolved, the latest > eligible version will be chosen; any other dependencies affected by that > change will prefer to remain at their previously-resolved versions as long as > those versions are eligible, and will otherwise update likewise. > > The Package.resolved resolved versions file will record the git revision used > for each resolved dependency in addition to its version. In future versions > of the package manager we may use this information to detect when a > previously-resolved version of a package resolves to a new revision, and warn > the user if this happens. > > The swift package resolve command will not actually perform a git fetch on > any dependencies unless it needs to in order to correctly resolve > dependencies. As such, if all dependencies are already resolved correctly and > allowed by the version constraints in the Package.swift manifest and > Package.resolved resolved versions file, the resolvecommand will not need to > do anything (e.g. a normal swift build won't hit the network or make > unnecessary changes during its implicit resolve). > > If a dependency is in edit mode, it is allowed to have a different version > checked out than that recorded in the resolved versions file. The version > recorded for an edited package will not change automatically. If a swift > package updateoperation is performed while any packages are in edit mode, the > versions of those edited packages will be removed from the resolved versions > file, so that when those packages leave edit mode the next resolution will > record a new version for them. Any packages in the dependency tree underneath > an edited package will also have their resolved version removed by swift > package update, as otherwise the resolved versions file might record versions > that wouldn't have been chosen without whatever edited package modifications > have been made. > > > <https://github.com/rballard/swift-evolution/blob/e5e7ce76f29c855aa7162ed3733b09e701d662d6/proposals/NNNN-package-manager-revised-dependency-resolution.md#alternatives-considered>Alternatives > considered > > We considered repurposing the existing fetch command for this new behavior, > instead of renaming the command to resolve. However, the name fetch is > defined by git to mean getting the latest content for a repository over the > network. Since this package manager command does not always actually fetch > new content from the network, it is confusing to use the name fetch. In the > future, we may offer additional control over when dependency resolution is > allowed to perform network access, and we will likely use the word fetch in > flag names that control that behavior. > > We considered continuing to write out the Package.pins file for packages > whose Swift tools version > <https://github.com/apple/swift-evolution/blob/master/proposals/0152-package-manager-tools-version.md> > was less than 4.0, for maximal compatibility with the Swift 3.1 tools. > However, as the old pinning behavior was a workflow feature and not a > fundamental piece of package compatibility, we do not consider it necessary > to support in the 4.0 tools. > > We considered keeping the pin and unpin commands, with the new behavior as > discussed briefly in this proposal. While we think we may wish to bring this > feature back in the future, we do not consider it critical for this release; > the workflow it supports (updating all packages except a handful which have > been pinned) is not something most users will need, and there are workarounds > (e.g. specify an explicit dependency in the Package.swift manifest). > > > <https://github.com/rballard/swift-evolution/blob/e5e7ce76f29c855aa7162ed3733b09e701d662d6/proposals/NNNN-package-manager-revised-dependency-resolution.md#why-we-didnt-use-packagelock>Why > we didn't use "Package.lock" > > We considered using the .lock file extension for the new resolved versions > file, to be consistent with many other package managers. We expect that the > decision not to use this extension will be controversial, as following > established precedent is valuable. However, we think that a "lockfile" is a > very poor name for this concept, and that using that name would cause > confusion when we re-introduce pins. Specifically: > > Calling this a "lock" implies a stronger lockdown of dependencies than is > supported by the actual behavior. As a simple update command will reset the > locks, and a change to the specified versions in Package.swift will override > them, they're not really "locked" at all. This is misleading. > When we re-introduce pinning, it would be very confusing to have both "locks" > and "pins". Having "resolved versions" and "pins" is not so confusing. > The term "lock" is already overloaded between POSIX file locks and locks in > concurrent programming. > For comparison, here is a list of other package managers which implement > similar behavior and their name for this file: > > Package Manager Language Resolved versions file name > Yarn JS yarn.lock > Composer PHP composer.lock > Cargo Rust Cargo.lock > Bundler Ruby Gemfile.lock > CocoaPods ObjC/Swift Podfile.lock > Glide Go glide.lock > Pub Dart pubspec.lock > Mix Elixir mix.lock > rebar3 Erlang rebar.lock > Carton Perl carton.lock > Carthage ObjC/Swift Cartfile.resolved > Pip Python requirements.txt > NPM JS npm-shrinkwrap.json > Meteor JS versions > Some arguments for using ".lock" instead of ".resolved" are: > > Users of other package managers will already be familiar with the terminology > and behavior. > For packages which support multiple package managers, it will be possible to > put "*.lock" into the gitignore file instead of needing a seperate entry for > "*.resolved". > However, we do not feel that these arguments outweigh the problems with the > term "lock". If providing feedback asking that we reconsider this decision, > please be clear about why the above decision is incorrect, with new > information not already considered. > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
