8 $tid = $ENV{GL_TID
} || 0;
12 use lib
$ENV{GL_LIBDIR
};
15 use Gitolite
::Conf
::Load
;
18 Usage 1: gitolite mirror push <slave> <repo>
19 gitolite mirror status <slave> <repo>
20 gitolite mirror status all <repo>
21 gitolite mirror status all all
22 Usage 2: ssh git@master-server mirror push <slave> <repo>
23 ssh git@master-server mirror status <slave> <repo>
25 Forces a push of one repo to one slave.
27 Usage 1 is directly on the master server. Nothing is checked; if the slave
28 accepts it, the push happens, even if the slave is not in any slaves
29 option. This is how you do delayed or lagged pushes to servers that do not
30 need real-time updates or have bandwidth/connectivity issues.
32 Usage 2 can be initiated by *any* user who has *any* gitolite access to the
33 master server, but it checks that the slave is in one of the slaves options
34 before doing the push.
36 MIRROR STATUS: The usage examples above show what can be done. The 'status
37 all <repo>' usage checks the status of all the slaves defined for the given
38 repo. The 'status all all' usage is special, in that it only prints a list of
39 repos that have *some* error, instead of dumping all the error info itself.
41 SERVER LIST: 'gitolite mirror list master <reponame>' and 'gitolite mirror
42 list slaves <reponame>' will show you the name of the master server, and list
43 the slave servers, for the repo. They only work on the server command line
44 (any server), but not remotely (from a normal user).
47 usage
() if not @ARGV or $ARGV[0] eq '-h';
49 _die
"HOSTNAME not set" if not $rc{HOSTNAME
};
51 my ( $cmd, $host, $repo ) = @ARGV;
55 if ( $cmd eq 'push' ) {
56 valid_slave
( $host, $repo ) if exists $ENV{GL_USER
};
57 # will die if host not in slaves for repo
59 trace
( 1, "TID=$tid host=$host repo=$repo", "gitolite mirror push started" );
60 _chdir
( $rc{GL_REPO_BASE
} );
63 if ( -f
"gl-creator" ) {
64 # try to propagate the wild repo, including creator name and gl-perms
65 my $creator = `cat gl-creator`; chomp($creator);
66 trace
( 1, `cat gl-perms 2>/dev/null | ssh $host CREATOR=$creator perms -c \\'$repo\\' 2>/dev/null` );
71 for (`git push --mirror $host:$repo 2>&1`) {
73 print STDERR
"$_" if -t STDERR
or exists $ENV{GL_USER
};
78 gl_log
( 'mirror', $_ );
80 trace
( 1, "mirror: $_" );
83 # save the mirror push status for this slave if the word 'fatal' is found,
84 # else remove the status file. We don't store "success" output messages;
85 # you can always get those from the log files if you really need them.
86 if ( $glss =~ /fatal/i ) {
87 my $glss_prefix = Gitolite
::Common
::gen_ts
() . "\t$ENV{GL_TID}\t";
88 $glss =~ s/^/$glss_prefix/gm;
89 _print
("gl-slave-$host.status", $glss);
91 unlink "gl-slave-$host.status";
95 } elsif ($cmd eq 'status') {
96 if (not exists $ENV{GL_USER
} and $repo eq 'all') {
97 # this means 'gitolite mirror status all all'; in this case we only
98 # return a list of repos that *have* status files (indicating some
99 # problem). It's upto you what you do with that list. This is not
100 # allowed to be run remotely; far too wide ranging, sorry.
101 _chdir
( $rc{GL_REPO_BASE
} );
102 my $phy_repos = list_phy_repos
(1);
103 for my $repo ( @
{$phy_repos} ) {
104 my @x = glob("$rc{GL_REPO_BASE}/$repo.git/gl-slave-*.status");
105 print "$repo\n" if @x;
110 valid_slave
( $host, $repo ) if exists $ENV{GL_USER
};
111 # will die if host not in slaves for repo
113 _chdir
( $rc{GL_REPO_BASE
} );
116 $host = '*' if $host eq 'all';
117 map { print_status
($repo, $_) } sort glob("gl-slave-$host.status");
119 # strictly speaking, we could allow some of the possible commands remotely
120 # also, at least for admins. However, these commands are mainly intended
121 # for server-side scripting so I don't care.
122 usage
() if $ENV{GL_USER
};
124 server_side_commands
(@ARGV);
127 # ----------------------------------------------------------------------
130 my ( $host, $repo ) = @_;
131 _die
"invalid repo '$repo'" unless $repo =~ $REPONAME_PATT;
133 my %list = repo_slaves
($repo);
134 _die
"'$host' not a valid slave for '$repo'" unless $list{$host};
140 my $ref = git_config
( $repo, "^gitolite-options\\.mirror\\.slaves.*" );
141 my %list = map { $_ => 1 } map { split } values %$ref;
149 my $ref = git_config
( $repo, "^gitolite-options\\.mirror\\.master\$" );
150 my @list = map { split } values %$ref;
151 _die
"'$repo' seems to have more than one master" if @list > 1;
153 return $list[0] || '';
159 return unless -f
$file;
160 my $slave = $1 if $file =~ /^gl-slave-(.+)\.status$/;
161 print "----------\n";
162 print "WARNING: previous mirror push of repo '$repo' to host '$slave' failed, status is:\n";
164 print "----------\n";
167 # ----------------------------------------------------------------------
168 # server side commands. Very little error checking.
169 # gitolite mirror list master <repo>
170 # gitolite mirror list slaves <repo>
172 sub server_side_commands
{
173 if ( $cmd eq 'list' ) {
174 if ( $host eq 'master' ) {
175 say repo_master
($repo);
176 } elsif ( $host eq 'slaves' ) {
177 my %list = repo_slaves
($repo);
178 say join( " ", sort keys %list );
180 _die
"gitolite mirror list master|slaves <reponame>";
183 _die
"invalid command";