<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">I share Rick’s concerns about any proposal that pushes locked versions downstream to dependent projects. Two thoughts on that:</div><div class=""><br class=""></div><div class="">First, the specific: a lockfile should lock the versions for <i class="">all</i> dependencies, direct and indirect. Library lockfiles should have no effect on downstream projects. (Bundler does it this way, and it plays out well in practice.)</div><div class=""><br class=""></div><div class="">Second, some general thoughts on the principles underlying that, which also address the concern about multiple sources of truth:</div><div class=""><br class=""></div><div class="">The dependency specification (Package.swift) and the lockfile serve distinct roles. The dependency spec says “here’s information about what I need, and which versions I think I’m compatible with.” The lockfile says “here are the specific versions I’m actually using to build and test with.”</div><div class=""><br class=""></div><div class="">In short, Package.swift is a declaration of intent, whereas the lockfile is a statement of fact. Package.swift is a set of constraints; the lockfile is a snapshot. Package.swift describes things what&nbsp;<i class="">may</i> happen; the lockfile describes what <i class="">did</i> happen.</div><div class=""><br class=""></div><div class="">The lockfile’s primary purposes are (1) to prevent external variables from causing surprising breakages, and (2) to diagnose the “it works here but not there” problem. This is why lockfiles should be checked in, but shouldn’t affect downstream projects.</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>– `swift build --update-deps` updates all dependencies to the latest allowed version and sets/updates dependency locks for each dependency.</div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>– `swift build --update-dep=&lt;package name&gt;` updates the named dependency to the latest allowed version and sets/updates dependency lock for that dependency.</div></div></div></blockquote></div><div class=""><div class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>– `swift build --lock-deps` looks at the HEAD of all cloned dependencies and sets the dependency lock in the top-level Package.swift to that HEAD commit. This is useful when you want to explicitly lock to something other than the latest allowed version of a package.</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>– `swift build --lock-dep=&lt;package name&gt; looks at HEAD of the cloned named dependency and sets the dependency lock in the the top-level Package.swift for that one dependency.</div><div class=""></div></div></blockquote></div></div><div class=""><br class=""></div><div class="">This set of capabilities seems right, though I’m not entirely sure about the separate “lock” operation. Are you thinking of the case when somebody manually checks out a different version in a submodule, totally bypassing the package manager?</div><div class=""><br class=""></div><div class="">That particular command line syntax is a bit Byzantine. I suspect I’d be Googling it a lot.</div><div class=""><br class=""></div><div class="">I’m not so sure “build” makes sense as the top-level command. What about (just brainstorming):</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>swift package update</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>swift package update &lt;Lib&gt;</div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>swift package lock</div></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>swift package lock &lt;Lib&gt;</div></div><div class=""><br class=""></div><div class="">…or maybe “deps” instead of “package”?</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">– This proposal still doesn't fully address how you can use a branch for your dependency instead of a version tag, which was one of the reasons this topic came up in the first place. You could do so by checking out the branch in your cloned dependency and then using `swift build --lock-deps` to lock to that commit, but if you do a `swift build --update-deps` we'll blow that away.</div></div></blockquote></div><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><br class=""></div></div></div><div class="">I would imagine that…</div><div class=""><div class=""><br class=""></div><div class="">• Package.swift can specify any tag or branch, not just a version number.</div><div class="">• The update and lock commands write&nbsp;a specific commit to the lockfile.</div><div class="">• Perhaps, for readability, if there is a tag for the commit, the tag name goes in the lockfile instead of a raw commit hash, and that tag name might be a version number — but it’s always specific commits in the lockfile.</div></div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">To solve this, perhaps a dependency lock could have an additional optional "overridingRef" property which, if specified, overrides the version specifier for the package. That means that `swift build --update-deps` will now update the package to what that ref points to. The --lock-dep option could allow a follow-on option --lock-overriding-ref which takes the overriding ref to set.</div></div></blockquote></div><div class=""><br class=""></div><div class="">That seems overly complex at first glance. If Package.swift does specify a branch, I interpret that as saying, “I depend on prerelease features of this package. Resolve dependencies at your own risk!” At that point, having a version number in there as well is just confusion. When the code on that branch gets release, you go back to the version specifier.</div><div class=""><br class=""></div><div class="">Cheers, P</div><div class=""><br class=""></div><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 22, 2015, at 11:57 AM, Rick Ballard &lt;<a href="mailto:rballard@apple.com" class="">rballard@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Thanks for pushing on this, Ankit, Thomas, and Paul. As Doug mentioned in another thread, Apple is heading into our holiday shutdown until the new year, so I think we should schedule the actual evolution review for the first week of January. Let's get this hashed out in the meantime and ready for that review now, though.</div><div class=""><br class=""></div><div class="">Here are my comments:</div><div class=""><br class=""></div><div class="">– I know Cargo uses these terms already, but --lock and "lockfile" are very generic terms. A "package manager lockfile" could easily refer to a file multiple package manager processes use to avoid corrupting a shared database. I think calling this a "deplock" file (for "dependency lock") is much more specific without being much more verbose. And I'd suggest calling the option something like --lock-deps.</div><div class=""><br class=""></div><div class="">– Likewise, --bootstrap isn't very clear. I'd suggest --use-locked-deps instead. (If we have this flag at all... see below).</div><div class=""><br class=""></div><div class="">– I'm concerned about the lockfile being a 2nd source of truth (vs Package.swift) that could easily get out of sync. For example, if you update Package.swift to require a new minimum version, but forget to update the lockfile (or forget to commit the updated lockfile), users will wind up silently using a different version than that allowed by the Package.swift's specified version.</div><div class=""><br class=""></div><div class="">– I'm also uneasy with the lockfile being toml while Package.swift is swift. That seems inconsistent and requires users to work in two different configuration file syntaxes (even if toml is very simple).</div><div class=""><br class=""></div><div class="">– To address both of the above points, maybe the dep-lock info should be stored in Package.swift itself. In this case, any tool which automatically modifies your Package.swift for you would autoclear the&nbsp;dependency lock&nbsp;when it updates a package version, and since that data is in the same file, those two changes would get checked in together. When you're hand-editing the file, it'd be a lot easier to remember to clear (or update) the locked dependency. And you'd ensure that the Package.swift data is always in sync with your dependency lock across revisions and branches, since both data is in the same file (at least for direct dependencies).</div><div class=""><br class=""></div><div class=""><div class="">Since dependency locks apply to non-direct dependencies as well, we would need to add a new package property for modeling the dependency lock for an otherwise-unspecified dependency. And we might require that the locks fully specify the properties of the dependency they apply to, so if the required version of an indirect dependency changes, we can tell that the dependency lock is out of date. For example, say your "FooApp" package depends on "Lib1" and "Lib2", which both depend on "LibBar". "Lib1" might specify that it depends on LibBar versions: Version(1,0,1)..&lt;Version(2,0,0)), while "Lib2" might specify LibBar versions: Version(1,0,0)..&lt;Version(1,5,0)). FooApp's indirect dependency on LibBar is thus constrained to versions: Version(1,0,1)..&lt;Version(1,5,0)), and that's what we'd record for the dependencyLock:</div></div><div class=""><br class=""></div><div class="">let&nbsp;package&nbsp;=<div class="">&nbsp;Package(</div><div class="">&nbsp; &nbsp; name: "FooApp",</div><div class="">&nbsp; &nbsp; dependencies: [</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; .Package(url:&nbsp;"<a href="ssh://git@example.com/Lib1.git" class="">ssh://git@example.com/Lib1.git</a>"),</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>.Package(url:&nbsp;"<a href="ssh://git@example.com/Lib2.git" class="">ssh://git@example.com/Lib2.git</a>"),</div><div class="">&nbsp; &nbsp; ],</div><div class="">&nbsp; &nbsp; dependencyLocks: [</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>.DependencyLock(lockRevision: c611ad62500182cae041abe83db908c2ea8e4485, .Package(url:&nbsp;"<a href="ssh://git@example.com/Lib1.git" class="">ssh://git@example.com/Lib1.git</a>"),</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>.DependencyLock(lockRevision: 1fb095a46ff55161876380067344ff641b8e95e2, .Package(url:&nbsp;"<a href="ssh://git@example.com/Lib2.git" class="">ssh://git@example.com/Lib2.git</a>"),</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; .DependencyLock(lockRevision: db2e873d530c72023af00ce7fe9a37211b8d2fbc, .Package(url:&nbsp;"<a href="ssh://git@example.com/LibBar.git" class="">ssh://git@example.com/LibBar.git</a>", versions: Version(1,0,1)..&lt;Version(1,5,0)),</div><div class="">&nbsp; &nbsp; ],</div><div class="">)</div></div><div class=""><br class=""></div><div class="">If Lib2 then updated its version specification to &nbsp;Version(1,0,0)..&lt;Version(1,6,0). we could tell that our dependency lock was out of date and prompt you to create a new lock.</div><div class=""><br class=""></div><div class="">Note that we wouldn't expect you to have to hand-author the .DependencyLock (and manually repeat the version range for packages you depend on); normally this would be autogenerated by the package manager.</div><div class=""><br class=""></div><div class="">– It would be nice if we could warn, when building with dependency locks, if your dependencyLock revision does not match a dependency's version specifier. For example, if your dependency specifies (2,0,1)..&lt;Version(2,1,0), and your dependencyLock is db2e873d530c72023cf00ce7fe9a37211b8d2fbc, we would check and make sure that some revision 2.0.1 or greater contains db2e873d530c72023cf00ce7fe9a37211b8d2fbc, but that it's not reachable from 2.1.0 or greater. That said, `git tag --contains` is probably not fast enough for nontrivial repositories to run on each build for the purposes of issuing this warning, so this might be a non-starter for performance reasons.</div><div class=""><br class=""></div><div class="">– Should we always automatically use the deplock info? Ankit's proposal said no, while Thomas and Paul said yes. I think that it makes sense for most use cases to use a stable version of your dependencies and only update to a newer version explicitly, instead of having that happen implicitly when you build if there happens to be a new version. That favors always using the deplock info. Thus I think I like Paul's proposal to "always generate .lock if absent, always use the locked version if present, and use a separate command to update the locked version." So I'd suggest:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>– `swift build --update-deps` updates all dependencies to the latest allowed version and sets/updates dependency locks for each dependency.</div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>– `swift build --update-dep=&lt;package name&gt;` updates the named dependency to the latest allowed version and sets/updates dependency lock for that dependency.</div></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>– `swift build --lock-deps` looks at the HEAD of all cloned dependencies and sets the dependency lock in the top-level Package.swift to that HEAD commit. This is useful when you want to explicitly lock to something other than the latest allowed version of a package.</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>– `swift build --lock-dep=&lt;package name&gt; looks at HEAD of the cloned named dependency and sets the dependency lock in the the top-level Package.swift for that one dependency.</div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>– `swift build` clones any dependencies that aren't already cloned, checks out the locked commit for all dependencies (whether they were already cloned before or not), and adds dependency locks to Package.swift for any packages that don't have a lock already. This also warns if the dependency lock's package specifier doesn't match the actual package specifier where that dependency is defined, which indicates that your locks are out of date with respect to your dependency specifications.</div></div><div class=""><div class=""><br class=""></div><div class="">One downside to this behavior is it makes it easy to mess up when modifying your dependencies locally. If you make an edit to a cloned dependency and commit it, and then `swift build` the top-level package, swiftpm will automatically revert HEAD of that dependency to the locked commit, so it won't actually build your change. In order to avoid this, you need to run `swift build --lock-deps` after committing a local change to a cloned dependency, and it's easy to forget to do so. That said, the alternative behavior – where `swift build` preserves the state of your dependencies by default – means that if you've built a package in the past, and you pull and get a new Package.swift with new dependency locks, you won't automatically get those dependencies updated when you build, since you already have cloned dependencies whose HEADs are stale and don't match the new dependency locks. The latter problem seems worse than the former. I'm open to ideas to how to solve both problems nicely; the ways I've thought of so far make this proposal even more complex.</div><div class=""></div></div><div class=""><div class=""><br class=""></div></div><div class="">– This proposal still doesn't fully address how you can use a branch for your dependency instead of a version tag, which was one of the reasons this topic came up in the first place. You could do so by checking out the branch in your cloned dependency and then using `swift build --lock-deps` to lock to that commit, but if you do a `swift build --update-deps` we'll blow that away. To solve this, perhaps a dependency lock could have an additional optional "overridingRef" property which, if specified, overrides the version specifier for the package. That means that `swift build --update-deps` will now update the package to what that ref points to. The --lock-dep option could allow a follow-on option --lock-overriding-ref which takes the overriding ref to set.</div><div class=""><br class=""></div><div class="">– Likewise, this mechanism could be used to allow you to override the source of a dependency for your indirect dependencies. For example, if you depend on "Lib1", which depends on&nbsp;git@github.com:Somewhere/LibFoo.git, but you actually want to use your own fork of LibFoo – git@github.com:YourName/LibFoo.git – the dependency lock would allow that override. This would be done with an "overridingURL" property on the dependency lock.</div><div class=""><br class=""></div><div class="">– I am concerned about the complexity and additional learning curve this behavior brings to the package manager. That said, this seems like important functionality.</div><div class=""><br class=""></div><div class="">Thoughts?</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>- Rick</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="">On Dec 20, 2015, at 1:22 PM, Paul Cantrell via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">+1 for Ankit’s general idea. Details of the proposal aside, I’ll say from experience with bundler that it’s immensely useful — a lifesaver! — to know the exact version of the dependencies another author was using. This has saved my neck more than once.</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">IMO it’s useful to have a lock file checked in even for libraries — just not pushed forward to client projects. You still want to know what versions the library’s tests last passed against, both for CI and for diagnosing downstream breakage.</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">-1 to this:</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><div class=""><div class=""><div class=""><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">[The] lock file will only be re-modified by&nbsp;</span><code class="" style="font-size: 14px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">$ swift build</code><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">&nbsp;if</span>&nbsp;<code class="" style="font-size: 14px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">Package.swift</code><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">&nbsp;is modified by the user.</span></div><div class=""><code class="" style="font-size: 14px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">$ swift build</code><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">&nbsp;always ignores the lock file and uses local state of Packages dir /&nbsp;</span><code class="" style="font-size: 14px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">Package.swift</code></div><div class=""><code class="" style="margin: 0px; padding: 0px; border: none; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">…</code></div><div class=""><span class="">To lock the current state of Packages user can run&nbsp;</span><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">&nbsp;</span><code class="" style="font-size: 14px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">$ swift build --lock</code></div></div></div></div></div></div></blockquote></div></div><blockquote type="cite" class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><div class=""><div class=""><div class=""><div class=""></div></div></div></div></div></div></div></blockquote></div></div></blockquote></blockquote></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">A couple of problems with that:</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">(1) Package.swift can specify a version range. You may want to update to the latest patch release without actually modifying Package.swift. I agree with Thomas: there should be a command to update dependencies to the latest matching version. This command should also be able update a single dependency:</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><span class="Apple-tab-span" style="white-space: pre;">        </span>swift build --update SomePackage</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">(2) I don’t like the idea of the build system running in two separate modes, where sometimes the lock file is ignored and sometimes takes precedence. (If there’s a desire to run in an “unlocked” mode, how about it just doesn't generate the .lock if not already present, and always uses it if it is present?) In practice, though, I’ve found the bundler model works quite well: always generate .lock if absent, always use the locked version if present, and use a separate command to update the locked version.</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Cheers,</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Paul</div><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="">On Dec 20, 2015, at 9:51 AM, Thomas Guthrie via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">Personally, I’d be more in favour of having something similar to Cargo (Rust’s package/crate manager):</div><div class=""><br class=""></div><div class="">1. `swift build`</div><div class=""><br class=""></div><div class="">Almost the same as it is now, expect if there’s no Package.lock it creates one and subsequent builds use the same dependencies.</div><div class=""><br class=""></div><div class="">2. `swift build --update` or maybe eventually `swift update`</div><div class=""><br class=""></div><div class="">Updates the dependencies in Package.lock to their newest versions and writes them to disk. It should probably build the project as well but possibly makes less sense if its `swift update`.</div><div class=""><br class=""></div><div class="">Similar to Bundler and Cargo you’d check in your Package.lock for app projects and ignore it for library projects.</div><div class=""><br class=""></div><div class="">I’m not really sure what their motivation was for having a lock file always created, it definitely favours “app” projects heavily, but I’ve been messing around with Rust recently and it works pretty well honestly. Maybe there’s a way of making the experience better when the package is solely a library? Personally, if you’re developing a library and `swift build` updates a dependency that breaks everything it’s probably better to know then, whereas with an app you probably want to be working to a lock file and checking what happens when you update dependencies individually.</div><div class=""><br class=""></div><div class="">As for the format of Package.lock, I think it might have to be more complicated than shown to be able to handle the possibility of multiple versions of a dependency etc? Haven’t had a chance to mess around with swiftpm enough yet to say though.</div><div class=""><br class=""></div><div class="">(/end ramble of first thoughts)</div><div class=""><br class="Apple-interchange-newline"><span class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">— Thomas</span></div><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 20 Dec 2015, at 09:01, Ankit Agarwal via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><h1 class="" style="margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding: 0px; font-size: 28px; font-family: Helvetica, arial, sans-serif; margin-top: 0px !important;">Lock File for Swift Package Manager</h1><h2 class="" style="margin: 20px 0px 10px; padding: 0px; font-size: 24px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(204, 204, 204); font-family: Helvetica, arial, sans-serif;">Introduction</h2><p class="" style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px;">A&nbsp;<code class="" style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">Package.lock</code>&nbsp;file containing list of resolved dependencies generated by swiftpm.</p><h2 class="" style="margin: 20px 0px 10px; padding: 0px; font-size: 24px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(204, 204, 204); font-family: Helvetica, arial, sans-serif;">Motivation</h2><p class="" style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px;"><code class="" style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">Package.lock</code>&nbsp;file can be helpful in situations like :&nbsp;</p><div class=""><h3 class="" style="margin: 20px 0px 10px; padding: 0px; font-size: 18px; font-family: Helvetica, arial, sans-serif;">Reproduce exact versions of dependencies on different machine</h3></div>* Multiple developers working on a package would want to use the exact versions (including minor and patch) of the dependencies declared in the manifest file<div class="">* Also helpful when a build is being performed on a remote machine eg CI&nbsp;<br class=""><div class=""><div class=""><h3 class="" style="margin: 20px 0px 10px; padding: 0px; font-size: 18px; font-family: Helvetica, arial, sans-serif;">Pointing a dependency to an untagged commit</h3></div><div class="">Sometimes it might be helpful to lock a dependency to a particular commit ref for which a tagged version is unavailable in cases such as :</div><div class=""><br class=""></div><div class="">* Forking a 3rd party library and making it swiftpm compatible for temporary use until officially supported by the author</div><div class="">* Package is in active development and not ready for a release tag</div><div class=""><h2 class="" style="margin: 20px 0px 10px; padding: 0px; font-size: 24px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(204, 204, 204); font-family: Helvetica, arial, sans-serif;">Proposed Solution</h2><p class="" style="margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px;">swiftpm generates a simple&nbsp;<code class="" style="margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">Package.lock</code>&nbsp;file after resolving the dependency graph for that package in some simple format.</p></div><div class=""><h2 class="" style="margin: 20px 0px 10px; padding: 0px; font-size: 24px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(204, 204, 204); font-family: Helvetica, arial, sans-serif;">Detailed Design</h2><div class="">1. Initial<code class="" style="font-size: 14px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">$ swift build</code><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">&nbsp;resolves the dependency graph and generates a&nbsp;</span><code class="" style="font-size: 14px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">Package.lock</code><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">&nbsp;file similar to :</span></div><div class=""><pre class="" style="font-size: 13px; white-space: pre-wrap; margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;"><code class="" style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">ssh://<a href="http://github.com/foo/bar" class="">github.com/foo/bar</a> "v1.2.3"
<a href="http://github.com/foo/baz" class="">http://github.com/foo/baz</a> "v1.0.0"
../local/git/repo "v3.4.4"
</code></pre></div><div class=""><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">lock file will only be re-modified by&nbsp;</span><code class="" style="font-size: 14px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">$ swift build</code><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">&nbsp;if</span>&nbsp;<code class="" style="font-size: 14px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">Package.swift</code><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">&nbsp;is modified by the user.</span></div><div class=""><code class="" style="font-size: 14px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">$ swift build</code><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">&nbsp;always ignores the lock file and uses local state of Packages dir /&nbsp;</span><code class="" style="font-size: 14px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">Package.swift</code></div><div class=""><code class="" style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;"><br class=""></code></div><div class=""><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: transparent;">2. User modifies the cloned packages in Packages dir and when satisfied with the current code of the dependency, commits and pushes it.</span></div><div class=""><span class="" style="background-color: transparent;">To lock the current state of Packages user can run&nbsp;</span><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">&nbsp;</span><code class="" style="font-size: 14px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">$ swift build --lock</code><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">&nbsp;which might result something similar to&nbsp;</span></div><div class=""><div class=""><pre class="" style="font-size: 13px; white-space: pre-wrap; margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;"><code class="" style="margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">ssh://<a href="http://github.com/foo/bar" class="">github.com/foo/bar</a> "248441ff375a19c4365d00d6b0706e11173074f6"
<a href="http://github.com/foo/baz" class="">http://github.com/foo/baz</a> "v1.0.0"
../local/git/repo "v3.4.4"
</code></pre></div></div><div class=""><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: transparent;">the lock file is committed into the package repo for others to use.</span><br class=""></div><div class=""><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px; background-color: transparent;"><br class=""></span></div><div class=""><font face="Helvetica, arial, sans-serif" class=""><span class="" style="font-size: 14px;">3. A command like&nbsp;</span></font><code class="" style="font-size: 14px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">$ swift build --bootstrap</code><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">&nbsp;will always use the lock file to fetch and checkout the dependencies.</span></div><div class=""><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">This is useful because running&nbsp;</span><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">&nbsp;</span><code class="" style="font-size: 14px; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">$ swift build</code><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;">&nbsp;might give a higher patch or minor version of the dependency.</span></div><div class=""><span class="" style="font-family: Helvetica, arial, sans-serif; font-size: 14px;"><br class=""></span></div><div class=""><div class="" style="font-size: 13px;">4. If some dependency depends on commit hash (ie non-tagged commit) the author mentions that in their readme and the end user and maybe other parallel dependencies will have to use only that commit hash in order to avoid dependency hell.</div></div><div class=""><br class=""></div><div class="">5. Allow declaring a dependency without versions in the manifest file for user wanting to use a untagged dependency. This should probably only be allowed in debug configuration.</div><h2 class="" style="margin: 20px 0px 10px; padding: 0px; font-size: 24px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(204, 204, 204); font-family: Helvetica, arial, sans-serif;">Impact on existing code</h2><div class="">None as this would be additional functionality to swift package manager</div><div class=""><h2 class="" style="margin: 20px 0px 10px; padding: 0px; font-size: 24px; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(204, 204, 204); font-family: Helvetica, arial, sans-serif;">Alternatives Considered</h2></div></div><div class="">One alternative is to allow mentioning refs in manifest file while declaring a dependency but as discussed in<span class="Apple-converted-space">&nbsp;</span><a href="https://lists.swift.org/pipermail/swift-build-dev/Week-of-Mon-20151214/000067.html" class="">this</a><span class="Apple-converted-space">&nbsp;</span>thread it might not be the best idea.<br clear="all" class=""><div class=""><br class=""></div>--<span class="Apple-converted-space">&nbsp;</span><br class=""><div class="gmail_signature">Ankit<br class=""></div></div></div></div></div><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=Zar6ynBlzujkeVlpaavlQNZIAgaw3wAYlAtcron3qg1RDV0kVmGnN0cQ7yCfy0zjbsp-2BCkvOHWp3k2As9Rn-2FgUFZw4s86N2ukOyJDx7-2Ba6fSXlvvaHtmUsALVfoUrKZ7ZJ8FZtFfrtBfGVe-2B1FPSjUFQ3xaoe8rJMRjdEf9CBZKaOX4YsdiOnPima7aKsJ9ze8WkkEk0TIDVx5l8elKKShVaEx4c9w2T1BCACMa3Bqw-3D" alt="" width="1" height="1" border="0" class="" style="height: 1px !important; width: 1px !important; border-width: 0px !important; margin: 0px !important; padding: 0px !important;"><span class="Apple-converted-space">&nbsp;</span>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=zCg-2FSGF9Wk188a6c55kLyEbrj7YhaXxFEHM-2F-2B0YAlzVLMVR-2FbpAm4-2FoCCYzSr-2BKV0QVynagSiTz1XMZMfYskm44kaHHyVeH-2F3RipMqb2AahMqyGtYIci7EECxe1sg6pBSgHjG-2BqNogYD2EmzZc1-2BUccYt3xEUm9hMe0YoablI-2Bls0mflHdDY5toJGcHGmZs6Zh69dIYerbPWBp1bR8RJq-2FYfuM1eCg6JV22Z1BDfpDo-3D" alt="" width="1" height="1" border="0" class="" style="height: 1px !important; width: 1px !important; border-width: 0px !important; margin: 0px !important; padding: 0px !important;"></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=qz0eNO-2BnIaKwfHdqdSEoWDzK1gYoMlfMcRDuURe6g4lDjQdfLp5HLVJIQsOXGVVuyW9eufyAJ15KSe3m0bMsP6rz5A8j7qx4eaMoarmoRILA5J4z7n9oogH-2BDtgxQ0XrTh11EXEnxVOA0i4kwSWD1FBaiXXza5sSdXRqMQfalsXb13Ca-2BZR3v2nSm-2FGMAtPAprYcH-2Fp-2FXbS5tdxgBelp3iDEBX7qDioOuBijuqhQMmM-3D" alt="" width="1" height="1" border="0" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; height: 1px !important; width: 1px !important; border-width: 0px !important; margin: 0px !important; padding: 0px !important;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class=""><span class="Apple-converted-space">&nbsp;</span>_______________________________________________</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">swift-evolution mailing list</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="mailto:swift-evolution@swift.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></body></html>