Follow-up to r29036: Now that the "mergeinfo" transaction file is no
[svn.git] / contrib / cgi / mirror_dir_through_svn.cgi
blob7bf24badbe9f2513f0ec532d82a9b7de17e0c896
1 #!/usr/bin/perl -wT
3 # $HeadURL$
4 # $LastChangedDate$
5 # $LastChangedBy$
6 # $LastChangedRevision$
8 $| = 1;
10 use strict;
11 use CGI 2.89;
12 use CGI::Carp 1.24 qw(fatalsToBrowser carpout);
13 use vars qw($query);
15 # Get a CGI object now and send the HTTP headers out immediately so
16 # that anything else printed will appear in the output, including
17 # compile errors.
18 BEGIN {
19 $query = CGI->new;
20 print $query->header('text/plain');
21 carpout(\*STDOUT);
24 # Protect the PATH environmental variable for safe system calls.
25 $ENV{PATH} = '/usr/bin:/bin';
27 # Configuration settings.
29 # The location of the svn program.
30 my $svn = '/opt/i386-linux/subversion/bin/svn';
32 # The location of the svn_load_dirs.pl script.
33 my $svn_load_dirs = '/export/home2/svn/bin/svn_load_dirs.pl';
35 # The source directory.
36 my $source_dirname = '/export/home2/svn/public_html/www-devel/webdav';
38 # The target directory.
39 my $target_dirname = '/export/home1/apache/htdocs/www';
41 # The URL for the Subversion repository.
42 my $repos_base_uri = 'file:///export/home2/svn/repos-www/trunk';
44 # Verbosity level.
45 my $opt_verbose = 1;
46 my @opt_verbose = $opt_verbose ? (qw(-v)) : ();
48 # Use this version of die instead of Perl's die so that messages are
49 # sent to STDOUT instead of STDERR so that the browser can see them.
50 # Otherwise, messages would be sent to Apache's error_log.
51 sub my_die ($@)
53 print "@_\n" if @_;
54 exit 1;
57 # For permissions information, print my actual and effective UID and
58 # GID.
59 if ($opt_verbose)
61 my $real_uid = getpwuid($<) || $<;
62 my $effective_uid = getpwuid($>) || $>;
63 my $real_gid = getgrgid($() || $(;
64 my $effective_gid = getgrgid($)) || $);
66 print "My real uid is $real_uid and my effective uid is $effective_uid.\n";
67 print "My real gid is $real_gid and my effective gid is $effective_gid.\n";
70 # Check the configuration settings.
71 -e $source_dirname
72 or my_die "$0: source directory `$source_dirname' does not exist.\n";
73 -d _
74 or my_die "$0: source directory `$source_dirname' is not a directory.\n";
75 -e $target_dirname
76 or my_die "$0: target directory `$target_dirname' does not exist.\n";
77 -d _
78 or my_die "$0: target directory `$target_dirname' is not a directory.\n";
80 # Since the path to svn and svn_load_dirs.pl depends upon the local
81 # installation preferences, check that the required programs exist to
82 # insure that the administrator has set up the script properly.
84 my $ok = 1;
85 foreach my $program ($svn, $svn_load_dirs)
87 if (-e $program)
89 unless (-x $program)
91 print "$0: required program `$program' is not executable, ",
92 "edit $0.\n";
93 $ok = 0;
96 else
98 print "$0: required program `$program' does not exist, edit $0.\n";
99 $ok = 0;
102 exit 1 unless $ok;
105 # Check that the svn base URL works by running svn log on it.
106 &read_from_process($svn, 'log', $repos_base_uri);
108 # Determine the authentication username for commit privileges.
109 # Untaint the REMOTE_USER environmental variable.
110 my $username;
111 if (defined $ENV{REMOTE_USER})
113 ($username) = $ENV{REMOTE_USER} =~ m/(\w+)/;
114 unless (defined $username and length $username)
116 my_die "$0: REMOTE_USER set to `$ENV{REMOTE_USER}' but no valid ",
117 "string extracted from it.\n";
120 else
122 my_die "$0: the REMOTE_USER environmental variable is not set.\n";
125 if ($opt_verbose)
127 print "I am logged in as `$username'.\n";
130 # Load the source directory into Subversion.
131 print "Now syncing Subversion repository with source directory.\n\n";
132 my_system($svn_load_dirs,
133 @opt_verbose,
134 '-no_user_input',
135 '-svn_username', $username,
136 '-p', '/opt/i386-linux/installed/svn_load_dirs_property_table.cfg',
137 $repos_base_uri,
138 '.',
139 $source_dirname) == 0
140 or my_die "$0: system failed. Quitting.\n";
142 print "\nNow syncing target directory with Subversion repository.\n\n";
144 chdir $target_dirname
145 or my_die "$0: chdir `$target_dirname' failed: $!\n";
146 my_system($svn, 'update', '.') == 0
147 or my_die "$0: system failed. Quitting.\n";
149 print "\nTarget directory sucessfully updated to mirror source directory.\n";
151 exit 0;
153 # Start a child process safely without using /bin/sh.
154 sub safe_read_from_pipe
156 unless (@_)
158 croak "$0: safe_read_from_pipe passed no arguments.\n";
161 if ($opt_verbose)
163 print "Running @_\n";
166 my $pid = open(SAFE_READ, '-|');
167 unless (defined $pid)
169 my_die "$0: cannot fork: $!\n";
171 unless ($pid)
173 open(STDERR, ">&STDOUT")
174 or my_die "$0: cannot dup STDOUT: $!\n";
175 exec(@_)
176 or my_die "$0: cannot exec `@_': $!\n";
178 my @output;
179 while (<SAFE_READ>)
181 chomp;
182 push(@output, $_);
184 close(SAFE_READ);
185 my $result = $?;
186 my $exit = $result >> 8;
187 my $signal = $result & 127;
188 my $cd = $result & 128 ? "with core dump" : "";
189 if ($signal or $cd)
191 print "$0: pipe from `@_' failed $cd: exit=$exit signal=$signal\n";
193 if (wantarray)
195 return ($result, @output);
197 else
199 return $result;
203 # Use safe_read_from_pipe to start a child process safely and exit the
204 # script if the child failed for whatever reason.
205 sub read_from_process
207 unless (@_)
209 croak "$0: read_from_process passed no arguments.\n";
211 my ($status, @output) = &safe_read_from_pipe(@_);
212 if ($status)
214 my_die "$0: @_ failed with this output:\n", join("\n", @output), "\n";
216 else
218 return @output;
222 # Run system() and print warnings on system's return values.
223 sub my_system
225 unless (@_)
227 confess "$0: my_system passed incorrect number of arguments.\n";
230 if ($opt_verbose)
232 print "Running @_\n";
235 my $result = system(@_);
236 if ($result == -1)
238 print "$0: system(@_) call itself failed: $!\n";
240 elsif ($result)
242 my $exit_value = $? >> 8;
243 my $signal_num = $? & 127;
244 my $dumped_core = $? & 128;
246 my $message = "$0: system(@_) exited with status $exit_value";
247 if ($signal_num)
249 $message .= " caught signal $signal_num";
251 if ($dumped_core)
253 $message .= " and dumped core";
255 print "$message\n";
258 $result;