Browse files

7d0e48a vref: third rewrite.

  • Loading branch information...
1 parent 30da9e4 commit 1adf34db0484a19a23f7ffd56e2b1531ed620ab9 @sitaramc committed Mar 16, 2013
Showing with 158 additions and 611 deletions.
  1. +1 −1 deleg.html
  2. +73 −58 gitolite.html
  3. +1 −1 master-toc.html
  4. +3 −3 non-core.html
  5. +3 −2 refex.html
  6. +77 −63 vref.html
  7. +0 −483 vref2.html
View
2 deleg.html
@@ -56,7 +56,7 @@
access rules for any other sub-admin's repos.</p>
<p>Delegation is achieved by combining two gitolite features: <a href="deleg.html#subconf">subconf</a> and the
-<a href="vref2.html#NAME">NAME VREF</a>.</p>
+<a href="vref.html#NAME">NAME VREF</a>.</p>
<p>To understand delegation, read both those links then come back to this
example.</p>
View
131 gitolite.html
@@ -1592,8 +1592,9 @@
<pre><code>RW = alice
</code></pre></li>
-<li><p>A refex not starting with <code>refs/</code> is assumed to start with <code>refs/heads/</code>.
-This means normal branches can be conveniently written like this:</p>
+<li><p>A refex not starting with <code>refs/</code> <font color="gray">(or <code>VREF/</code>)</font>
+is assumed to start with <code>refs/heads/</code>. This means normal branches can be
+conveniently written like this:</p>
<pre><code>RW master = alice
# becomes 'refs/heads/master' internally
@@ -3657,70 +3658,84 @@
won't make sense until you read further, but I had to put it up here for folks
who stop reading halfway!</p>
-<p><strong>IMPORTANT</strong>: VREFs is an advanced topic. Be prepared to spend some time
-experimenting to understand things.</p>
+<p>VREFs are a mechanism to add additional constraints to a push.</p>
<p>Here's an example to start you off.</p>
-<pre><code>repo r1
- RW+ = lead_dev dev2 dev3
- - VREF/COUNT/9 = dev2 dev3
- - VREF/COUNT/3/NEWFILES = dev2 dev3
+<p>To disallow junior developers from changing more than five files, or from
+touching the Makefile, you can do this:</p>
+
+<pre><code>repo foo
+ RW+ = @all-devs
+ - VREF/COUNT/5 = @junior-devs
+ - VREF/NAME/Makefile = @junior-devs
</code></pre>
-<p>Now dev2 and dev3 cannot push changes that affect more than 9 files at a time,
-nor those that have more than 3 new files.</p>
+<h3>basic use</h3>
-<h3>rule matching recap</h3>
+<p>Normally, rules deal with branches and tags (which git collectively calls
+"refs"). The "ref" is a property of the push which gitolite checks against
+the set of rules.</p>
-<p>You won't get any joy out of this if you don't understand at least
-<a href="gitolite.html#refex-refex">refex</a>es and how <a href="gitolite.html#rules-rules">rules</a> are processed.</p>
+<p>VREFs ("virtual refs") are other properties of a push that gitolite can be
+told to check, in addition to the normal ref. For example, "this push has
+more than 5 changed files" could be one property. Or "this push changed the
+file called Makefile" could be another.</p>
-<p>But VREFs have one <strong>very important difference</strong> from normal rules. With
-VREFs, a <strong>fallthru results in success</strong>. You'll see why this is more
-convenient as you read on.</p>
+<p>The simplest way to use them is as <em>additional</em> "deny" rules to fail a push
+that might otherwise have passed. This is what the example at the top shows.
+Using VREFs like this does not require any great understanding of, or thinking
+about, how they work under the hood.</p>
-<h3>what is a virtual ref?</h3>
+<h3>advanced use</h3>
-<p>We know that "refs/heads/master" and such are normal git refs that are matched
-against the <a href="gitolite.html#rules-rules">rules</a> to decide if the push is to be allowed or denied.</p>
+<p>More complex uses are possible, but may be harder to understand. You may want
+to experiment with the rules to solidify your understanding as you read this.</p>
-<p>This ref is a "property" of the push.</p>
+<h4>differences from normal refs</h4>
-<p>Similarly, there could be several other "properties" that you may want to test
--- we call them "virtual" refs, or VREFs. For example, "this push has more
-than 5 changed files". Or "this push changed the file called Makefile".</p>
+<p>We know where normal refs (like "refs/heads/master" or "refs/tags/v1.0") come
+from -- they are supplied by git itself when it calls the update hook.</p>
-<h3>how do I use a VREF?</h3>
+<p>VREFs have two differences with normal refs:</p>
-<p>Simple. To disallow junior developers from changing more than five files, or
-from touching the Makefile, you do this:</p>
+<ul>
+<li>gitolite has to generate them somehow
+</li>
+<li>fallthru is success, not failure
+</li>
+</ul>
-<pre><code>repo foo
- RW+ = @all-devs
- - VREF/COUNT/5 = @junior-devs
- - VREF/NAME/Makefile = @junior-devs
-</code></pre>
+<p>Here's some more detail on how it works.</p>
+
+<ul>
+<li><p>first, the normal ("real") ref is checked.</p>
-<h3>where do VREFs come from?</h3>
+<p>As you already know, the push dies if the ref hits a deny rule <strong>or</strong> it
+falls through without hitting an allow rule.</p></li>
+<li><p>next, VREFs are generated and checked one by one.</p>
-<p>From a VREF-maker of course!</p>
+<p>We'll talk about the generaton later, but for the check, a VREF dies (and
+kills the push) <em>only</em> if it meets an explicit deny rule ("-"). Fallthru
+does <em>not</em> cause failure of a VREF.</p>
-<h3>ok who calls the VREF-maker?</h3>
+<p><a href="gitolite.html#refex-refex">refex</a> and <a href="gitolite.html#rules-rules">rules</a> still apply, but several parts of the latter are
+just not relevant to VREFs (since VREFs only run from the update hook).
+Plus of course, as we said, fallthru is not a failure now.</p></li>
+</ul>
-<p>Gitolite. It looks at each rule that contains a VREF rule (there are 2 in the
-above example) and calls VREF-makers for each of them.</p>
+<h4>generating virtual refs</h4>
-<p>This only happens if the "real" ref (e.g., 'refs/heads/master',
-'refs/tags/v1.0', etc) passes the access rules for the user. If the real ref
-fails, the program dies anyway, and none of the VREF stuff runs.</p>
+<p>Gitolite uses the VREF rules themselves to help it generate the virtual refs.</p>
-<h3>how does a VREF-maker work?</h3>
+<p>Specifically, it looks at each rule that contains a VREF (there are 2 in the
+above example) and calls a VREF-maker for each of them.</p>
<p>We'll take the COUNT example rule above.</p>
<p>When gitolite sees that rule, it calls the "COUNT" VREF-maker. Specifically,
-the <code>VREF/COUNT</code> program (See <a href="gitolite.html#cust-cust">here</a> for actual locations on disk).</p>
+this is the <code>VREF/COUNT</code> program (See <a href="gitolite.html#cust-cust">here</a> for actual locations on
+disk).</p>
<p>Gitolite passes it the string "5" as an argument (actually, as the <em>eighth</em>
argument; details later).</p>
@@ -3734,13 +3749,17 @@
<li><p>otherwise it should print nothing.</p></li>
</ul>
-<p>It should exit with an exit code of zero in either case. See next section for
-more.</p>
+<p>It should exit with an exit code of zero in either case.</p>
-<h3>mimicking a plain old update hook</h3>
+<p>If it exits with a non-zero, the push dies regardless of what is printed (see
+"mimicking a plain old update hook" for why this is useful).</p>
-<p>If it exists with a non-zero exit code, then regardless of what it prints or
-does not, the push dies.</p>
+<h3>more details and nuances</h3>
+
+<h4>mimicking a plain old update hook</h4>
+
+<p>If the VREF maker exists with a non-zero exit code, then regardless of what it
+prints or does not, the push dies.</p>
<p>This is just like a plain 'update' hook. Since the first 3 arguments (see
later) are also the same that a plain 'update' hook receives, you can actually
@@ -3756,8 +3775,6 @@
<p>That's it.</p>
-<h3>details</h3>
-
<h4>what if the VREF-maker prints a different VREF?</h4>
<p>Unless you know what you're upto, don't do that.</p>
@@ -7264,22 +7281,20 @@
</li>
<li><a href="gitolite.html#vref-vref">virtual refs</a>
<ul>
-<li>rule matching recap
+<li>basic use
</li>
-<li>what is a virtual ref?
-</li>
-<li>how do I use a VREF?
-</li>
-<li>where do VREFs come from?
+<li>advanced use
+<ul>
+<li>differences from normal refs
</li>
-<li>ok who calls the VREF-maker?
+<li>generating virtual refs
</li>
-<li>how does a VREF-maker work?
+</ul>
</li>
+<li>more details and nuances
+<ul>
<li>mimicking a plain old update hook
</li>
-<li>details
-<ul>
<li>what if the VREF-maker prints a different VREF?
</li>
<li><a href="gitolite.html#vref-vref-fallthru">why is fallthru considered success with VREFs</a>
View
2 master-toc.html
@@ -260,7 +260,7 @@
</li>
<li><a href="deleg.html">delegating</a> access control responsibilities
<ul>
-<li>(<a href="vref2.html#NAME">link</a>: the NAME VREF)
+<li>(<a href="vref.html#NAME">link</a>: the NAME VREF)
</li>
<li>the <a href="deleg.html#subconf">subconf</a> command
</li>
View
6 non-core.html
@@ -250,7 +250,7 @@
details. However, here's a list of VREFs shipped with gitolite:</p>
<ul>
-<li><em><a href="vref2.html#COUNT">COUNT</a></em> -- restrict pushes by number of changed or new files pushed
+<li><em><a href="vref.html#COUNT">COUNT</a></em> -- restrict pushes by number of changed or new files pushed
</li>
<li><em>EMAIL-CHECK</em> -- check if all new commits are authored by the person pushing
</li>
@@ -260,7 +260,7 @@
<li><em>MAX_NEWBIN_SIZE</em> -- restrict by size of new binary files (helps catch
people checking in random PDFs, JARs, WARs, etc.)
</li>
-<li><strong><a href="vref2.html#NAME">NAME</a></strong> -- restrict pushes by dir/file name
+<li><strong><a href="vref.html#NAME">NAME</a></strong> -- restrict pushes by dir/file name
</li>
<li><a href="non-core.html#partial-copy">partial-copy</a> -- simulated read control for branches (in combination
with the partial-copy trigger)
@@ -269,7 +269,7 @@
expressions over refexes, like "refex-1 and not refex-2". (Example:
changing file 'foo' but not on 'master' branch)
</li>
-<li><em><a href="vref2.html#votes">VOTES</a></em> -- voting on commits a la gerrit
+<li><em><a href="vref.html#votes">VOTES</a></em> -- voting on commits a la gerrit
</li>
</ul>
View
5 refex.html
@@ -61,8 +61,9 @@
<pre><code>RW = alice
</code></pre></li>
-<li><p>A refex not starting with <code>refs/</code> is assumed to start with <code>refs/heads/</code>.
-This means normal branches can be conveniently written like this:</p>
+<li><p>A refex not starting with <code>refs/</code> <font color="gray">(or <code>VREF/</code>)</font>
+is assumed to start with <code>refs/heads/</code>. This means normal branches can be
+conveniently written like this:</p>
<pre><code>RW master = alice
# becomes 'refs/heads/master' internally
View
140 vref.html
@@ -54,53 +54,48 @@
won't make sense until you read further, but I had to put it up here for folks
who stop reading halfway!</p>
-<p><strong>IMPORTANT</strong>: VREFs is an advanced topic. Be prepared to spend some time
-experimenting to understand things.</p>
-
<hr />
<ul>
<li><a href="vref.html">virtual refs</a>
<ul>
-<li>rule matching recap
-</li>
-<li>what is a virtual ref?
+<li>basic use
</li>
-<li>how do I use a VREF?
-</li>
-<li>where do VREFs come from?
+<li>advanced use
+<ul>
+<li>differences from normal refs
</li>
-<li>ok who calls the VREF-maker?
+<li>generating virtual refs
</li>
-<li>how does a VREF-maker work?
+</ul>
</li>
+<li>more details and nuances
+<ul>
<li>mimicking a plain old update hook
</li>
-<li>details
-<ul>
<li>what if the VREF-maker prints a different VREF?
</li>
-<li><a href="vref2.html#vref-fallthru">why is fallthru considered success with VREFs</a>
+<li><a href="vref.html#vref-fallthru">why is fallthru considered success with VREFs</a>
</li>
<li>what if the VREF-maker prints something that's not even a VREF?
</li>
<li>in what order are VREF-makers called?
</li>
-<li><a href="vref2.html#vref-args">what arguments are passed to the vref-maker?</a>
+<li><a href="vref.html#vref-args">what arguments are passed to the vref-maker?</a>
</li>
</ul>
</li>
<li>VREF-makers shipped with gitolite
<ul>
-<li><a href="vref2.html#NAME">restricting pushes by dir/file name</a>
+<li><a href="vref.html#NAME">restricting pushes by dir/file name</a>
</li>
-<li><a href="vref2.html#COUNT">number of changed or new files</a>
+<li><a href="vref.html#COUNT">number of changed or new files</a>
</li>
<li>advanced filetype detection
</li>
<li>checking author email
</li>
-<li><a href="vref2.html#votes">voting on commits</a>
+<li><a href="vref.html#votes">voting on commits</a>
</li>
</ul>
</li>
@@ -118,69 +113,86 @@
<hr />
+<p>VREFs are a mechanism to add additional constraints to a push.</p>
+
<p>Here's an example to start you off.</p>
-<pre><code>repo r1
- RW+ = lead_dev dev2 dev3
- - VREF/COUNT/9 = dev2 dev3
- - VREF/COUNT/3/NEWFILES = dev2 dev3
-</code></pre>
+<p>To disallow junior developers from changing more than five files, or from
+touching the Makefile, you can do this:</p>
-<p>Now dev2 and dev3 cannot push changes that affect more than 9 files at a time,
-nor those that have more than 3 new files.</p>
+<pre><code>repo foo
+ RW+ = @all-devs
+ - VREF/COUNT/5 = @junior-devs
+ - VREF/NAME/Makefile = @junior-devs
+</code></pre>
<hr />
-<h2>rule matching recap</h2>
+<h2>basic use</h2>
-<p>You won't get any joy out of this if you don't understand at least
-<a href="refex.html">refex</a>es and how <a href="rules.html">rules</a> are processed.</p>
+<p>Normally, rules deal with branches and tags (which git collectively calls
+"refs"). The "ref" is a property of the push which gitolite checks against
+the set of rules.</p>
-<p>But VREFs have one <strong>very important difference</strong> from normal rules. With
-VREFs, a <strong>fallthru results in success</strong>. You'll see why this is more
-convenient as you read on.</p>
+<p>VREFs ("virtual refs") are other properties of a push that gitolite can be
+told to check, in addition to the normal ref. For example, "this push has
+more than 5 changed files" could be one property. Or "this push changed the
+file called Makefile" could be another.</p>
-<h2>what is a virtual ref?</h2>
+<p>The simplest way to use them is as <em>additional</em> "deny" rules to fail a push
+that might otherwise have passed. This is what the example at the top shows.
+Using VREFs like this does not require any great understanding of, or thinking
+about, how they work under the hood.</p>
-<p>We know that "refs/heads/master" and such are normal git refs that are matched
-against the <a href="rules.html">rules</a> to decide if the push is to be allowed or denied.</p>
+<h2>advanced use</h2>
-<p>This ref is a "property" of the push.</p>
+<p>More complex uses are possible, but may be harder to understand. You may want
+to experiment with the rules to solidify your understanding as you read this.</p>
-<p>Similarly, there could be several other "properties" that you may want to test
--- we call them "virtual" refs, or VREFs. For example, "this push has more
-than 5 changed files". Or "this push changed the file called Makefile".</p>
+<h3>differences from normal refs</h3>
-<h2>how do I use a VREF?</h2>
+<p>We know where normal refs (like "refs/heads/master" or "refs/tags/v1.0") come
+from -- they are supplied by git itself when it calls the update hook.</p>
-<p>Simple. To disallow junior developers from changing more than five files, or
-from touching the Makefile, you do this:</p>
+<p>VREFs have two differences with normal refs:</p>
-<pre><code>repo foo
- RW+ = @all-devs
- - VREF/COUNT/5 = @junior-devs
- - VREF/NAME/Makefile = @junior-devs
-</code></pre>
+<ul>
+<li>gitolite has to generate them somehow
+</li>
+<li>fallthru is success, not failure
+</li>
+</ul>
-<h2>where do VREFs come from?</h2>
+<p>Here's some more detail on how it works.</p>
-<p>From a VREF-maker of course!</p>
+<ul>
+<li><p>first, the normal ("real") ref is checked.</p>
+
+<p>As you already know, the push dies if the ref hits a deny rule <strong>or</strong> it
+falls through without hitting an allow rule.</p></li>
+<li><p>next, VREFs are generated and checked one by one.</p>
-<h2>ok who calls the VREF-maker?</h2>
+<p>We'll talk about the generaton later, but for the check, a VREF dies (and
+kills the push) <em>only</em> if it meets an explicit deny rule ("-"). Fallthru
+does <em>not</em> cause failure of a VREF.</p>
+
+<p><a href="refex.html">refex</a> and <a href="rules.html">rules</a> still apply, but several parts of the latter are
+just not relevant to VREFs (since VREFs only run from the update hook).
+Plus of course, as we said, fallthru is not a failure now.</p></li>
+</ul>
-<p>Gitolite. It looks at each rule that contains a VREF rule (there are 2 in the
-above example) and calls VREF-makers for each of them.</p>
+<h3>generating virtual refs</h3>
-<p>This only happens if the "real" ref (e.g., 'refs/heads/master',
-'refs/tags/v1.0', etc) passes the access rules for the user. If the real ref
-fails, the program dies anyway, and none of the VREF stuff runs.</p>
+<p>Gitolite uses the VREF rules themselves to help it generate the virtual refs.</p>
-<h2>how does a VREF-maker work?</h2>
+<p>Specifically, it looks at each rule that contains a VREF (there are 2 in the
+above example) and calls a VREF-maker for each of them.</p>
<p>We'll take the COUNT example rule above.</p>
<p>When gitolite sees that rule, it calls the "COUNT" VREF-maker. Specifically,
-the <code>VREF/COUNT</code> program (See <a href="cust.html">here</a> for actual locations on disk).</p>
+this is the <code>VREF/COUNT</code> program (See <a href="cust.html">here</a> for actual locations on
+disk).</p>
<p>Gitolite passes it the string "5" as an argument (actually, as the <em>eighth</em>
argument; details later).</p>
@@ -194,13 +206,17 @@
<li><p>otherwise it should print nothing.</p></li>
</ul>
-<p>It should exit with an exit code of zero in either case. See next section for
-more.</p>
+<p>It should exit with an exit code of zero in either case.</p>
-<h2>mimicking a plain old update hook</h2>
+<p>If it exits with a non-zero, the push dies regardless of what is printed (see
+"mimicking a plain old update hook" for why this is useful).</p>
-<p>If it exists with a non-zero exit code, then regardless of what it prints or
-does not, the push dies.</p>
+<h2>more details and nuances</h2>
+
+<h3>mimicking a plain old update hook</h3>
+
+<p>If the VREF maker exists with a non-zero exit code, then regardless of what it
+prints or does not, the push dies.</p>
<p>This is just like a plain 'update' hook. Since the first 3 arguments (see
later) are also the same that a plain 'update' hook receives, you can actually
@@ -216,8 +232,6 @@
<p>That's it.</p>
-<h2>details</h2>
-
<h3>what if the VREF-maker prints a different VREF?</h3>
<p>Unless you know what you're upto, don't do that.</p>
View
483 vref2.html
@@ -1,483 +0,0 @@
-
-<head>
- <title>virtual refs</title>
-<style>
- body { background: #fff; text-color: #000; margin-left: 40px; font-size: 0.9em; font-family: sans-serif; max-width: 800px; }
- h1 { background: #ffb; text-color: #000; margin-left: -30px; border-top: 5px solid #ccc; }
- h2 { background: #ffb; text-color: #000; margin-left: -20px; border-top: 3px solid #ddd; }
- h3 { background: #ffb; text-color: #000; margin-left: -10px; }
- h4 { background: #ffb; text-color: #000; }
- code { font-size: 1.1em; background: #ddf; text-color: #000; }
- pre { margin-left: 2em; background: #ddf; text-color: #000; }
- pre code { font-size: 1.1em; background: #ddf; text-color: #000; }
-</style>
-<style>
- body{counter-reset: section}
- h1{counter-reset: sub-section}
- h2{counter-reset: composite}
- h3{counter-reset: detail}
-
- h1:before {
- counter-increment: section;
- content: counter(section) ". ";
- }
- h2:before {
- counter-increment: sub-section;
- content: counter(section) "." counter(sub-section) ". ";
- }
- h3:before {
- counter-increment: composite;
- content: counter(section) "." counter(sub-section) "." counter(composite) ". ";
- }
- h4:before {
- counter-increment: detail;
- content: counter(section) "." counter(sub-section) "." counter(composite) "." counter(detail) ". ";
- }
-</style>
-</head>
-
-<p style="text-align:center">
- <a href="master-toc.html">master TOC</a>
-|
- <a href="index.html">main page</a>
-|
- <a href="gitolite.html">single-page</a>
-|
- <a href="index.html#license">license</a>
-</p>
-<p style="text-align:center">
-<font color="gray">This is for gitolite "g3"; for older (v2.x) documentation click <a href="http://sitaramc.github.com/gitolite/g2/master-toc.html">here</a></font>
-</p>
-<h1>virtual refs</h1>
-
-<p><strong>IMPORTANT</strong>: fallthru is success in VREFs, unlike the normal refs. That
-won't make sense until you read further, but I had to put it up here for folks
-who stop reading halfway!</p>
-
-<p><strong>IMPORTANT</strong>: VREFs is an advanced topic. Be prepared to spend some time
-experimenting to understand things.</p>
-
-<hr />
-
-<ul>
-<li><a href="vref2.html">virtual refs</a>
-<ul>
-<li>basics
-</li>
-<li>details
-<ul>
-<li>differences from normal refs
-</li>
-<li>generating virtual refs
-</li>
-</ul>
-</li>
-<li>more details and nuances
-<ul>
-<li>mimicking a plain old update hook
-</li>
-<li>what if the VREF-maker prints a different VREF?
-</li>
-<li><a href="vref2.html#vref-fallthru">why is fallthru considered success with VREFs</a>
-</li>
-<li>what if the VREF-maker prints something that's not even a VREF?
-</li>
-<li>in what order are VREF-makers called?
-</li>
-<li><a href="vref2.html#vref-args">what arguments are passed to the vref-maker?</a>
-</li>
-</ul>
-</li>
-<li>VREF-makers shipped with gitolite
-<ul>
-<li><a href="vref2.html#NAME">restricting pushes by dir/file name</a>
-</li>
-<li><a href="vref2.html#COUNT">number of changed or new files</a>
-</li>
-<li>advanced filetype detection
-</li>
-<li>checking author email
-</li>
-<li><a href="vref2.html#votes">voting on commits</a>
-</li>
-</ul>
-</li>
-<li>other ideas -- code welcome!
-<ul>
-<li>"no non-merge first-parents"
-</li>
-<li>other ideas for VREFs
-</li>
-</ul>
-</li>
-</ul>
-</li>
-</ul>
-
-<hr />
-
-<p>Here's an example to start you off.</p>
-
-<p>To disallow junior developers from changing more than five files, or from
-touching the Makefile, you can do this:</p>
-
-<pre><code>repo foo
- RW+ = @all-devs
- - VREF/COUNT/5 = @junior-devs
- - VREF/NAME/Makefile = @junior-devs
-</code></pre>
-
-<hr />
-
-<h2>basics</h2>
-
-<p>Until now, you've seen rules deal with branches and tags (which git
-collectively calls "refs"). The "ref" is a property of the push which
-gitolite checks against a set of rules.</p>
-
-<p>VREFs ("virtual refs") are other properties of a push that gitolite can be
-told to check, in addition to the normal ref. For example, "this push has
-more than 5 changed files" could be one property. Or "this push changed the
-file called Makefile" could be another.</p>
-
-<p>The simplest way to use them is as additional "deny" rules that can be used to
-fail a push that might otherwise have passed. This is what the example at the
-top shows. Using VREFs like this does not require any great understanding of
-how they work under the hood.</p>
-
-<p>More complex uses are possible, but only if you understand how they work at a
-deeper level. If you do that, note that with VREFs, <strong>fallthru results in
-success</strong>, not failure as it does with normal refs. You'll see why this is
-more convenient as you read on.</p>
-
-<h2>details</h2>
-
-<h3>differences from normal refs</h3>
-
-<p>We know where normal refs (like "refs/heads/master" or "refs/tags/v1.0") come
-from -- they are supplied by git itself when it calls the update hook. This
-ref is then run through all the rules, and if it is explicitly denied or falls
-through the end, the push dies.</p>
-
-<p>VREFs have two differences with normal refs:</p>
-
-<ul>
-<li>they don't come from outside; gitolite has to generate them internally
-</li>
-<li>fallthru is success, not failure for reasons explained later
-</li>
-</ul>
-
-<h3>generating virtual refs</h3>
-
-<p>Gitolite uses a trick to do this, so pay attention. It uses the VREF rules
-themselves to help it generate the virtual refs. Specifically, it looks at
-each rule that contains a VREF (there are 2 in the above example) and calls a
-VREF-maker for each of them.</p>
-
-<p>We'll take the COUNT example rule above.</p>
-
-<p>When gitolite sees that rule, it calls the "COUNT" VREF-maker. Specifically,
-this is the <code>VREF/COUNT</code> program (See <a href="cust.html">here</a> for actual locations on
-disk).</p>
-
-<p>Gitolite passes it the string "5" as an argument (actually, as the <em>eighth</em>
-argument; details later).</p>
-
-<p>The program (which can be written in any language) is expected to do one of
-two things:</p>
-
-<ul>
-<li><p>if the condition is satisfied (i.e., there <em>are</em> more than 5 files in this
-push), it should print <code>VREF/COUNT/5</code> to STDOUT.</p></li>
-<li><p>otherwise it should print nothing.</p></li>
-</ul>
-
-<p>It should exit with an exit code of zero in either case. If it does exit with
-a non-zero, the push dies regardless of what is printed (see "mimicking a
-plain old update hook" for why this is useful).</p>
-
-<h2>more details and nuances</h2>
-
-<h3>mimicking a plain old update hook</h3>
-
-<p>If the VREF maker exists with a non-zero exit code, then regardless of what it
-prints or does not, the push dies.</p>
-
-<p>This is just like a plain 'update' hook. Since the first 3 arguments (see
-later) are also the same that a plain 'update' hook receives, you can actually
-use any existing update hook as a VREF-maker.</p>
-
-<p>To repurpose an existing update hook as a VREF-maker, just copy it to the VREF
-directory (again, see <a href="cust.html">here</a> for actual locations on disk). Then add
-this rule to your repos:</p>
-
-<pre><code>repo foo # or maybe even 'repo @all'
- - VREF/my-update-hook = @all
-</code></pre>
-
-<p>That's it.</p>
-
-<h3>what if the VREF-maker prints a different VREF?</h3>
-
-<p>Unless you know what you're upto, don't do that.</p>
-
-<p>But it's allowed and the behaviour is defined. The VREF-maker for the NAME
-VREF is a good example. It ignores the arguments and just makes VREFs out of
-the name of every file that was changed in the push.</p>
-
-<p>Here's another example. Consider the problem of not allowing pushes at
-specific times. Let's say repo 'foo' cannot be pushed between 4 and 7pm, and
-repo 'bar' can only be pushed before 9am. And of course all this only applies
-to the junior developers, the poor guys!</p>
-
-<pre><code>repo foo
- RW+ = @all
- - VREF/Hour/16 = @junior-devs
- - VREF/Hour/17 = @junior-devs
- - VREF/Hour/18 = @junior-devs
-
-repo bar
- RW+ = @all
- - VREF/Hour/09 = @junior-devs
- - VREF/Hour/1[0-9] = @junior-devs
- - VREF/Hour/2[0-9] = @junior-devs
-</code></pre>
-
-<p>In this example, we write the "Hour" VREF-maker to <em>ignore the argument
-passed</em> and just print <code>VREF/Hour/NN</code> where NN can be between 00 to 23
-inclusive and of course represents the current hour.</p>
-
-<p>if foo is pushed at 6:30pm, the VREF-maker prints VREF/Hour/18, which
-satisfies the third rule and is rejected.</p>
-
-<p>If bar is pushed at, say, 7:20am, the vref printed is VREF/Hour/07, which does
-not match any of the rules. And fallthru is success so it passes.</p>
-
-<h3><a name="vref-fallthru"></a> why is fallthru considered success with VREFs</h3>
-
-<p>Virtual refs are <strong>best used</strong> (1) as additional "deny" rules, performing
-extra checks that core gitolite cannot. You usually want such extra checks
-only for some people.</p>
-
-<p>When fallthru is success, you can simply <em>ignore</em> all the other users (for
-whom such additional checks are not needed).</p>
-
-<p>If fallthru were to be considered 'failure', you'd be forced to add a "success
-rule" like this for <em>every</em> vref you used in this repo, in each case listing
-every user who was not already mentioned in the context of that vref:</p>
-
-<pre><code>RW+ VREF/VREFNAME = @userlist # uggh! what a pain!
-</code></pre>
-
-<p>Worse, since every virtual ref involves calling an external program, many of
-these calls may be wasted.</p>
-
-<p><font color="gray">(1) "best used as..." does not mean "only used as...". For
-example it's perfectly easy to turn this around if, instead of having a list
-of people who <em>do</em> need extra checks, all you have is the complementary
-list:</p>
-
-<pre><code>RW+ VREF/NAME/Makefile = @senior-devs
-- VREF/NAME/Makefile = @all
-</code></pre>
-
-<p></font></p>
-
-<h3>what if the VREF-maker prints something that's not even a VREF?</h3>
-
-<p>The VREF-maker can print anything it wants to STDOUT. Lines not starting with
-<code>VREF/</code> are printed as is (so your VREF-maker can do mostly-normal printing to
-STDOUT). This is especially useful if you've turned an existing update hook
-into a VREF-maker, and it prints stuff but you don't want to touch the code.</p>
-
-<p>For lines starting with <code>VREF/</code>, the first word in each such line will be
-treated as a virtual ref, while the rest, if any, is a message to be added to
-the standard "...DENIED..." message that gitolite will print if that refex
-matches and the rule is a deny rule.</p>
-
-<h3>in what order are VREF-makers called?</h3>
-
-<p>VREF-makers are called in the sequence in which they appear in the conf file.</p>
-
-<p>There are some optimisations to prevent calling the same VREF-maker with the
-same arguments more than once, and the VREF-maker code for the NAME VREF
-(which is special) is called only once regardless of how many times it appears
-but these details should not concern anyone but a developer.</p>
-
-<h3><a name="vref-args"></a> what arguments are passed to the vref-maker?</h3>
-
-<ul>
-<li><p>Arguments <strong>1, 2, 3</strong>: the 'ref', 'oldsha', and 'newsha' that git passed
-to the update hook (see 'man githooks').</p>
-
-<p>This, combined with the fact that non-zero exits are detected, mean that
-you can simply use an existing update.secondary as a VREF-maker as-is, no
-changes needed.</p></li>
-<li><p>Arguments <strong>4 and 5</strong>: the 'oldtree' and 'newtree' SHAs. These are the
-same as the oldsha and newsha values, except if one of them is all-0.
-(indicating a ref creation or deletion). In that case the corresponding
-'tree' SHA is set (by gitolite, as a courtesy) to the special SHA
-<code>4b825dc642cb6eb9a060e54bf8d69288fbee4904</code>, which is the hash of an empty
-tree.</p>
-
-<p>(None of these shenanigans would have been needed if <code>git diff $oldsha
-$newsha</code> would not error out when passed an all-0 SHA.)</p></li>
-<li><p>Argument <strong>6</strong>: the attempted access flag. Typically <code>W</code> or <code>+</code>, but
-could also be <code>C</code>, <code>D</code>, or any of these 4 followed by <code>M</code>. If you have to
-ask what they mean, you haven't read enough gitolite documentation to be
-able to make virtual refs work.</p></li>
-<li><p>Argument <strong>7</strong>: is the entire refex; say <code>VREF/COUNT/3/NEWFILES</code>.</p></li>
-<li><p>Arguments <strong>8 onward</strong>: are the split out (by <code>/</code>) portions of the refex,
-excluding the first two components. In our example they would be <code>3</code>
-followed by <code>NEWFILES</code>.</p></li>
-</ul>
-
-<p>Yes, argument 7 is redundant if you have 8 and 9. It's meant to make it easy
-to write vref-maker scripts in any language. See script examples in source.</p>
-
-<h2>VREF-makers shipped with gitolite</h2>
-
-<h3><a name="NAME"></a> restricting pushes by dir/file name</h3>
-
-<p>The "NAME" VREF allows you to restrict pushes by the names of dirs and files
-changed. (Side note: the NAME VREF is the only one directly implemented
-within the update hook, so you won't find it in the VREF directory).</p>
-
-<p>Here's an example. Say you don't want junior developers pushing changes to
-the Makefile, because it's quite complex:</p>
-
-<pre><code>repo foo
- RW+ = @senior_devs
- RW = @junior_devs
-
- - VREF/NAME/Makefile = @junior_devs
-</code></pre>
-
-<p>When a senior dev pushes, the VREF is not invoked at all. But when a junior
-dev pushes, the VREF is invoked, and it returns a list of files changed <strong>as
-refs</strong>, looking like this:</p>
-
-<pre><code>VREF/NAME/file-1
-VREF/NAME/dir-2/file-3
-...etc...
-</code></pre>
-
-<p>Each of these refs is matched against the access rules. If one of them
-happens to be the Makefile, then the ref returned (VREF/NAME/Makefile) will
-match the deny rule and kill the push.</p>
-
-<p>Another way to use this is when you know what is allowed instead of what is
-not allowed. Let's say the QA person is only allowed to touch a file called
-CHANGELOG and any files in a directory called ReleaseNotes:</p>
-
-<pre><code>repo foo
- RW+ = @senior_devs
- RW = @junior_devs
- RW+ = QA-guy
-
- RW+ VREF/NAME/CHANGELOG = QA-guy
- RW+ VREF/NAME/ReleaseNotes/ = QA-guy
- - VREF/NAME/ = QA-guy
-</code></pre>
-
-<h3><a name="COUNT"></a> number of changed or new files</h3>
-
-<p>The COUNT VREF is used like this:</p>
-
-<pre><code>- VREF/COUNT/9 = @junior-developers
-</code></pre>
-
-<p>In response, if anyone in the user list pushes a commit series that
-changes more than 9 files, a vref of "VREF/COUNT/9" is returned. Gitolite
-uses that as a "ref" to match against all the rules, hits the same rule
-that invoked it, and denies the request.</p>
-
-<p>If the user did not push more than 9 files, the VREF code returns nothing,
-and nothing happens.</p>
-
-<p>COUNT can take one more argument:</p>
-
-<pre><code>- VREF/COUNT/9/NEWFILES = @junior-developers
-</code></pre>
-
-<p>This is the same as before, but have to be more than 9 <em>new</em> files not
-just changed files.</p>
-
-<h3>advanced filetype detection</h3>
-
-<p>Note: this is more for illustration than use; it's rather specific to one of
-the projects I manage but the idea is the important thing.</p>
-
-<p>Sometimes a file has a standard extension (that cannot be 'gitignore'd), but
-it is actually automatically generated. Here's one way to catch it:</p>
-
-<pre><code> - VREF/FILETYPE/AUTOGENERATED = @all
-</code></pre>
-
-<p>You can look at <code>src/VREF/FILETYPE</code> to see how it handles the
-'AUTOGENERATED' option. You could also have a more generic option, like
-perhaps BINARY, and handle that in the FILETYPE vref too.</p>
-
-<h3>checking author email</h3>
-
-<p>Some people want to ensure that "you can only push your own commits".</p>
-
-<p>If you force it on everyone, this is a very silly idea (see "Philosophical
-Notes" section of <code>src/VREF/EMAIL-CHECK</code>).</p>
-
-<p>But there may be value in enforcing it just for the junior developers.</p>
-
-<p>The neat thing is that the existing <code>contrib/update.email-check</code> was just
-copied to <code>src/VREF/EMAIL-CHECK</code> and it works, because VREFs get
-the same first 3 arguments and those are all that it cares about. (Note: you
-have to change one subroutine in that script if you want to use it)</p>
-
-<h3><a name="votes"></a> voting on commits</h3>
-
-<p>Although gitolite can't/won't do the whole "code review + workflow
-enforcement" thing that Gerrit Code Review does, a basic implementation of
-voting on a commit is surprisingly easy. See src/VREF/VOTES for details (and
-note that the actual <em>code</em> is just 2-3 lines; the rest is inline
-documentation).</p>
-
-<h2>other ideas -- code welcome!</h2>
-
-<h3>"no non-merge first-parents"</h3>
-
-<p>Shruggar on #gitolite wanted this. Possible code to implement it would be
-something like this (untested)</p>
-
-<pre><code>[ -z "$(git rev-list --first-parent --no-merges $2..$3)" ]
-</code></pre>
-
-<p>This can be implemented using <code>src/VREF/MERGE-CHECK</code> as a model. That script
-does what the 'M' qualifier does in access rules (see last part of
-<a href="write-types.html">this</a>), although the syntax to be used in conf/gitolite will be
-quite different.</p>
-
-<h3>other ideas for VREFs</h3>
-
-<p>Here are some more ideas:</p>
-
-<ul>
-<li>Number of commits (<code>git rev-list --count $old $new</code>).
-</li>
-<li>Number of binary files in commit (currently I only know to count
-occurrences of <code>Bin</code> in the output of <code>git diff --stat</code>.
-</li>
-<li>Number of <em>new</em> binary files (count <code>Bin 0 -&gt;</code> in <code>git diff --stat</code>
-output).
-</li>
-<li>Time of day/day of week (see example snippet somewhere above).
-</li>
-<li>IP address.
-</li>
-<li>Phase of the moon.
-</li>
-</ul>
-
-<p>Note that pretty much anything that involves <code>$oldsha..$newsha</code> will have to
-deal with the issue that when you push a new tag or branch, the "old" part
-is all 0's, and unless you consider <code>--all</code> existing branches and tags it
-becomes meaningless in terms of "number of new files" etc.</p>

0 comments on commit 1adf34d

Please sign in to comment.