summaryrefslogtreecommitdiffstats
path: root/src/commands/writable
blob: 3e97f0b9a972592022458e4670e4d2ee0a55bf1b (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
#!/usr/bin/perl
use strict;
use warnings;

use lib $ENV{GL_LIBDIR};
use Gitolite::Easy;

=for usage
Usage: gitolite writable <reponame>|@all on|off|status

Disable/re-enable pushes to all repos or named repo.  Useful to run
non-git-aware backups and so on.

'on' enables, 'off' disables, writes (pushes) to the named repo or all repos.
'status' returns the current status as shell truth (i.e., exit code 0 for
writable, 1 for not writable).

With 'off', any subsequent text is taken to be the message to be shown to
users when their pushes get rejected.  If it is not supplied, it will take it
from STDIN; this allows longer messages.
=cut

usage() if not @ARGV or @ARGV < 2 or $ARGV[0] eq '-h';
usage() if $ARGV[1] ne 'on' and $ARGV[1] ne 'off' and $ARGV[1] ne 'status';

my $repo = shift;
my $op   = shift;    # on|off|status

if ( $repo eq '@all' ) {
    _die "you are not authorized" if $ENV{GL_USER} and not is_admin();
} else {
    _die "you are not authorized" if $ENV{GL_USER} and not( owns($repo) or is_admin() or ( can_write($repo) and $op eq 'status' ) );
}

my $msg = join( " ", @ARGV );
# try STDIN only if no msg found in args *and* it's an 'off' command
if ( not $msg and $op eq 'off' ) {
    say2 "...please type the message to be shown to users:";
    $msg = join( "", <> );
}

my $sf = ".gitolite.down";
my $rb = $ENV{GL_REPO_BASE};

if ( $repo eq '@all' ) {
    target( $ENV{HOME} );
} else {
    target("$rb/$repo.git");
    target( $ENV{HOME} ) if $op eq 'status';
}

exit 0;

sub target {
    my $repodir = shift;
    if ( $op eq 'status' ) {
        exit 1 if -e "$repodir/$sf";
    } elsif ( $op eq 'on' ) {
        unlink "$repodir/$sf";
    } elsif ( $op eq 'off' ) {
        _print( "$repodir/$sf", $msg );
    }
}