#!/usr/bin/perl use warnings; use strict; use Getopt::Long; use Pod::Usage; =head1 NAME sa - sync all =head1 SYNOPSIS sa [options] [status|update|checkout] [directories to sync] Options: --quick, -Q don't update external projects --verbose, -v be more verbose --quiet, -q be quiet --debug, -d debugging level (Default 0) --help, -h display this help --man, -m display manual =head1 OPTIONS =over =item B<--debug, -d> Debug verbosity. (Default 0) =item B<--help, -h> Display brief useage information. =item B<--man, -m> Display this manual. =back =head1 EXAMPLES =cut #use User; use IO::File; use vars qw($DEBUG $VERBOSE); my %options = (quick => 1, quiet => 1, debug => 0, help => 0, man => 0, verbose => 0, ); GetOptions(\%options,'quick|Q+','quiet|q!','debug|d+','help|h|?','man|m','verbose|v+'); pod2usage() if $options{help}; pod2usage({verbose=>2}) if $options{man}; # parse configuration file =head1 CONFIGURATION Reads configuration information from Start by parsing /etc/sa.conf, then the contents of ~/sa.d/ which match ^[\w\d][\w\d_.-]+$ The configuration file contains a list of svn repositories which should be queried; each line can contain a tab, which indicates that the command following the tab should be run after the svn directory is updated. The configuration files are read in the order given above. =cut sub parse_config_file { my ($repos,$filename,$home) = @_; return unless -e $filename and -r _; my $fh = new IO::File $filename, 'r' or die "Unable to read configuration file $filename $!"; while (<$fh>) { chomp; next if /^#/; my ($repo,$command) = split /\t/,$_,2; $repo =~ s/^\~/$home/; $$repos{$repo} = $command; } } my $HOME=$ENV{HOME}; my $HOSTNAME=qx(hostname); $HOSTNAME=~s/\n//g; my $CAN_IGNORE_EXTERNALS = 0; qx(svn --version) =~ /\(r(\d+)\)/; if ($1 > 13838) { $CAN_IGNORE_EXTERNALS = 1; } sub available_config_files{ my $dir; opendir($dir, "$HOME/.sa.d/") or return (); return map {"$HOME/.sa.d/$_"} grep /^[\w\d][\w\d_.-]+$/, readdir $dir; } my %repos; for ('/etc/sa.conf', available_config_files()) { if (-e $_) { parse_config_file(\%repos,$_,$HOME); } } $DEBUG = $options{debug}; $VERBOSE = $options{verbose}; my $command; if (@ARGV and $ARGV[0] =~ /^(st(?:atus)?|up(?:date)?|checkout)$/) { $command = $ARGV[0]; } else { $command = 'status'; } while (my ($repo,$run_after) = each(%repos)) { if (-e "$repo/.svn") { print "Checking [$repo]\n"; system('svn', $command, (not $VERBOSE and $options{quiet})?'-q':(), ($VERBOSE >= 2)?'-v':(), ($options{quick} and $CAN_IGNORE_EXTERNALS)?'--ignore-externals':(), $options{quick}>1?'-N':(), $repo, ); } if ($command =~ /^up(?:date)|checkout$/) { system('sh', '-c',"$run_after $repo") if defined $run_after and length $run_after; } }