<div dir="ltr"><h1 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 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 style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px">A <code 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> file containing list of resolved dependencies generated by swiftpm.</p><h2 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 style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px"><code 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> file can be helpful in situations like : </p><div><h3 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>* Also helpful when a build is being performed on a remote machine eg CI <br><div><div><h3 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>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><br></div><div>* Forking a 3rd party library and making it swiftpm compatible for temporary use until officially supported by the author</div><div>* Package is in active development and not ready for a release tag</div><div><h2 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 style="margin:15px 0px;font-family:Helvetica,arial,sans-serif;font-size:14px">swiftpm generates a simple <code 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> file after resolving the dependency graph for that package in some simple format.</p></div><div><h2 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>1. Initial<code 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 style="font-family:Helvetica,arial,sans-serif;font-size:14px"> resolves the dependency graph and generates a </span><code 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 style="font-family:Helvetica,arial,sans-serif;font-size:14px"> file similar to :</span></div><div><pre 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 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">github.com/foo/bar</a> &quot;v1.2.3&quot;
<a href="http://github.com/foo/baz">http://github.com/foo/baz</a> &quot;v1.0.0&quot;
../local/git/repo &quot;v3.4.4&quot;
</code></pre></div><div><span style="font-family:Helvetica,arial,sans-serif;font-size:14px">lock file will only be re-modified by </span><code 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 style="font-family:Helvetica,arial,sans-serif;font-size:14px"> if</span> <code 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 style="font-family:Helvetica,arial,sans-serif;font-size:14px"> is modified by the user.</span></div><div><code 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 style="font-family:Helvetica,arial,sans-serif;font-size:14px"> always ignores the lock file and uses local state of Packages dir / </span><code 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><code 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></code></div><div><span 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><span style="background-color:transparent">To lock the current state of Packages user can run </span><span style="font-family:Helvetica,arial,sans-serif;font-size:14px"> </span><code 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 style="font-family:Helvetica,arial,sans-serif;font-size:14px"> which might result something similar to </span></div><div><div><pre 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 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">github.com/foo/bar</a> &quot;248441ff375a19c4365d00d6b0706e11173074f6&quot;
<a href="http://github.com/foo/baz">http://github.com/foo/baz</a> &quot;v1.0.0&quot;
../local/git/repo &quot;v3.4.4&quot;
</code></pre></div></div><div><span 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></div><div><span style="font-family:Helvetica,arial,sans-serif;font-size:14px;background-color:transparent"><br></span></div><div><font face="Helvetica, arial, sans-serif"><span style="font-size:14px">3. A command like </span></font><code 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 style="font-family:Helvetica,arial,sans-serif;font-size:14px"> will always use the lock file to fetch and checkout the dependencies.</span></div><div><span style="font-family:Helvetica,arial,sans-serif;font-size:14px">This is useful because running </span><span style="font-family:Helvetica,arial,sans-serif;font-size:14px"> </span><code 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 style="font-family:Helvetica,arial,sans-serif;font-size:14px"> might give a higher patch or minor version of the dependency.</span></div><div><span style="font-family:Helvetica,arial,sans-serif;font-size:14px"><br></span></div><div><div 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><br></div><div>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 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>None as this would be additional functionality to swift package manager</div><div><h2 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>One alternative is to allow mentioning refs in manifest file while declaring a dependency but as discussed in <a href="https://lists.swift.org/pipermail/swift-build-dev/Week-of-Mon-20151214/000067.html">this</a> thread it might not be the best idea.<br clear="all"><div><br></div>-- <br><div class="gmail_signature">Ankit<br></div></div>
</div></div></div>