<https://github.com/apple/swift-package-manager/blob/master/Documentation/Internals/SwiftBasedManifestFormat.md#discussion>

> We decided to use a Swift-based format for the manifest because we believe it 
> gives developers the best experience for working with and describing their 
> project. The primary alternative we considered was to use a declarative 
> format encoded in a common data format like JSON. Although that would 
> simplify implementation of the tooling around the manifest, it has the 
> downside that users must then learn this additional language, and the 
> development of high quality tools for that (documentation, syntax coloring, 
> parsing diagnostics) isn't aligned with our goal of building great tools for 
> Swift. In contrast, using the Swift language means that we can leverage all 
> of the work on Swift to make those tools great.


Could you generate a similar Swift-based format for the lockfile?

-- Ben

> On 17 Mar 2016, at 18:23, Max Howell via swift-evolution 
> <[email protected]> wrote:
> 
> The following is a draft proposal, feedback welcome.
> 
> ____________
> SwiftPM Dependency Version Locking
> Proposal: SE-NNNN 
> <https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-swiftpm-dependency-lockfiles.md>
> Author(s): Ankit Agarwal <https://github.com/aciidb0mb3r>, Max Howell 
> <https://github.com/mxcl>
> Status: Discussion
> Review manager: Rick Ballard
> Introduction
> This proposal seeks to declare a new, generated file 
> Packages/VersionLocks.json that describes the exact state of a package’s 
> dependency graph and then by default will be respected when executing most 
> package manager commands. Thus it is considered a “version lock” for a 
> package’s dependency sources.
> 
> Swift-evolution thread 
> <https://lists.swift.org/pipermail/swift-build-dev/Week-of-Mon-20151214/000067.html>
> Terminology
> A package refers to a published, versioned git repository designed to be 
> consumed as a dependency by SwiftPM.
> A project refers to an end-user workspace that uses SwiftPM (via a 
> Package.swift and swift build) fetching and building packages as part of its 
> build
> Describing this distinction is required because both the above have the same 
> form, but are used differently by an end-user. An end-user may publish 
> packages, but will eventually consume those packages in a project.
> 
> As justification for this confusion, it is considered a feature that projects 
> can easily and trivially become packages when using SwiftPM. Encouraging a 
> vibrant packaging ecosystem is one of our goals.
> 
> Motivation
> In a vibrant packaging ecosystem, dependencies update continuously with 
> bug-fixes and new features. A development team needs:
> 
> To ensure they are all using the same versions of their dependencies for any 
> given version-control commit.
> Ensure they are all using the same versions of the underlying Swift toolchain
> Be able to override or modify dependency specifications for the whole team 
> for specific commits.
> Currently with SwiftPM it is possible to fulfill 1. by committing the sources 
> of a package’s dependencies with the package itself, but this is not always 
> desirable. There is no way to achieve 2. and 3. with SwiftPM alone.
> 
> Additionally, there is not currently a way to know which version of Swift a 
> package requires to build. At this time this situation is particularly 
> precarious because Swift itself is not backwards compatible. As a Swift 
> developer at the very least recording which Swift version a package was built 
> with by the package developer is essential information in order to assess a 
> package's suitability. Practically the package manager could in the future 
> use this information to aid an end-user or even fix the problem when packages 
> fail to compile.
> 
> Proposed Solution
> A file: Packages/VersionLocks.json will be created alongside the 
> Package.swift file. Its contents will describe:
> 
> The URL and versions of cloned dependencies
> An inline diff of any local modifications made to those packages relative to 
> their pristine cloned states
> The exact version of the Swift toolchain used as part of the last successful 
> build of the package
> This file is generated by SwiftPM.
> 
> This file should be checked-in with projects.
> 
> This file is generated and should not be edited by users. If the file is 
> edited by users the behavior is undefined.
> 
> This file should be checked-in with packages designed for consumption in 
> projects, however SwiftPM will not use the checkout files of dependencies 
> when determining a project’s dependency graph (this would make dependency 
> graphs much less likely to resolve due to overly strict versioning 
> requirements). In the future we may choose to make it possible for end-users 
> to attempt to build a package using all checkout files since in certain 
> deployment scenarios where an exact graph has already been tested, this is a 
> solid reliabiity feature.
> 
> Any local, modifications made to the clones in Packages are recorded in 
> Packages/VersionLocks.json as part of the flow described in the next section. 
> Modifications here means: changes to git remotes and the git-ref of the 
> checked-out HEAD.
> 
> Detailed Design
> In a fresh clone that does not contain a Packages directory swift build will 
> determine the dependency graph, clone the packages into Packages and generate 
> a Packages/VersionLocks.json file.
> 
> The user can now step into the Packages directory and modify package sources. 
> If the user then runs swift build again the package manager will error out:
> 
> error: dependency sources have been modified
> execute `swift build --lock` or `swift build --ignore-lock`
> It is an error to build against an unlocked dependency graph, but to 
> facilitate fixing bugs etc. an ignore flag can be specified.
> 
> When swift build --lock is specified the package manager regenerates the 
> lockfile detailing the active git remote and the SHA that is checked-out.
> 
> Every time swift build completes a build the lockfile is updated (if 
> necessary) recording the current version of the Swift toolchain that achieved 
> the build.
> 
> Packages/VersionLocks.json
> 
> The exact design of the contents of this file will be explored during 
> iterative development, but here is a possible example:
> 
> json { "packages": [ { "clone": "Packages/PromiseKit-3.0.3", "origin": 
> "https://github.com/mxcl/PromiseKit <https://github.com/mxcl/PromiseKit>" 
> "ref": "3.0.3" }, { "clone": "Packages/Alamofire-1.2.3", "origin": 
> "https://github.com/a-fork-somewhere/Alamofire 
> <https://github.com/a-fork-somewhere/Alamofire>" "ref": "crucial-fix" }, { 
> "clone": "Packages/Quick-1.2.3", "origin": "https://github.com/Quick/Quick 
> <https://github.com/Quick/Quick>" "ref": "1.2.3" } ] }
> 
> Workflow — Regular Build
> 
> User runs swift build
> If Packages/ contains clones and a VersionLocks.jsonSwiftPM skips to 7.
> If Packages/ contains clones and no VersionLocks.json the lockfile is 
> generated from the clones
> If Packages/ contains checked out sources without git information and no 
> VersionLocks.json SwiftPM fetches the git information and provided there is 
> no diff, generates the Lockfile, if there is variation it is an error *
> If Packages/VersionLocks.json is present its dependency graph is used
> If Packages doesn't exist or is empty the dependency graph is resolved, 
> packages are cloned and the Lockfile is generated
> Build, if Packages are missing because we skipped from 2. the build will 
> error, it is the user's responsibility to instruct SwiftPM to --update or to 
> fix their dependency graph some other way.
> 
> This scenario is so users can check in their complete dependency sources to 
> their tree instead of / as well as the VersionLocks.json file: a situation 
> which sometimes is necessary if your dependencies are removed from their 
> third party online location, etc.
> 
> Workflow — Making Modifications
> 
> User makes local modification to a dependency’s sources
> User runs swift build
> swift build errors out.
> User must either lock the graph or run with --ignore-lock
> The error-out is likely to be considered tedious by users, however we 
> consider it important that users are made aware and forced to act when they 
> modify their dependencies and thus are exposing their team/users to so-called 
> “dependency hell”.
> 
> Runing swift build --lock regenerates the lockfile, but does not build.
> 
> Modifications must be committed. This means that if the modifications are not 
> uploaded to a location accessible to the rest of the team they will fail to 
> build when they update their checkouts.
> 
> The package manager could check for this by asking git if the specified 
> origin has the current locked ref and error out as appropriate.
> 
> Workflow — Overriding Packages
> 
> User steps into a Package directory eg. Packages/Foo-1.2.3
> User changes the origin of Foo to their own fork
> User alters HEAD to point to a fix in their own fork
> swift build errors out.
> User must either lock the graph or run with --ignore-lock
> Running swift build --lock regenerates the lockfile, the new origin and tag 
> is stored. Thus a fresh clone of this project would use these overrides.
> 
> It is important to note that this workflow will not be respected for 
> dependencies, only for projects.
> 
> If a package author requires an override they have a few options:
> 
> Change the Package.swift dependency specification. This should only be done 
> as a last resort, for example, a critical bug must be fixed in a dependency 
> and that dependency author is not being responsive. It is up to the Package 
> author to ensure this scenario goes well. SwiftPM itself wants to guard 
> against these conditions with our proposed “publish & lint” step that 
> validates such decisions before signing a published package tag. But we are 
> not there yet and thus package authors should be responsible.
> Advise end-users in a package README that they should override the dependency 
> themselves.
> 2 is preferred, but 1 will happen. We consider it our responsibility to 
> develop tooling that makes 1. safe or unnecessary, but we are not there yet.
> 
> Workflow — Updating Packages
> 
> SwiftPM has no update mechanism yet, but once it does running swift build 
> --update will fetch the latest versions of all dependencies and update the 
> lockfile.
> 
> Impact on existing code
> This proposal will have no impact on existing code.
> 
> Alternatives Considered
> One alternative is to allow mentioning refs in manifest file while declaring 
> a dependency but as discussed in this 
> <http://markdownlivepreview.com/%22https://lists.swift.org/pipermail/swift-build-dev/Week-of-Mon-20151214/>
>  thread it might not be the best idea.
> 
> Using Git submodules for this feature was considered. However something 
> additionally would be required to specify swift version and record local 
> diffs. Also this would lock us into git, and despite the fact that currently 
> we only use git, we have not yet ruled out supporting other version control 
> systems.
> 

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to