<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="227795" data-post-id="227795">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarioFlach" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/MarioFlach/120/24564_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarioFlach
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’ve continued my journey and committed to the project every now and then.</p>
<aside class="onebox allowlistedgeneric" data-onebox-src="https://expireddomains.com/domain/git.limo?utm_source=redi">
  <header class="source">
      <img src="https://expireddomains.com/images/favicon.webp" class="site-icon" alt="" width="205" height="205">

      <a href="https://expireddomains.com/domain/git.limo?utm_source=redi" target="_blank" rel="noopener nofollow ugc">ExpiredDomains.com</a>
  </header>

  <article class="onebox-body">
    <div class="aspect-image" style="--aspect-ratio:690/362;"><img src="https://expireddomains.com/logos/ed.jpg" class="thumbnail" alt="" width="690" height="362"></div>

<h3><a href="https://expireddomains.com/domain/git.limo?utm_source=redi" target="_blank" rel="noopener nofollow ugc">git.limo is for sale! Check it out on ExpiredDomains.com</a></h3>

  <p>Buy git.limo for 100 on GoDaddy via ExpiredDomains.com. This premium expired .limo domain is ideal for establishing a strong online identity.</p>


  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>

<p>So here’s a little update <img src="https://forum.elixirforum.com/images/emoji/apple/grin.png?v=15" title=":grin:" class="emoji" alt=":grin:" loading="lazy" width="20" height="20">.</p>
<h2><a name="p-227795-distributed-setup-1" class="anchor" href="#p-227795-distributed-setup-1" aria-label="Heading link" rel="nofollow"></a>Distributed Setup</h2>
<p>The current version is running on <a href="https://fly.io" rel="noopener nofollow ugc">Fly</a> <img src="https://forum.elixirforum.com/images/emoji/apple/rocket.png?v=15" title=":rocket:" class="emoji" alt=":rocket:" loading="lazy" width="20" height="20">. I’ve got a small cluster (two nodes: <em>FRA</em>, <em>LAX</em>) setup with <code>:libcluster</code> so adding new nodes should work automatically.</p>
<p>Each Fly instance has it own storage attached for storing Git repositories. When a user creates a new repository it is assigned to the local’s node storage and all the Git objects will be stored there:</p>
<p><em>I live in Austria, so my Git repositories are stored on the closest instance running in Frankfurt.</em></p>
<p><em>When accessing one of my repos from the US, the instance in Los Angeles will route all Git commands to the right node.</em></p>
<p>In order to get things working without too much latency, I had to refactor a big chunk of code to batch Git commands together and keep the number of roundtrips between instances low. In the end I’m quite happy with the results <img src="https://forum.elixirforum.com/images/emoji/apple/partying_face.png?v=15" title=":partying_face:" class="emoji" alt=":partying_face:" loading="lazy" width="20" height="20"></p>
<p>Try for yourself:</p>
<ul>
<li><a href="https://git.limo/redrabbit/elixir" rel="noopener nofollow ugc">redrabbit/elixir</a> is running in <em>FRA</em>.</li>
<li><a href="https://git.limo/redrabbit/phoenix" rel="noopener nofollow ugc">redrabbit/phoenix</a> is running in <em>LAX</em>.</li>
</ul>
<h2><a name="p-227795-repository-pools-2" class="anchor" href="#p-227795-repository-pools-2" aria-label="Heading link" rel="nofollow"></a>Repository Pools</h2>
<p>I’ve implemented some kind of distributed routing pool on top of Erlang’s <code>:global</code>.</p>
<p>Here’s a screenshot of the supervision tree:</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://forum.elixirforum.com/uploads/default/original/3X/6/5/650dbc6cf71ae25c9120dcb447a7b99264704676.jpeg" data-download-href="https://forum.elixirforum.com/uploads/default/650dbc6cf71ae25c9120dcb447a7b99264704676" title="image" rel="nofollow"><img src="https://forum.elixirforum.com/uploads/default/optimized/3X/6/5/650dbc6cf71ae25c9120dcb447a7b99264704676_2_690x208.jpeg" alt="image" data-base62-sha1="epXExmsJNJL3W1OB0SXpNNvej4i" width="690" height="208" srcset="https://forum.elixirforum.com/uploads/default/optimized/3X/6/5/650dbc6cf71ae25c9120dcb447a7b99264704676_2_690x208.jpeg, https://forum.elixirforum.com/uploads/default/optimized/3X/6/5/650dbc6cf71ae25c9120dcb447a7b99264704676_2_1035x312.jpeg 1.5x, https://forum.elixirforum.com/uploads/default/original/3X/6/5/650dbc6cf71ae25c9120dcb447a7b99264704676.jpeg 2x" data-dominant-color="DBD6D8"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">image</span><span class="informations">1200×363 22.6 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><p></p>
<p>When a node start’s up, <a href="http://almightycouch.com/gitgud/GitGud.RepoSupervisor.html" rel="noopener nofollow ugc"><code>GitGud.RepoSupervisor</code></a> does a few things:</p>
<ul>
<li>tags the local storage (if not already tagged) and registers the resulting id across the cluster.</li>
<li>starts a <a href="http://almightycouch.com/gitgud/GitGud.RepoStorage.html" rel="noopener nofollow ugc"><code>GitGud.RepoStorage</code></a> worker for handling filesystem operations.</li>
<li>starts a <a href="http://almightycouch.com/gitgud/GitGud.RepoPool.html" rel="noopener nofollow ugc"><code>GitGud.RepoPool</code></a> supervisor for handling Git commands.</li>
</ul>
<p>The <a href="http://almightycouch.com/gitgud/GitGud.Repo.html" rel="noopener nofollow ugc"><code>GitGud.Repo</code></a> schema has a <code>:volume</code> field which points to the storage VOLUME where it data is stored. When creating a repositories it is assigned to the local storage:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">field :volume, :string, autogenerate: {GitGud.RepoStorage, :volume, []}
</code></pre>
<p>With this in mind, let see how we can run Git commands on a specific repository:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">repo = GitGud.RepoQuery.user_repo("redrabbit", "git-limo")
{:ok, agent} = GitRekt.GitRepo.get_agent(repo)
{:ok, head} = GitRekt.GitAgent.head(agent, head)
{:ok, commit} = GitRekt.GitAgent.peel(agent, head)
{:ok, commit_msg} = GitRekt.GitAgent.commit_message(agent, commit)
IO.puts commit_msg
</code></pre>
<p>The above example prints the <em>HEAD</em> commit message for <a href="https://git.limo/redrabbit/git-limo" rel="noopener nofollow ugc">redrabbit/git-limo</a>.</p>
<p>The interesting part here is <a href="http://almightycouch.com/gitgud/GitRekt.GitRepo.html#get_agent/1" rel="noopener nofollow ugc"><code>GitRekt.GitRepo.get_agent/1</code></a> which is implemented by <code>GitGud.Repo</code>:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  defimpl GitRekt.GitRepo, for: GitGud.Repo do
    def get_agent(repo), do: GitGud.RepoPool.checkout(repo)
  end
</code></pre>
<p>As you can see, it rely on <code>GitGud.RepoPool</code> for retrieving a Git agent from the pool on the right node. Let’s dive into it <img src="https://forum.elixirforum.com/images/emoji/apple/diving_mask.png?v=15" title=":diving_mask:" class="emoji" alt=":diving_mask:" loading="lazy" width="20" height="20">.</p>
<p>Internally, the pool can be seen as a <code>DynamicSupervisor</code> of  <code>DynamicSupervisor</code>s. <a href="http://almightycouch.com/gitgud/GitGud.RepoPool.html#checkout/1" rel="noopener nofollow ugc"><code>GitGud.RepoPool.checkout/1</code></a> being the entry-point for fetching agents. It also provides a few nice things:</p>
<ul>
<li>auto scale – grows/shrinks the number of agent processes based on demand.</li>
<li>global cache – agents in a pool share a global ETS table.</li>
<li>round robin – agents are distributed using round-robin.</li>
<li>node aware – a pool will always start on the right node based on the repo’s <code>VOLUME</code>.</li>
</ul>
<h2><a name="p-227795-git-agents-3" class="anchor" href="#p-227795-git-agents-3" aria-label="Heading link" rel="nofollow"></a>Git Agents</h2>
<p>The <a href="http://almightycouch.com/gitgud/GitRekt.GitAgent.html" rel="noopener nofollow ugc"><code>GitRekt.GitAgent</code></a> module is the backbone for running Git commands. While the public API is quite easy to grasp, it hides a lot of complexity.</p>
<p>An agent is basically a wrapper around <a href="http://almightycouch.com/gitgud/GitRekt.Git.html" rel="noopener nofollow ugc"><code>GitRekt.Git</code></a>. Here’s a very basic usage example:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">{:ok, agent} = GitRekt.GitAgent.start_link("path/to/workdir")
{:ok, tags} = GitRekt.GitAgent.tags(agent)
for tag &lt;- tags do
  IO.puts "Tag #{tag.name} -&gt; #{Base.decode16(tag.oid)}"
end
</code></pre>
<p>In the above example, <code>agent</code> is a dedicated process for running Git commands.</p>
<p>Note that it is also allowed to run Git commands in the current process as well:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">{:ok, agent} = GitRekt.Git.repository_open("path/to/workdir")
{:ok, branches} = GitRekt.GitAgent.branches(agent)
for branch &lt;- branches do
  IO.puts "Branch #{branch.name} -&gt; #{Base.decode16(branch.oid)}"
end
</code></pre>
<p>In the above example, <code>agent</code> is a NIF-resource representing a libgit2 repository.</p>
<h4><a name="p-227795-transactions-4" class="anchor" href="#p-227795-transactions-4" aria-label="Heading link" rel="nofollow"></a>Transactions</h4>
<p><code>GitRekt.GitAgent</code> provides support for transactions aka. batching a bunch of Git operations in one call. This is very important when running Git commands on a separate node:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># agent is a PID running on an other node
{:ok, head} = GitRekt.GitAgent.head(agent, head) #1
{:ok, commit} = GitRekt.GitAgent.peel(agent, head) #2
{:ok, commit_msg} = GitRekt.GitAgent.commit_message(agent, commit) #3
IO.puts commit_msg
</code></pre>
<p>Running the above code would make three separate <code>GenServer.call/2</code> resulting in quite some latency. We can fix this by batching the commands in a transaction:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># agent is a PID running on an other node
{:ok, commit_msg} =
  GitRekt.GitAgent.transaction(agent, fn agent -&gt;
    with {:ok, head} &lt;- GitRekt.GitAgent.head(agent, head),
         {:ok, commit} = GitRekt.GitAgent.peel(agent, head) do
      GitRekt.GitAgent.commit_message(agent, commit)
  end)
</code></pre>
<p>In the above example, the three commands are execute in a single call on the dedicated <code>agent</code> process. Reducing the overall latency…</p>
<h4><a name="p-227795-caching-5" class="anchor" href="#p-227795-caching-5" aria-label="Heading link" rel="nofollow"></a>Caching</h4>
<p>An additional feature of <code>GitRekt.GitAgent</code> is caching. When running <a href="http://almightycouch.com/gitgud/GitRekt.GitAgent.html#transaction/3" rel="noopener nofollow ugc"><code>transaction/3</code></a> we can pass a cache key as the 2nd argument:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def commit_info(agent, commit) do
  GitAgent.transaction(agent, {:commit_info, commit.oid}, fn agent -&gt;
    with {:ok, author} &lt;- GitAgent.commit_author(agent, commit),
        {:ok, committer} &lt;- GitAgent.commit_committer(agent, commit),
        {:ok, message} &lt;- GitAgent.commit_message(agent, commit),
        {:ok, parents} &lt;- GitAgent.commit_parents(agent, commit),
        {:ok, timestamp} &lt;- GitAgent.commit_timestamp(agent, commit),
        {:ok, gpg_sig} &lt;- GitAgent.commit_gpg_signature(agent, commit) do
      {:ok, %{
        oid: commit.oid,
        author: author,
        committer: committer,
        message: message,
        parents: Enum.to_list(parents),
        timestamp: timestamp,
        gpg_sig: gpg_sig
      }}
    end
  end)
end
</code></pre>
<p>You may have noticed the <code>{:commit_info, commit.oid}</code> tuple given to <code>transaction/3</code>. This tells the agent that the transaction should be cached using this key.</p>
<p>Calling <code>commit_info/2</code> two times in a row would result in the following log output:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">[debug] [Git Agent] transaction(:commit_info, "b662d32") executed in 361 µs
[debug] [Git Agent] &gt; commit_author(&lt;GitCommit:b662d32&gt;) executed in 6 µs
[debug] [Git Agent] &gt; commit_committer(&lt;GitCommit:b662d32&gt;) executed in 5 µs
[debug] [Git Agent] &gt; commit_message(&lt;GitCommit:b662d32&gt;) executed in 1 µs
[debug] [Git Agent] &gt; commit_parents(&lt;GitCommit:b662d32&gt;) executed in 4 µs
[debug] [Git Agent] &gt; commit_timestamp(&lt;GitCommit:b662d32&gt;) executed in 11 µs
[debug] [Git Agent] &gt; commit_gpg_signature(&lt;GitCommit:b662d32&gt;) executed in 6 µs
[debug] [Git Agent] transaction(:commit_info, "b662d32") executed in ⚡ 3 µs
</code></pre>
<p>We can observe that the first call executes the different commands one by one and cache the result while the second one fetches the result directly from the cache without having to actually run the transaction.</p>
<p>There’s a lot more to tell about <code>GitRekt.GitAgent</code>’s internals (streaming support, mechanism to prevent the garbage collector for deleting NIF-resources, etc.). If you’re interested I can write a small post about it.</p>
<h2><a name="p-227795-liveview-6" class="anchor" href="#p-227795-liveview-6" aria-label="Heading link" rel="nofollow"></a>LiveView</h2>
<p>On the frontend, I’ve managed to introduce Phoenix LiveView and replace all my React/Relay components with a LiveView counterpart. For example, the <a href="http://almightycouch.com/gitgud/GitGud.Web.TreeBrowserLive.html" rel="noopener nofollow ugc"><code>GitGud.Web.TreeBrowserLive</code></a> is used to navigate across a Git repository tree. Here’s a list of all views/components:</p>
<ul>
<li><code>GitGud.Web.BlobHeaderLive</code></li>
<li><code>GitGud.Web.BranchSelectLive</code></li>
<li><code>GitGud.Web.CommentFormLive</code></li>
<li><code>GitGud.Web.CommentLive</code></li>
<li><code>GitGud.Web.CommitDiffLive</code></li>
<li><code>GitGud.Web.CommitLineReviewLive</code></li>
<li><code>GitGud.Web.GlobalSearchLive</code></li>
<li><code>GitGud.Web.IssueEventLive</code></li>
<li><code>GitGud.Web.IssueFormLive</code></li>
<li><code>GitGud.Web.IssueLabelSelectLive</code></li>
<li><code>GitGud.Web.IssueLive</code></li>
<li><code>GitGud.Web.MaintainerSearchFormLive</code></li>
<li><code>GitGud.Web.TreeBrowserLive</code></li>
</ul>
<h2><a name="p-227795-fast-git-backend-server-7" class="anchor" href="#p-227795-fast-git-backend-server-7" aria-label="Heading link" rel="nofollow"></a>Fast Git Backend Server</h2>
<p>I also refactored the Git backend aka. <a href="http://almightycouch.com/gitgud/GitRekt.WireProtocol.html" rel="noopener nofollow ugc"><code>GitRekt.WireProtocol</code></a> which was slow and consumed a lot of resources.</p>
<p>When pushing a repository, the incoming PACK file is now directly streamed to the disk. This increases raw performances about 700% and greatly reduced the amount of RAM and CPU used for the operation.</p>
<p>The performance boost allows to fetch/push across nodes in a cluster setup. When you push via SSH you will send the PACK to the nearest node which is then streamed to the right node in the cluster.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="227795" data-batch-url="/posts/batch_likers">
                        32
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/gitgud-github-clone-entirely-written-in-elixir/12920/52">Post #51</a>
	                </div>
	            </div>
              <div id="likers-container-227795" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="227795"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-most-liked cat-most-liked" title="One of the top 3 liked posts in this thread!"></div>
  </section>
</div>
    <div class="postbit" id="227797" data-post-id="227797">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarioFlach" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/MarioFlach/120/24564_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarioFlach
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Also, the project is sponsored by <a href="https://appsignal.com" rel="noopener nofollow ugc">AppSignal</a> <img src="https://forum.elixirforum.com/images/emoji/apple/heart.png?v=15" title=":heart:" class="emoji" alt=":heart:" loading="lazy" width="20" height="20">. You can check the <a href="https://git.limo/redrabbit/git-limo/tree/appsignal" rel="noopener nofollow ugc">appsignal</a> branch if you’re interested:</p>
<p></p><div class="lightbox-wrapper"><a class="lightbox" href="https://forum.elixirforum.com/uploads/default/original/3X/0/4/0448a52da086fd461fb851f01279229d21b0cf52.jpeg" data-download-href="https://forum.elixirforum.com/uploads/default/0448a52da086fd461fb851f01279229d21b0cf52" title="image" rel="nofollow"><img src="https://forum.elixirforum.com/uploads/default/optimized/3X/0/4/0448a52da086fd461fb851f01279229d21b0cf52_2_676x600.jpeg" alt="image" data-base62-sha1="BTycd6pp4DJkdcshp4KMjoYKhY" width="676" height="600" srcset="https://forum.elixirforum.com/uploads/default/optimized/3X/0/4/0448a52da086fd461fb851f01279229d21b0cf52_2_676x600.jpeg, https://forum.elixirforum.com/uploads/default/optimized/3X/0/4/0448a52da086fd461fb851f01279229d21b0cf52_2_1014x900.jpeg 1.5x, https://forum.elixirforum.com/uploads/default/original/3X/0/4/0448a52da086fd461fb851f01279229d21b0cf52.jpeg 2x" data-dominant-color="FBFBFB"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">image</span><span class="informations">1200×1064 48.1 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><p></p>
<p>You can also check-out the <a href="https://git.limo/redrabbit/git-limo/tree/fly" rel="noopener nofollow ugc">fly</a> branch if you want to deploy on your own Fly instances.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="227797" data-batch-url="/posts/batch_likers">
                        14
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/gitgud-github-clone-entirely-written-in-elixir/12920/53">Post #52</a>
	                </div>
	            </div>
              <div id="likers-container-227797" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="227797"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-most-liked cat-most-liked" title="One of the top 3 liked posts in this thread!"></div>
  </section>
</div>
    <div class="postbit" id="228346" data-post-id="228346">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="EdmondFrank" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/EdmondFrank/120/22859_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  EdmondFrank
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Very cool</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="228346" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/gitgud-github-clone-entirely-written-in-elixir/12920/54">Post #53</a>
	                </div>
	            </div>
              <div id="likers-container-228346" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="228346"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #53"></div>
  </section>
</div>
    <div class="postbit" id="228393" data-post-id="228393">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="mattei" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/mattei/120/23012_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  mattei
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Look, I just want to mention… your taste in library naming is top notch. GitRekt <img src="https://forum.elixirforum.com/images/emoji/apple/joy.png?v=15" title=":joy:" class="emoji" alt=":joy:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="228393" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/gitgud-github-clone-entirely-written-in-elixir/12920/55">Post #54</a>
	                </div>
	            </div>
              <div id="likers-container-228393" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="228393"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #54"></div>
  </section>
</div>
    <div class="postbit" id="228768" data-post-id="228768">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarioFlach" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/MarioFlach/120/24564_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarioFlach
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p><code>GitRekt</code> for the dangerous, not very safe NIF/C code (low-level Git), <code>GitGud</code> for the Elixir counterpart (schemas, supervision tree, etc.) <img src="https://forum.elixirforum.com/images/emoji/apple/face_savoring_food.png?v=15" title=":face_savoring_food:" class="emoji" alt=":face_savoring_food:" loading="lazy" width="20" height="20">.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="228768" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/gitgud-github-clone-entirely-written-in-elixir/12920/57">Post #56</a>
	                </div>
	            </div>
              <div id="likers-container-228768" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="228768"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #56"></div>
  </section>
</div>
    <div class="postbit" id="230571" data-post-id="230571">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarioFlach" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/MarioFlach/120/24564_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarioFlach
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’ve updated to Phoenix 1.6 and LiveView 0.16 and started refactoring my LiveViews to work with the new live session  <img src="https://forum.elixirforum.com/images/emoji/apple/raised_hands.png?v=15" title=":raised_hands:" class="emoji" alt=":raised_hands:" loading="lazy" width="20" height="20">.</p>
<p>Now when browsing a repository, codebase navigation happens with <code>live_redirect/2</code>. This works across most live views and makes the entire user-experience much snappier <img src="https://forum.elixirforum.com/images/emoji/apple/zap.png?v=15" title=":zap:" class="emoji" alt=":zap:" loading="lazy" width="20" height="20">.</p>
<p>I’m really happy for this new feature. While it makes the frontend faster, it also reduces a lot of load on the backend as well. <img src="https://forum.elixirforum.com/images/emoji/apple/heart.png?v=15" title=":heart:" class="emoji" alt=":heart:" loading="lazy" width="20" height="20"></p>
<p>I’ve also add support for <a href="https://github.com/buunguyen/topbar" rel="noopener nofollow ugc">topbar.js</a> in order to show the progression indicator.</p>
<p>You can give it a try here:</p>
<aside class="onebox allowlistedgeneric" data-onebox-src="https://expireddomains.com/domain/git.limo?utm_source=redi">
  <header class="source">
      <img src="https://expireddomains.com/images/favicon.webp" class="site-icon" alt="" width="205" height="205">

      <a href="https://expireddomains.com/domain/git.limo?utm_source=redi" target="_blank" rel="noopener nofollow ugc">ExpiredDomains.com</a>
  </header>

  <article class="onebox-body">
    <div class="aspect-image" style="--aspect-ratio:690/362;"><img src="https://expireddomains.com/logos/ed.jpg" class="thumbnail" alt="" width="690" height="362"></div>

<h3><a href="https://expireddomains.com/domain/git.limo?utm_source=redi" target="_blank" rel="noopener nofollow ugc">git.limo is for sale! Check it out on ExpiredDomains.com</a></h3>

  <p>Buy git.limo for 100 on GoDaddy via ExpiredDomains.com. This premium expired .limo domain is ideal for establishing a strong online identity.</p>


  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>
 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="230571" data-batch-url="/posts/batch_likers">
                        9
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/gitgud-github-clone-entirely-written-in-elixir/12920/58">Post #57</a>
	                </div>
	            </div>
              <div id="likers-container-230571" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="230571"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #57"></div>
  </section>
</div>
    <div class="postbit" id="233495" data-post-id="233495">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="derek-zhou" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/derek-zhou/120/19943_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  derek-zhou
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I always want to have a self-hosted github. So I try the demo server before I deploy one myself. I registered a user at git.limo uploaded a ssh pubkey, however, it is not clear to me how to push. The brief instruction for a newly generated project suggested:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">git remote add origin https://git.limo/derek-zhou/test.git
git push -u origin master
</code></pre>
<p>I’d assume https is for read only access? Anyway, it does not work:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">fatal: unable to access 'https://git.limo/derek-zhou/test.git/': server certificate verification failed. CAfile: none CRLfile: none
</code></pre>
<p>I’ve also tried the github convention:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">git remote add origin git@git.limo:derek-zhou/test.git
</code></pre>
<p>But then it just hangs.</p>
<p>from the git-limo repo linked above it seems to want:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">git remote add origin ssh://derek-zhou@git.limo:1022/derek-zhou/test.git
</code></pre>
<p>But it hangs too. <a class="mention" href="/u/marioflach" rel="nofollow">@MarioFlach</a> ?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="233495" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/gitgud-github-clone-entirely-written-in-elixir/12920/59">Post #58</a>
	                </div>
	            </div>
              <div id="likers-container-233495" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="233495"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #58"></div>
  </section>
</div>
    <div class="postbit" id="233556" data-post-id="233556">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarioFlach" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/MarioFlach/120/24564_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarioFlach
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hi <a class="mention" href="/u/derek-zhou" rel="nofollow">@derek-zhou</a>,</p>
<p>Pushing over HTTPS is supported. You must authenticate with your git.limo username/password thought.</p>
<p>From the error message, it looks like you are missing root certificates somehow. Depending on your OS you might want to install/update them:</p>
<aside class="onebox stackexchange" data-onebox-src="https://stackoverflow.com/questions/35821245/github-server-certificate-verification-failed">
  <header class="source">

      <a href="https://stackoverflow.com/questions/35821245/github-server-certificate-verification-failed" target="_blank" rel="noopener nofollow ugc">stackoverflow.com</a>
  </header>

  <article class="onebox-body">
      <a href="https://stackoverflow.com/users/6023799/torsten-crass" target="_blank" rel="noopener nofollow ugc">
    <img alt="Torsten Crass" src="https://lh5.googleusercontent.com/-Icd1sLYzPm8/AAAAAAAAAAI/AAAAAAAAASI/4LfbxonEi7g/s256-rj/photo.jpg" class="thumbnail onebox-avatar" width="256" height="256">
  </a>

<h4>
  <a href="https://stackoverflow.com/questions/35821245/github-server-certificate-verification-failed" target="_blank" rel="noopener nofollow ugc">github: server certificate verification failed</a>
</h4>

<div class="tags">
  <strong>git, github, debian</strong>
</div>

<div class="date">
  asked by
  
  <a href="https://stackoverflow.com/users/6023799/torsten-crass" target="_blank" rel="noopener nofollow ugc">
    Torsten Crass
  </a>
  on <a href="https://stackoverflow.com/questions/35821245/github-server-certificate-verification-failed" target="_blank" rel="noopener nofollow ugc">11:35PM - 05 Mar 16 UTC</a>
</div>

  </article>

  <div class="onebox-metadata">
    
    
  </div>

  <div style="clear: both"></div>
</aside>

<p>Pushing over SSH is actually also supported. You should be able to authenticate with</p>
<ul>
<li>your git.limo username/password.</li>
<li>your git.limo username and associated SSH key.</li>
</ul>
<p><em>Note that this differs from other Git hosting platforms providing authentication with SSH key only with the ‘git’ user.</em></p>
<p>Now, because <a href="http://Fly.io" rel="noopener nofollow ugc">Fly.io</a> does not allow for external port <code>22</code>, I’m using <code>10022</code>. You should be able to push via:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">git remote add origin ssh://derek-zhou@git.limo:10022/derek-zhou/test.git
</code></pre>
<p>Edit: There is a bug when showing the SSH clone URL for a repository. It shows the internal port <code>1022</code> and not the external one <code>10022</code>… Will fix that.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="233556" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/gitgud-github-clone-entirely-written-in-elixir/12920/60">Post #59</a>
	                </div>
	            </div>
              <div id="likers-container-233556" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="233556"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #59"></div>
  </section>
</div>
    <div class="postbit" id="233559" data-post-id="233559">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="derek-zhou" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/derek-zhou/120/19943_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  derek-zhou
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thanks. After I disable sslverify in git I can push and pull in https. However, there is still something wrong with the ssh push/pull.  SSH itself works with my key:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">derek@mail:~/projects/notes$ ssh derek-zhou@git.limo -p 10022
You are not allowed to start a shell.
Connection to git.limo closed.
</code></pre>
<p>However, git over it does not.<br>
I have seen 2 distinct error messages:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">error: failed to push some refs to 'ssh://derek-zhou@git.limo:10022/derek-zhou/test.git'
</code></pre>
<p>and:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">error: remote unpack failed: %GitRekt.GitError{code: -1, message: "missing trailer at the end of the pack"}
fatal: the remote end hung up unexpectedly
</code></pre>
<p>My git version is a bit old though:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">derek@mail:~/projects/notes$ git --version
git version 2.20.1
</code></pre>
<p>The strange thing is https works.</p>
<p>EDIT:<br>
a newer git version seem to work:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">git version 2.30.2
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="233559" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/gitgud-github-clone-entirely-written-in-elixir/12920/61">Post #60</a>
	                </div>
	            </div>
              <div id="likers-container-233559" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="233559"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #60"></div>
  </section>
</div>
    <div class="postbit" id="233564" data-post-id="233564">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="MarioFlach" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/MarioFlach/120/24564_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  MarioFlach
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<blockquote>
<p>Thanks. After I disable sslverify in git I can push and pull in https.</p>
</blockquote>
<p><img src="https://forum.elixirforum.com/images/emoji/apple/+1.png?v=15" title=":+1:" class="emoji only-emoji" alt=":+1:" loading="lazy" width="20" height="20"></p>
<blockquote>
<p>However, git over SSH does not.</p>
</blockquote>
<p>Yes, so I did rewrite the entire <code>git-receive-pack</code> implementation a while ago to add support for streaming PACK files directly to disk. This was necessary because my previous implementation was way too slow and memory consumption went through the roof.</p>
<p>While testing intensively, I did not have any problems with small or big repositories <img src="https://forum.elixirforum.com/images/emoji/apple/thinking.png?v=15" title=":thinking:" class="emoji" alt=":thinking:" loading="lazy" width="20" height="20">.</p>
<p>Now <a href="http://almightycouch.com/gitgud/GitRekt.WireProtocol.ReceivePack.html" rel="noopener nofollow ugc"><code>GitRekt.WireProtocol.ReceivePack</code></a> is used by both transport protocols HTTP and SSH. So only the transport implementation differs…</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">error: remote unpack failed: %GitRekt.GitError{code: -1, message: "missing trailer at the end of the pack"}
</code></pre>
<p>Interesting. Seems like the last chunk of data is missing somehow. Maybe I have something wrong. Will check and keep you up to date.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="233564" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/gitgud-github-clone-entirely-written-in-elixir/12920/62">Post #61</a>
	                </div>
	            </div>
              <div id="likers-container-233564" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="233564"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #61"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/12920/load_more?page=7">Load more posts (3 remaining)</a>
</div></template></turbo-stream>