<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Dependencies on Roberto Selbach</title><link>https://rselbach.com/tags/dependencies/</link><description>Recent content in Dependencies on Roberto Selbach</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Thu, 08 May 2014 17:55:00 +0000</lastBuildDate><atom:link href="https://rselbach.com/tags/dependencies/index.xml" rel="self" type="application/rss+xml"/><item><title>GOPATH is not a versioning system</title><link>https://rselbach.com/gopath-is-not-a-versioning-system/</link><pubDate>Thu, 08 May 2014 17:55:00 +0000</pubDate><guid>https://rselbach.com/gopath-is-not-a-versioning-system/</guid><description>&lt;p&gt;I reproduced a build failure only after deleting my &lt;code&gt;GOPATH&lt;/code&gt;. That sentence contains most of the problem.&lt;/p&gt;
&lt;p&gt;My normal workspace had this shape:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$GOPATH/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; src/example.com/service
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; src/github.com/some/dependency
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; pkg/darwin_amd64
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; bin
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;go get&lt;/code&gt; fetched the dependency&amp;rsquo;s current source into the expected import path. My machine had an older checkout that still provided a function the service used. A fresh machine fetched a newer revision where the function had changed. The import path named a repository location, not the exact source revision I had tested.&lt;/p&gt;
&lt;p&gt;I briefly considered copying dependencies under a random directory in the service. In 2014 the go command does not define vendoring semantics that make such a copy transparently override the canonical import. Rewriting imports to local copies creates new package identities and a permanent maintenance chore.&lt;/p&gt;
&lt;p&gt;For deployable applications, I record the repository revisions and make the build checkout those revisions into an isolated &lt;code&gt;GOPATH&lt;/code&gt;. Some teams use scripts; others use emerging third-party dependency tools. None is yet the universal answer. Libraries have an even harder choice because pinning their transitive world can conflict with the application assembling the final program.&lt;/p&gt;
&lt;p&gt;I also keep import paths canonical. Relative imports make a package depend on where it happens to sit and behave poorly outside a narrow local experiment.&lt;/p&gt;
&lt;p&gt;The decisive experiment was a new empty workspace:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ mkdir /tmp/service-build
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ GOPATH=/tmp/service-build go get example.com/service/cmd/server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That made every source checkout visible under one disposable root. I recorded &lt;code&gt;git rev-parse HEAD&lt;/code&gt; for each dependency and reproduced the working set by checking out those revisions. The script fails if a revision cannot be fetched; silently falling back to a branch tip would restore the original uncertainty.&lt;/p&gt;
&lt;p&gt;Import-path compatibility remains social rather than solver-enforced. If upstream makes an incompatible change at the same path, the go command cannot select &amp;ldquo;the old API&amp;rdquo; from the import statement. Forking under a new path changes package identity, so values from original and forked packages are distinct even when declarations match.&lt;/p&gt;
&lt;p&gt;For every recorded revision I also keep its canonical repository URL. Import paths can redirect discovery, and repeatability requires knowing both what commit was selected and where the build expects to obtain it.&lt;/p&gt;
&lt;p&gt;GOPATH solves workspace layout and import discovery well. It does not solve repeatable dependency selection. Saying that plainly avoids a lot of mystical advice about cleaning &lt;code&gt;$GOPATH/pkg&lt;/code&gt;. My build was not stale; its input was unspecified.&lt;/p&gt;</description></item></channel></rss>