main
1<!DOCTYPE html>
2
3<html lang="en">
4
5 <head>
6 <meta charset="utf-8">
7 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
8
9 <link rel="start" href="https://vincent.demeester.fr" />
10
11 <title>Vincent Demeester</title>
12 <link rel="canonical" href="https://vincent.demeester.fr/posts/2012-05-08-gitolite-quick-and-dirty-mirror/">
13 <link href="https://vincent.demeester.fr/index.xml" rel="alternate" type="application/rss+xml" title="Vincent Demeester" />
14
15 <link rel="openid.server" href="https://indieauth.com/openid" />
16 <link rel="openid.delegate" href="http://vincent.demeester.fr/" />
17 <link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
18
19 <link rel="stylesheet" href="/css/screen.css" type="text/css" />
20 <link rel="stylesheet" href="/css/sbrain.css" type="text/css" />
21 <link rel="stylesheet" href="/css/syntax.css" type="text/css" />
22
23 </head>
24
25 <body lang="" class="gray">
26
27
28
29
30
31
32<div id="main-container">
33 <div id="page">
34 <article class="post">
35 <header>
36 <h1 class="emphnext">Gitolite quick and dirty mirror</h1><a href='https://vincent.demeester.fr/posts/2012-05-08-gitolite-quick-and-dirty-mirror/'></a>
37 <address class="signature">
38 <span class="date">Tue, 8 May, 2012</span>
39 <span class="words">(700 Words)</span>
40 </address>
41 <ul class="tag_box inline">
42
43 <li class="category"><a href="/categories/#developement">developement</a></li>
44
45
46
47
48
49 <li class="tag tag-gitolite"><a href="/tags/#gitolite">gitolite<span>1</span></a></li>
50
51
52 <li class="tag tag-git"><a href="/tags/#git">git<span>3</span></a></li>
53
54
55 <li class="tag tag-linux"><a href="/tags/#linux">linux<span>4</span></a></li>
56
57
58 <li class="tag tag-mirror"><a href="/tags/#mirror">mirror<span>1</span></a></li>
59
60
61 <li class="tag tag-github"><a href="/tags/#github">github<span>2</span></a></li>
62
63 <br/>
64
65 </ul>
66 </header>
67
68
69
70
71
72<p>I’m running a gitolite <em>instance</em> on my personal server to manage my repositories
73(personnal, private or public) ; and I am quickly going to share with you how I
74setup a <em>quick and dirty</em> mirror feature.</p>
75
76<p>First, I am using <strong>gitolite 3</strong>. The mirroring we are going to setup is not the
77<em>supported</em> <a href="http://sitaramc.github.com/gitolite/mirroring.html">mirroring <strong>built-in</strong></a>.
78We are going to implement a simplier way to set mirror thing :</p>
79
80<ol>
81<li>Write a custom gitolite command ; the idea is to be able to write <code>git-config</code>
82stuff.</li>
83<li>Write a hook that take a specific <code>git-config</code> (let say <code>mirror.url</code>) and do
84a simple mirroring.</li>
85</ol>
86
87<h1 id="gitolite-commands">Gitolite commands</h1>
88
89<p>Gitolite 3 has been rewritten to be more flexible : <a href="http://sitaramc.github.com/gitolite/g3why.html">Why a completely new version</a>.
90The rewrite made it really easy to extend gitolite. <del>I’ve fork <a href="https://github.com/vdemeester/gitolite">gitolite</a> on github</del>
91I’ve created a <a href="http://github.com/vdemeester/vdemeester-gitolite-local-code">repository git</a>
92to easily add commands to my gitolite instance via <em>local code</em>. The gitolite command I wrote is
93a quick and dirty script in shell to add <code>git config</code>. The source should speek
94for itself ; It <em>should</em> include some way to check if the given config is not
95already present in the <code>gitolite-admin</code> configuration file — and so might be
96rewritten in <code>Perl</code>.</p>
97
98<p>The command is <code>write-git-config</code> because a <code>git-config</code> command already exists
99in the built-in commands.</p>
100
101<div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash"><span class="cp">#!/bin/sh
102</span><span class="cp"></span>
103<span class="c1"># Usage: ssh git@host write-git-config <repo> <key> <value></span>
104#
105<span class="c1"># Set git-config value for user-created ("wild") repo.</span>
106
107die<span class="o">()</span> <span class="o">{</span> <span class="nb">echo</span> <span class="s2">"</span><span class="nv">$@</span><span class="s2">"</span> ><span class="p">&</span><span class="m">2</span><span class="p">;</span> <span class="nb">exit</span> <span class="m">1</span><span class="p">;</span> <span class="o">}</span>
108usage<span class="o">()</span> <span class="o">{</span> perl -lne <span class="s1">'print substr($_, 2) if /^# Usage/../^$/'</span> < <span class="nv">$0</span><span class="p">;</span> <span class="nb">exit</span> <span class="m">1</span><span class="p">;</span> <span class="o">}</span>
109<span class="o">[</span> -z <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">]</span> <span class="o">&&</span> <span class="o">[</span> -z <span class="s2">"</span><span class="nv">$2</span><span class="s2">"</span> <span class="o">]</span> <span class="o">&&</span> <span class="o">[</span> -z <span class="s2">"</span><span class="nv">$3</span><span class="s2">"</span> <span class="o">]</span> <span class="o">&&</span> usage
110<span class="o">[</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="o">=</span> <span class="s2">"-h"</span> <span class="o">]</span> <span class="o">&&</span> usage
111<span class="o">[</span> -z <span class="s2">"</span><span class="nv">$GL_USER</span><span class="s2">"</span> <span class="o">]</span> <span class="o">&&</span> die GL_USER not <span class="nb">set</span>
112
113<span class="c1"># ----------------------------------------------------------------------</span>
114<span class="nv">repo</span><span class="o">=</span><span class="nv">$1</span><span class="p">;</span> <span class="nb">shift</span>
115<span class="nv">key</span><span class="o">=</span><span class="nv">$1</span><span class="p">;</span> <span class="nb">shift</span>
116<span class="nv">value</span><span class="o">=</span><span class="nv">$1</span><span class="p">;</span> <span class="nb">shift</span>
117
118<span class="c1"># this shell script takes arguments that are completely under the user's</span>
119<span class="c1"># control, so make sure you quote those suckers!</span>
120
121<span class="k">if</span> gitolite query-rc -q WRITER_CAN_UPDATE_DESC
122<span class="k">then</span>
123 gitolite access -q <span class="s2">"</span><span class="nv">$repo</span><span class="s2">"</span> <span class="nv">$GL_USER</span> W any <span class="o">||</span> die You are not authorised
124<span class="k">else</span>
125 gitolite creator <span class="s2">"</span><span class="nv">$repo</span><span class="s2">"</span> <span class="nv">$GL_USER</span> <span class="o">||</span> die You are not authorised
126<span class="k">fi</span>
127
128<span class="c1"># if it passes, $repo is a valid repo name so it is known to contain only sane</span>
129<span class="c1"># characters. This is because 'gitolite creator' return true only if there</span>
130<span class="c1"># *is* a repo of that name and it has a gl-creator file that contains the same</span>
131<span class="c1"># text as $GL_USER.</span>
132
133<span class="nv">configfile</span><span class="o">=</span><span class="sb">`</span>gitolite query-rc GL_REPO_BASE<span class="sb">`</span>/<span class="s2">"</span><span class="nv">$repo</span><span class="s2">"</span>.git/config
134
135git config --file <span class="s2">"</span><span class="nv">$configfile</span><span class="s2">"</span> <span class="s2">"</span><span class="nv">$key</span><span class="s2">"</span> <span class="s2">"</span><span class="nv">$value</span><span class="s2">"</span></code></pre></div>
136
137<h1 id="gitolite-hooks">Gitolite hooks</h1>
138
139<p>The next step is to write a quick <code>post-receive</code> hook that check if there is a
140certain <code>git-config</code> entry and run <code>git push --mirror</code>. The file is in
141<code>$HOME/.gitolite/hooks/common/post-receive</code> ; you could add a better system to
142hooks (to be able to add “dynamic” hooks, …).</p>
143
144<div class="highlight"><pre class="chroma"><code class="language-bash" data-lang="bash"><span class="cp">#!/bin/sh
145</span><span class="cp"></span>
146<span class="c1"># Simple gitolite mirroring</span>
147
148<span class="c1"># flush STDIN coming from git, because gitolite's own post-receive.mirrorpush</span>
149<span class="c1"># script does the same thing</span>
150<span class="o">[</span> -t <span class="m">0</span> <span class="o">]</span> <span class="o">||</span> cat >/dev/null
151
152<span class="o">[</span> -z <span class="s2">"</span><span class="nv">$GL_REPO</span><span class="s2">"</span> <span class="o">]</span> <span class="o">&&</span> die GL_REPO not <span class="nb">set</span>
153
154<span class="nv">target</span><span class="o">=</span><span class="sb">`</span>git config --get mirror.url<span class="sb">`</span>
155<span class="o">[</span> -z <span class="s2">"</span><span class="nv">$target</span><span class="s2">"</span> <span class="o">]</span> <span class="o">&&</span> <span class="nb">exit</span> <span class="m">0</span>
156
157<span class="c1"># Support a REPO variable for wildcard mirrors</span>
158<span class="nv">gl_repo_escaped</span><span class="o">=</span><span class="k">$(</span><span class="nb">echo</span> <span class="nv">$GL_REPO</span> <span class="p">|</span> sed <span class="s1">'s/\//\\\//g'</span><span class="k">)</span>
159<span class="nv">target</span><span class="o">=</span><span class="k">$(</span><span class="nb">echo</span> <span class="nv">$target</span> <span class="p">|</span> sed -e <span class="s2">"s/REPO/</span><span class="nv">$gl_repo_escaped</span><span class="s2">/g"</span><span class="k">)</span>
160
161<span class="c1"># Do the mirror push</span>
162git push --mirror <span class="nv">$target</span></code></pre></div>
163
164<p>The next, and final step is to run <code>gitolite compile</code> to update links to hooks
165for every repositories.</p>
166
167<h1 id="for-real">For real</h1>
168
169<p>And finaly, this is the final step you’ll do.</p>
170
171<pre><code>$ ssh git@host write-git-config vincent/vcsh-home mirror.url git@github.com:vdemeester/vcsh-home.git
172$ git push
173Counting objects: 5, done.
174Delta compression using up to 2 threads.
175Compressing objects: 100% (3/3), done.
176Writing objects: 100% (3/3), 294 bytes, done.
177Total 3 (delta 2), reused 0 (delta 0)
178remote: To git@github.com:vdemeester/vcsh-home.git
179remote: 65681a8..701c990 master -> master
180To git@host:vincent/vcsh-home.git
181 65681a8..701c990 master -> master
182</code></pre>
183
184<p>And that should be it !</p>
185
186<p><strong>Update 2012/10/04</strong> : Moved from gitolite fork to <em>gitolite local code</em>
187repository.</p>
188
189
190 </article>
191 <hr />
192 <div class="prev-next">
193
194 <a class="paging-link prev" href="/posts/2012-05-13-jekyll-foreman-guard-bundler/" title="Jekyll Forman Guard Bundler">← Previous post</a>
195
196
197
198 <a class="paging-link next" href="/posts/2012-05-07-reinit-and-jekyll/" title="Reinit and Jekyll">Next post →</a>
199
200 </div>
201
202 </div>
203</div>
204
205<footer>
206 <nav>
207
208 <a href="/">home</a>
209 <span class="text-muted"> | </span>
210
211 <a href="/about">about</a>
212 <span class="text-muted"> | </span>
213
214 <a href="/archive">archive</a>
215 <span class="text-muted"> | </span>
216
217 <a href="/categories">categories</a>
218 <span class="text-muted"> | </span>
219
220 <a href="/tags">tags</a>
221 <span class="text-muted"> | </span>
222
223 <a href="https://twitter.com/vdemeest">twitter</a>
224 <span class="text-muted"> | </span>
225
226 <a href="https://github.com/vdemeester">github</a>
227 <span class="text-muted"> | </span>
228
229 <a href="https://vincent.demeester.fr/index.xml">rss</a>
230 </nav>
231 <br/>
232 <address>
233 <span class="copyright">
234 Content and design by Vincent Demeester
235 (<a rel="licence" href="http://creativecommons.org/licenses/by-nc-sa/3.0/">Some rights reserved</a>)
236 </span><br />
237 <span class="engine">
238 Powered by <a href="https://gohugo.io/">Hugo</a> and <a href="https://github.com/kaushalmodi/ox-hugo/">ox-hugo</a>
239 </span>
240 </address>
241</footer>
242</body>
243