main
  1<!DOCTYPE html>
  2<html lang="en">
  3<head>
  4<!-- Sep 03, 2024 -->
  5<meta charset="utf-8" />
  6<meta name="viewport" content="width=device-width, initial-scale=1" />
  7<title>Gitolite quick and dirty mirror</title>
  8<meta name="author" content="Vincent Demeester" />
  9<meta name="generator" content="Org Mode" />
 10<link rel='icon' type='image/x-icon' href='/images/favicon.ico'/>
 11<meta name='viewport' content='width=device-width, initial-scale=1'>
 12<link rel='stylesheet' href='/css/new.css' type='text/css'/>
 13<link rel='stylesheet' href='/css/syntax.css' type='text/css'/>
 14<link href='/index.xml' rel='alternate' type='application/rss+xml' title='Vincent Demeester' />
 15</head>
 16<body>
 17<main id="content" class="content">
 18<header>
 19<h1 class="title">Gitolite quick and dirty mirror</h1>
 20</header><section id="outline-container-Introduction" class="outline-2">
 21<h2 id="Introduction">Introduction</h2>
 22<div class="outline-text-2" id="text-Introduction">
 23<p>
 24I&rsquo;m running a gitolite <span class="underline">instance</span> on my personal server to manage my repositories
 25(personnal, private or public) ; and I am quickly going to share with you how I setup a
 26<span class="underline">quick and dirty</span> mirror feature.
 27</p>
 28
 29<p>
 30First, I am using <b><b>gitolite 3</b></b>. The mirroring we are going to setup is not the
 31<span class="underline">supported</span> <a href="http://sitaramc.github.com/gitolite/mirroring.html">mirroring <b>built-in</b></a>.  We are going to implement a simplier way to set mirror
 32thing :
 33</p>
 34
 35<ol class="org-ol">
 36<li>Write a custom gitolite command ; the idea is to be able to write <code>git-config</code> stuff.</li>
 37<li>Write a hook that take a specific <code>git-config</code> (let say <code>mirror.url</code>) and do a simple
 38mirroring.</li>
 39</ol>
 40</div>
 41</section>
 42<section id="outline-container-Gitolite%20commands" class="outline-2">
 43<h2 id="Gitolite%20commands">Gitolite commands</h2>
 44<div class="outline-text-2" id="text-Gitolite%20commands">
 45<p>
 46Gitolite 3 has been rewritten to be more flexible : <a href="http://sitaramc.github.com/gitolite/g3why.html">Why a completely new version</a>. The
 47rewrite made it really easy to extend gitolite. <del>I&rsquo;ve fork <a href="https://github.com/vdemeester/gitolite">gitolite</a> on github</del> I&rsquo;ve
 48created a <a href="http://github.com/vdemeester/vdemeester-gitolite-local-code">repository git</a> to easily add commands to my gitolite instance via <span class="underline">local
 49code</span>. The gitolite command I wrote is a quick and dirty script in shell to add <code>git
 50config</code>. The source should speek for itself ; It <span class="underline">should</span> include some way to check if the
 51given config is not already present in the <code>gitolite-admin</code> configuration file — and so
 52might be rewritten in <code>Perl</code>.
 53</p>
 54
 55<p>
 56The command is <code>write-git-config</code> because a <code>git-config</code> command already exists
 57in the built-in commands.
 58</p>
 59
 60<div class="org-src-container">
 61<pre class="src src-bash">#!/bin/sh
 62
 63# Usage:    ssh git@host write-git-config &lt;repo&gt; &lt;key&gt; &lt;value&gt;
 64#
 65# Set git-config value for user-created ("wild") repo.
 66
 67die() { echo "$@" &gt;&amp;2; exit 1; }
 68usage() { perl -lne 'print substr($_, 2) if /^# Usage/../^$/' &lt; $0; exit 1; }
 69[ -z "$1" ] &amp;&amp; [ -z "$2" ] &amp;&amp; [ -z "$3" ] &amp;&amp; usage
 70[ "$1" = "-h" ] &amp;&amp; usage
 71[ -z "$GL_USER" ] &amp;&amp; die GL_USER not set
 72
 73# ----------------------------------------------------------------------
 74repo=$1; shift
 75key=$1; shift
 76value=$1; shift
 77
 78# this shell script takes arguments that are completely under the user's
 79# control, so make sure you quote those suckers!
 80
 81if gitolite query-rc -q WRITER_CAN_UPDATE_DESC
 82then
 83    gitolite access -q "$repo" $GL_USER W any || die You are not authorised
 84else
 85    gitolite creator "$repo" $GL_USER || die You are not authorised
 86fi
 87
 88# if it passes, $repo is a valid repo name so it is known to contain only sane
 89# characters.  This is because 'gitolite creator' return true only if there
 90# *is* a repo of that name and it has a gl-creator file that contains the same
 91# text as $GL_USER.
 92
 93configfile=`gitolite query-rc GL_REPO_BASE`/"$repo".git/config
 94
 95git config --file "$configfile" "$key" "$value"
 96</pre>
 97</div>
 98</div>
 99</section>
100<section id="outline-container-Gitolite%20hooks" class="outline-2">
101<h2 id="Gitolite%20hooks">Gitolite hooks</h2>
102<div class="outline-text-2" id="text-Gitolite%20hooks">
103<p>
104The next step is to write a quick <code>post-receive</code> hook that check if there is a
105certain <code>git-config</code> entry and run <code>git push --mirror</code>. The file is in
106<code>$HOME/.gitolite/hooks/common/post-receive</code> ; you could add a better system to
107hooks (to be able to add &ldquo;dynamic&rdquo; hooks, …).
108</p>
109
110<div class="org-src-container">
111<pre class="src src-bash">
112#!/bin/sh
113
114# Simple gitolite mirroring
115
116# flush STDIN coming from git, because gitolite's own post-receive.mirrorpush
117# script does the same thing
118[ -t 0 ] || cat &gt;/dev/null
119
120[ -z "$GL_REPO" ] &amp;&amp; die GL_REPO not set
121
122target=`git config --get mirror.url`
123[ -z "$target" ] &amp;&amp; exit 0
124
125# Support a REPO variable for wildcard mirrors
126gl_repo_escaped=$(echo $GL_REPO | sed 's/\//\\\//g')
127target=$(echo $target | sed -e "s/REPO/$gl_repo_escaped/g")
128
129# Do the mirror push
130git push --mirror $target
131</pre>
132</div>
133
134<p>
135The next, and final step is to run `gitolite compile` to update links to hooks
136for every repositories.
137</p>
138</div>
139</section>
140<section id="outline-container-For%20real" class="outline-2">
141<h2 id="For%20real">For real</h2>
142<div class="outline-text-2" id="text-For%20real">
143<p>
144And finaly, this is the final step you&rsquo;ll do.
145</p>
146
147<div class="org-src-container">
148<pre class="src src-bash">$ ssh git@host write-git-config vincent/vcsh-home mirror.url git@github.com:vdemeester/vcsh-home.git
149$ git push
150Counting objects: 5, done.
151Delta compression using up to 2 threads.
152Compressing objects: 100% (3/3), done.
153Writing objects: 100% (3/3), 294 bytes, done.
154Total 3 (delta 2), reused 0 (delta 0)
155remote: To git@github.com:vdemeester/vcsh-home.git
156remote:    65681a8..701c990  master -&gt; master
157To git@host:vincent/vcsh-home.git
158   65681a8..701c990  master -&gt; master
159</pre>
160</div>
161
162
163<p>
164And that should be it !
165</p>
166
167<p>
168<span class="underline">Update 2012/10/04</span> : Moved from gitolite fork to <span class="underline">gitolite local code</span>
169repository.
170</p>
171</div>
172</section>
173</main>
174<footer id="postamble" class="status">
175<footer>
176     <small><a href="/" rel="history">Index</a><a href="/sitemap.html">Sitemap</a><a href="https://dl.sbr.pm/">Files</a></small><br/>
177     <small class='questions'>Questions, comments ? Please use my <a href="https://lists.sr.ht/~vdemeester/public-inbox">public inbox</a> by sending a plain-text email to <a href="mailto:~vdemeester/public-inbox@lists.sr.ht">~vdemeester/public-inbox@lists.sr.ht</a>.</small><br/>
178     <small class='copyright'>
179      Content and design by Vincent Demeester
180      (<a rel='licence' href='http://creativecommons.org/licenses/by-nc-sa/3.0/'>Some rights reserved</a>)
181    </small><br />
182</footer>
183</footer>
184</body>
185</html>