Scott Harrison <sharrison@users.sourceforge.net> writes:
> New file.
> svn_filesystem_doctor - analyze and manipulate svn reposi-
> tories on a filesystem
Scott, I was about to add this tool, but then I realized it might be
out of date w.r.t. recent changes to svnadmin usage. Do you know?
By the way, maybe 'svn_repos_doctor' would be more intuitive?
-Karl
> #!/usr/bin/perl
>
> =head1 NAME
>
> svn_filesystem_doctor - analyze and manipulate svn repositories on a filesystem
>
> =head1 SYNOPSIS
>
> svn_filesystem_doctor S<[ B<--printf>="I<string>" ]>
> S<[ B<--oldsvnadminpath>="I<command_path>" ]>
> S<[ B<--svnadminpath>="I<command_path>" ]>
> S<[ B<--autochange> ]> S<[ B<--backup> ]>
> S<[ B<--stdin> ]> S<[ B<--findall>="I<starting_path>" ]>
> S<[ B<--apacheconf> ]>
>
> At minimum, either B<stdin> or the B<findall> flag must be specified in order
> to launch B<svn_filesystem_doctor>.
>
> The B<printf> I<string> can consist of the following escaped characters:
>
> =over 4
>
> =item %d
>
> Directory path to a subversion repository.
>
> =item %s
>
> The format schema of the subversion repository. A value of "0N" means
> that the format schema equals version 0 that it does not work with the current
> B<svnadmin> command. A value of "0Y" means version 0, and that it does work
> with the current B<svnadmin> command. A value of "13Y" means version 13
> and that it does work with the current B<svnadmin> command. And so on.
>
> =back
>
> =head1 DESCRIPTION
>
> Looks at an existing filesystem and diagnoses the locations and states
> of various subversion repositories (and this means "repositories", not
> working copies). This program also facilitates the generation
> of plain-text backups as well as upgrading the format db schema
> based on new releases of subversion.
>
> =head2 Getting the subversion repositories
>
> The B<findall> and B<stdin> flags control the repositories that this
> script works with. The B<findall> flag will probe the entire filesystem
> and look for likely locations of subversion repositories (using heuristics
> related to directory structure). The B<stdin> flag will alternatively
> accept a list of subversion directory filesystem paths (for which to apply
> the B<--printf>, B<--autochange>, or other functionalities).
>
> =head2 Locating the svnadmin executable
>
> The B<svnadminpath> and B<oldsvnadminpath> flags specify the location
> of the B<svnadmin> executables necessary to implement various
> svn_filesystem_doctor functionalities. Ordinarily, just the B<svnadminpath>
> variable would need to be specified (if it is not specified, the regular shell
> command path is used). The B<oldsvnadminpath> variable is specified for
> situations where the older version of B<svnadmin> is needed to perform db
> format schema upgrades (C<oldsvnadmin dump> followed by a C<currentsvnadmin
> load>)....
>
> =head2 Functionalities of svn_filesystem_doctor
>
> =over 4
>
> =item * Generate an apache configuration file
>
> >From the determined list of subversion repositories, an apache configuration
> text string is generated. This functionality is invoked by the B<apacheconf>
> flag. The configuration text is passed to standard output.
>
> =item * Autochange: update db format schemas used by subversion repositories
>
> Subversion repositories are updated from an older database format to a
> newer database format. This functionality is invoked by the B<autochange>
> flag. The manual procedure for this is:
>
> =over 4
>
> C<svnadmin1 dump reposname E<gt> reposname.dump>
>
> C<svnadmin2 load reposname E<lt> reposname.dump>
>
> =back
>
> where C<svnadmin1> and C<svnadmin2> are the old and new binary B<svnadmin>
> executables respectively. C<svnadmin1> is specified by the
> B<oldsvnadminpath> variable. C<svnadmin2> is specified by the
> B<svnadminpath> variable (or, if not specified, by the default location
> in the shell command path).
>
> =item * Backup by generating plain-text files for each subversion repository
>
> This dumps (creates) plain-text repository backup files for every specified
> subversion repository. This functionality is invoked by the B<backup> flag.
> The list of generated backup files is sent to standard output.
>
> =item * Print out repository information (printf)
>
> This functionality is invoked by the B<printf> command line argument
> (and this is also the default functionality if no functionality is
> specified). The repository locations (and potentially other information)
> is output to standard output.
>
> =back
>
> =cut
>
> use Getopt::Long; # Get specified options from the command line.
>
> # ============================= Process command-line arguments and error-check.
> my $usage=(<<END);
> Usage of svn_filesystem_doctor.
>
> SYNOPSIS
> svn_filesystem_doctor [ --printf="*string*" ]
> [ --oldsvnadminpath="*command_path*" ]
> [ --svnadminpath="*command_path*" ] [ --autochange ] [ --backup ]
> [ --stdin ] [ --findall="*starting_path*" ] [ --apacheconf ]
>
> At minimum, either stdin or the findall flag must be specified in order
> to launch svn_filesystem_doctor.
>
> The printf *string* can consist of the following escaped characters:
>
> %d Directory path to a subversion repository.
>
> %s The format schema of the subversion repository. A value of "0N"
> means that the format schema equals version 0 that it does not work
> with the current svnadmin command. A value of "0Y" means version 0,
> and that it does work with the current svnadmin command. A value of
> "13Y" means version 13 and that it does work with the current
> svnadmin command. And so on.
>
> DESCRIPTION
> Looks at an existing filesystem and diagnoses the locations and states
> of various subversion repositories (and this means "repositories", not
> working copies). This program also facilitates the generation of
> plain-text backups as well as upgrading the format db schema based on
> new releases of subversion.
>
> Getting the subversion repositories
>
> The findall and stdin flags control the repositories that this script
> works with. The findall flag will probe the entire filesystem and look
> for likely locations of subversion repositories (using heuristics
> related to directory structure and also applying the "svnadmin youngest"
> command. The stdin flag will alternatively accept a list of subversion
> directory filesystem paths (for which to apply the --printf,
> --autochange, or other functionalities).
>
> Locating the svnadmin executable
>
> The svnadminpath and oldsvnadminpath flags specify the location of the
> svnadmin executables necessary to implement various svn_filesystem_doctor
> functionalities. Ordinarily, just the svnadminpath variable would need
> to be specified (if it is not specified, the regular shell command path
> is used). The oldsvnadminpath variable is specified for situations where
> the older version of svnadmin is needed to perform db format schema
> upgrades ("oldsvnadmin dump" followed by a "currentsvnadmin load")....
>
> Functionalities of svn_filesystem_doctor
>
> * Generate an apache configuration file
> From the determined list of subversion repositories, an apache
> configuration text string is generated. This functionality is
> invoked by the apacheconf flag. The configuration text is passed to
> standard output.
>
> * Autochange: update db format schemas used by subversion repositories
> Subversion repositories are updated from an older database format to
> a newer database format. This functionality is invoked by the
> autochange flag. The manual procedure for this is:
>
> "svnadmin1 dump reposname > reposname.dump"
>
> "svnadmin2 load reposname < reposname.dump"
>
> where "svnadmin1" and "svnadmin2" are the old and new binary
> svnadmin executables respectively. "svnadmin1" is specified by the
> oldsvnadminpath variable. "svnadmin2" is specified by the
> svnadminpath variable (or, if not specified, by the default location
> in the shell command path).
>
> * Backup by generating plain-text files for each subversion repository
> This dumps (creates) plain-text repository backup files for every
> specified subversion repository. This functionality is invoked by
> the backup flag. The list of generated backup files is sent to
> standard output.
>
> * Print out repository information (printf)
> This functionality is invoked by the printf command line argument (and
> this is also the default functionality if no functionality is
> specified). The repository locations (and potentially other
> information) is output to standard output.
>
> END
> my %h; # This has will store the command line options values.
> my $retval = &GetOptions(\%h,
> "printf=s","oldsvnadminpath=s","svnadminpath=s",
> "autochange","backup","findall=s","stdin",
> "apacheconf");
>
> # Command option syntax must be correct.
> unless ($retval)
> {
> print($usage);
> exit(1);
> }
>
> # At minimum, either the findall or the stdin flag needs to be specified
> # (so that a list of repositories can be obtained to work on).
> unless ($h{'findall'} or $h{'stdin'})
> {
> print($usage);
> exit(1);
> }
>
> # Both findall and stdin flags cannot be specified together.
> if ($h{'findall'} and $h{'stdin'})
> {
> print('findall and stdin cannot both be specified'."\n");
> print($usage);
> exit(1);
> }
>
> # If specified, the findall path should exist on the filesystem.
> if (defined($h{'findall'}))
> {
> unless (-e $h{'findall'})
> {
> print('The findall variable does not exist on the'.
> ' filesystem'."\n");
> print($usage);
> exit(1);
> }
> }
>
> # If specified, the oldsvnadminpath should exist on the filesystem.
> if (defined($h{'oldsvnadminpath'}))
> {
> unless (-x $h{'oldsvnadminpath'})
> {
> print('The oldsvnadminpath variable does not exist as an executable '.
> 'on the filesystem'."\n");
> print($usage);
> exit(1);
> }
> }
>
> # If specified, the findall path should exist on the filesystem.
> if (defined($h{'svnadminpath'}))
> {
> unless (-x $h{'svnadminpath'})
> {
> print('The svnadminpath variable does not exist as an executable on '.
> ' the filesystem'."\n");
> print($usage);
> exit(1);
> }
> }
>
> # If autochange is specified, then oldsvnadminpath should be specified.
> if ($h{'autochange'})
> {
> unless ($h{'oldsvnadminpath'})
> {
> print('For autochange, the oldsvnadminpath value must be specified.'.
> "\n");
> print($usage);
> exit(1);
> }
> }
>
> # ==================== Gather the list of subversion repositories to work with.
> my @subversion_repository_list;
> if ($h{'stdin'}) # Subversion repository directory list coming through stdin?
> {
> my @a = <>;
> @subversion_repository_list = map {chomp; $_} @a;
> }
> elsif ($h{'findall'}) # Scan, starting from specified location in filesystem.
> {
> my @a = `find $h{'findall'} -maxdepth 1000 -type d -name "hooks" 2>/dev/null`;
> foreach my $possible (@a)
> {
> chomp($possible);
> $possible =~ s/\/[^\/]*$//;
> opendir(SDIR,$possible);
> my @otherdirs = grep {!/^\.\.?$/} readdir(SDIR);
> closedir(SDIR);
> my $score = 0; # The "heuristical measure" as to whether = svn repos.
> foreach my $odir (@otherdirs)
> {
> if ($odir eq 'locks')
> {
> $score++;
> }
> if ($odir eq 'db')
> {
> $score++;
> }
> }
> if ($score > 1) # Score is good?
> {
> push(@subversion_repository_list,$possible); # Add to list.
> }
> }
> }
>
> # ============================================ Locate the svnadmin executables.
> my $oldsvnadmin; # Set to the svnadmin command (of old database format schema).
> my $currentsvnadmin;# Set to the svnadmin command (of desired format schema).
>
> # Set the variables.
> if ($h{'oldsvnadminpath'})
> {
> $oldsvnadmin = $h{'oldsvnadminpath'};
> }
> if ($h{'svnadminpath'})
> {
> $currentsvnadmin = $h{'svnadminpath'};
> }
> else
> {
> $currentsvnadmin = 'svnadmin';
> system("$currentsvnadmin --version 2>/dev/null");
> if ($? == 127)
> {
> print('Cannot find the current svnadmin command.'."\n");
> exit(1);
> }
> }
>
> # ================================== Determine the function(s) to be performed.
> my @functions; # List of functions to perform on the repository list.
> if ($h{'printf'})
> {
> push(@functions,'printf');
> }
> if ($h{'autochange'})
> {
> push(@functions,'autochange');
> }
> if ($h{'backup'})
> {
> push(@functions,'backup');
> }
> if ($h{'apacheconf'})
> {
> push(@functions,'apacheconf');
> }
>
> if (!@functions) # printf is the default
> {
> push(@functions,'printf');
> }
>
> # ========================================================= Carry out the task.
> foreach my $function (@functions)
> {
> if ($function eq 'printf') # Output information.
> {
> foreach my $repos (@subversion_repository_list)
> {
> my $p = $h{'printf'};
> unless ($p)
> {
> $p = $repos."\n";
> }
> else
> {
> $p =~ s/^\"//;
> $p =~ s/\"$//;
> $p =~ s/\\t/\t/g;
> $p =~ s/\\n/\n/g;
> $p =~ s/\%d/$repos/g;
> }
> if ($p =~ /\%s/)
> {
> my $format;
> if (-e "$repos/format")
> {
> $format = `cat $repos/format`;
> chomp($format);
> }
> else
> {
> $format = 0;
> }
> $p =~ s/\%s/$format/g;
> }
> print($p);
> }
> }
> if ($function eq 'backup') # Create plaintext backups (svnadmin dump).
> {
> my $timestamp = `date +"%Y%m%d%H%M%S"`;
> chomp($timestamp);
> foreach my $repos (@subversion_repository_list)
> {
> system("$currentsvnadmin dump $repos > $repos.$timestamp.dump");
> if ($?)
> {
> print('FAILURE:'.$repos."\n");
> }
> else
> {
> print('SUCCESS:'.$repos."\n");
> print('(RESTORE):'.
> "mv $repos $repos.old; $currentsvnadmin create $repos; ".
> "$currentsvnadmin load $repos < $repos.$timestamp.dump".
> "\n");
> }
> }
> }
> if ($function eq 'autochange') # Try to convert database format schemas.
> {
> my $timestamp = `date +"%Y%m%d%H%M%S"`;
> chomp($timestamp);
> foreach my $repos (@subversion_repository_list)
> {
> system("$oldsvnadmin dump $repos > $repos.$timestamp.dump");
> system("mv $repos > $repos.$timestamp.old") unless $?;
> system("$currentsvnadmin create $repos") unless $?;
> system("$currentsvnadmin load $repos < $repos.$timestamp.dump")
> unless $?;
> system("rm -f $repos.$timestamp.old") unless $?;
> if ($?)
> {
> print('FAILURE:'.$repos."\n");
> }
> else
> {
> print('SUCCESS:'.$repos."\n");
> }
> }
> }
> if ($function eq 'apacheconf') # Generate an apache configuration.
> {
> my $timestamp = `date +"%Y%m%d%H%M%S"`;
> foreach my $repos (@subversion_repository_list)
> {
> my $reposdir = $repos;
> $reposdir =~ s/^.*\/([^\/]*)$/$1/;
> print(<<END);
> <Directory $repos>
> Options FollowSymLinks Indexes
> AllowOverride All
> </Directory>
> <Location /svn/$reposdir>
> DAV svn
> SVNPath $repos
>
> # Limit write permission to list of valid users.
> <LimitExcept GET PROPFIND OPTIONS REPORT>
> # Require SSL connection for password protection.
> # SSLRequireSSL
>
> AuthType Basic
> AuthName "Authorization Realm"
> AuthUserFile /subversion_users/passwdfile
> Require valid-user
> </LimitExcept>
> </Location>
> END
> }
> }
> }
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
> For additional commands, e-mail: dev-help@subversion.tigris.org
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Thu Dec 12 19:27:45 2002