<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><blockquote type="cite" class=""><div class=""><span style="font-family: SFUIText-Regular;" class="">The review of "SE-0145: Package Manager Version Pinning" begins again after revisions, starting now and running through November 28th. The proposal is available here:</span></div><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br style="font-family: SFUIText-Regular;" class=""><span class="Apple-tab-span" style="font-family: SFUIText-Regular; white-space: pre;">        </span><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0145-package-manager-version-pinning.md" class="">https://github.com/apple/swift-evolution/blob/master/proposals/0145-package-manager-version-pinning.md</a><div class=""><br style="font-family: SFUIText-Regular;" class=""></div></div></div></blockquote><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><span style="font-family: SFUIText-Regular;" class="">What is your evaluation of the proposal?</span><br style="font-family: SFUIText-Regular;" class=""></div></div></div></blockquote><div><br class=""></div><div>+1</div><div>I think this is an important change for the Swift package ecosystem.</div><div>Having reproducible builds by default is a big step forward.</div><div>Storing the version of all dependencies in version control and having an easy way to update them helps to reduce maintenance overhead of packages.</div><div><br class=""></div><div>I have two comments / requests for improvement:</div><div>&nbsp;* Having two completely separate modes (—enable-autopin vs. —disable-autopin) with a different semantic (e.g. for `swift update`) unnecessarily complicates the design. I understand that there are different use cases where packages have to be handled differently, however I think we should invest some more time on understanding these use cases (see below).</div><div>&nbsp;* For me the term ‚pin‘ (just like ‚lock‘) implies that the version of pinned dependencies should be fixed and should therefore not be changed/updated. (But I’m not a native speaker, so you may have other associations here.) We should make clear that we *manage* dependencies and that dependencies should be easy to update even while they can be reproduced exactly.</div><div><br class=""></div><div>Let’s look at the features of the proposal and how they can be used:</div><div>&nbsp;* Defines two groups of dependencies (pinned vs. unpinned) where one group can be updated independently;</div><div>&nbsp;* unpinned dependencies are automatically updated on clone, not just on update;</div><div>&nbsp;* updates of unpinned dependencies are not considered a change in the package’s repository.</div><div>This can be used to easily update internal dependencies while keeping the same version of external dependencies.</div><div>Or to keep some difficult-to-update dependencies while constantly updating all the other dependencies.</div><div>Or to not create git changes for some selected dependencies.</div><div>You name it.</div><div><br class=""></div><div>Basically it boils down to better control when and how dependencies are updated.</div><div>However, I’m not yet convinced that the proposed pinning system is the best way to do that.</div><div>Why only support two groups? Why these two modes of operation? Why not support a specific set of dependencies which are unmanaged while still tracking all new dependencies?</div><div><br class=""></div><div><div>When we want to create groups of dependencies and handle them differently, then we should do that explicitly, by introducing groups which can be defined by the package maintainer.</div><div><br class=""></div><div>E.g.:</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>swift package dependency &lt;dep-name&gt; —group &lt;group-name&gt;</div><div><br class=""></div><div>We could store each group in a file of its own (e.g. `Package-&lt;group-name&gt;.versions` or whatever) and the maintainer could put each one under version control or not as he likes.</div><div><br class=""></div><div>A whole group could be updated in one go:</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>swift package update —group internal</div><div><br class=""></div><div>This could simulate the pinning as described in the proposal:</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>swift package dependency A —group unpinned</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>swift package dependency B —group pinned</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>echo Package-unpinned.versions &gt; .gitignore</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>git add .gitignore Package-pinned.versions</div><div><br class=""></div><div>Each group can be updated individually and the package maintainer can put this group under version control or not.</div><div>One group would have to be special to automatically include all new dependencies.</div><div>Other than that we would not need any special handling ala —repin/—enable-autopin. Groups could be defined to make updating related packages easier.</div><div>When needed, we could even set some groups to update automatically on build (not only on clone/update).</div><div>This could be useful for closely related packages. Why should clone be special anyways?</div><div><br class=""></div><div class=""><br class=""></div></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><span style="font-family: SFUIText-Regular;" class="">&nbsp;Is the problem being addressed significant enough to warrant a change to Swift?</span><br style="font-family: SFUIText-Regular;" class=""></div></div></div></blockquote><div><br class=""></div><div>Yes.</div><div>Not managing the package dependencies would unnecessarily complicate package maintenance in the long term.</div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><span style="font-family: SFUIText-Regular;" class="">Does this proposal fit well with the feel and direction of Swift?</span><br style="font-family: SFUIText-Regular;" class=""></div></div></div></blockquote><div><br class=""></div><div>Yes.</div><div>Reproducible builds fit well into the safe-by-default approach of Swift.<br class=""></div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><span style="font-family: SFUIText-Regular;" class="">If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?</span><br style="font-family: SFUIText-Regular;" class=""></div></div></div></blockquote><div><br class=""></div>I always hated `npm` and all those node packages which had overly restrictive dependency requirements.<br class="">I guess these were used in order to have more control about which version to use, but this resulted<br class="">in both packages which I could not build out of the box (because some dependencies changed),<br class="">and packages I could not update because of conflicting requirements.<br class="">Using loose version requirements + semver in `Package.swift` files together with exact versions<br class="">of all dependencies stored in the top-level package solves everything: you get reproducible builds<br class="">(based on `Package*.versions`) together with easy updates (based on all packages’ `Package.swift`).</div><div><br class=""></div><div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><span style="font-family: SFUIText-Regular;" class="">How much effort did you put into your review? A glance, a quick reading, or an in-depth study?</span><br style="font-family: SFUIText-Regular;" class=""></div></div></div></blockquote></div><div class=""><br class=""></div>Read both versions of the proposal, took part in the discussion.<div class=""><br class=""><div class="">— Martin Waitz</div></div></body></html>