aboutsummaryrefslogtreecommitdiff
blob: 482da19c35b921d324aa14e5d906c442179aa746 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/perl -s


# To anyone except pingou: these aren't the droids you are looking for.  Move along.


use strict;
use warnings;

# This program is meant to re-compile the access rules (and 'config' or
# 'option' lines) of exacttly ONE repo.

# It expects to run as a gitolite sub-command, that is:
#   gitolite compile-1 $single_repo_conf_file

# It takes one argument: the name of a file that contains the new ruleset you
# want to use.  The file must contain exactly one 'repo' line, with exactly
# one repo name, followed by the rules, configs, and options for that repo in
# the normal gitolite.conf syntax.

# IMPORTANT CAVEATS ARE DISCUSSED AT THE END OF THIS FILE.  PLEASE READ!

# THERE IS NO ERROR CHECKING ON THESE CAVEATS.  PLEASE USE CAREFULLY!

use 5.10.0;
use Data::Dumper;

use lib $ENV{GL_LIBDIR};
use Gitolite::Rc;
use Gitolite::Common;
use Gitolite::Conf;
use Gitolite::Conf::Store;
use Gitolite::Conf::Sugar;

# these variables get populated by the "do" function
our %one_repo;
our %one_config;

my ($cf, $repo) = args();       # conffile from @ARGV, repo from first line of conffile
do_gl_conf($repo);              # read conffile and grab %one_repo and %one_config
my $startseq = startseq();      # get the lowest sequence number from %one_repo and %one_config
parse_and_store($cf, $repo);    # parse the ruleset and write out just the gl-conf file
                                # (this is the only part that uses core gitolite functions)
update_seq($repo, $startseq);   # update gl-conf with adjusted sequence numbers

exit 0;

# ----------------------------------------------------------------------

sub args {
    my $cf = shift @ARGV or _die "need conffile";
    $cf = $ENV{PWD} . "/" . $cf unless $cf =~ m(^/);

    my $t = slurp($cf);
    _die "bad conf file" unless $t =~ /^\s*repo\s+(\S+)\s*$/m;
    my $repo = $1;

    return ($cf, $repo);
}

sub do_gl_conf {
    my $repo = shift;
    _chdir("$rc{GL_REPO_BASE}/$repo.git");
    _die "parse gl-conf failed: " . ( $@ or $! ) unless do "./gl-conf";
    # populates the two "our" variables
}

sub startseq {
    # find the starting sequence number from the two "our" variables
    $one_config{$repo} ||= [];
    my ($startseq) =
        sort { $a <=> $b }
        map { $_->[0] }
        map { @$_ }
        (
            $one_config{$repo}, 
            map { values %$_ } $one_repo{$repo}
        );
    return $startseq;
}

sub parse_and_store {
    my ($cf, $repo) = @_;

    parse(sugar($cf));
    _chdir( $rc{GL_REPO_BASE} );
    Gitolite::Conf::Store::store_1($repo);
}

sub update_seq {
    my ($repo, $startseq) = @_;

    _chdir("$rc{GL_REPO_BASE}/$repo.git");
    my $text = slurp("gl-conf");

    $startseq--;    # adjust for ++ at start of parse
    $text =~ s/^( +)(\d+),$/"$1" . ($2+$startseq) . ","/gme;

    _print("gl-conf", $text);
}

__END__

This program is meant to do one thing, and one thing only: re-compile the
rules for a single repo quickly and efficiently.

CAVEATS:

Apart from the requirements listed at the top, there are some things to watch for.

Before we do that, let's define some terms for ease of discussion.

*   "named repos" -- repos that are explicitly named in gitolite.conf; e.g.

        repo foo bar baz
            ...

*   "other repos" -- repos that are not "named".  Usually, they are defined
    via a group definition or a regex; e.g.

        repo @all
            ...

        @g1 = foo bar baz
        repo @g1
            ...

        repo fo[a-z].*
            ...

Now the caveats:

1.  You can only use this to recompile rules for named repos, not for other
    repos.

2.  The repo must be defined only once in gitolite.conf.  I.e., it's rules
    must NOT be split up across multiple sections or files, with other repos
    rules intervening in between.  (Normal gitolite lets you do that, but that
    won't work with this code).

3.  All the "named repos" which you might ever want to single-compile in
    future, must be placed at the end of gitolite.conf.  Do not place any
    "other repo" definitions after them.

    (This is a somewhat conservative restriction; there are situations in
    which it can be violated but it's hard to explain.  Your current config
    seems to satisfy this constraint so I won't bother detailing how to get
    around it!  Ask me on email if needed.)