]> git.donarmstrong.com Git - bin.git/blob - sa
add common subscriber
[bin.git] / sa
1 #!/usr/bin/perl
2
3 use warnings;
4 use strict;
5
6 use Getopt::Long;
7 use Pod::Usage;
8
9 =head1 NAME
10
11 sa - sync all
12
13 =head1 SYNOPSIS
14
15 sa [options] [status|update|checkout] [directories to sync]
16
17  Options:
18   --quick, -Q don't update external projects
19   --verbose, -v be more verbose
20   --quiet, -q be quiet
21   --debug, -d debugging level (Default 0)
22   --help, -h display this help
23   --man, -m display manual
24
25 =head1 OPTIONS
26
27 =over
28
29 =item B<--debug, -d>
30
31 Debug verbosity. (Default 0)
32
33 =item B<--help, -h>
34
35 Display brief useage information.
36
37 =item B<--man, -m>
38
39 Display this manual.
40
41 =back
42
43 =head1 EXAMPLES
44
45 =cut
46
47
48
49 #use User;
50 use IO::File;
51 use vars qw($DEBUG $VERBOSE);
52
53 my %options = (quick           => 1,
54                quiet           => 1,
55                debug           => 0,
56                help            => 0,
57                man             => 0,
58                verbose         => 0,
59                hooks_only      => 0,
60               );
61
62 GetOptions(\%options,'quick|Q+','quiet|q!','debug|d+','help|h|?','man|m','verbose|v+','hooks_only|hooks-only');
63
64 pod2usage() if $options{help};
65 pod2usage({verbose=>2}) if $options{man};
66
67 # parse configuration file
68
69 =head1 CONFIGURATION
70
71 Reads configuration information from Start by parsing /etc/sa.conf,
72 then the contents of ~/sa.d/ which match ^[\w\d][\w\d_.-]+$
73
74 The configuration file contains a list of svn repositories which
75 should be queried; each line can contain a tab, which indicates that
76 the command following the tab should be run after the svn directory is
77 updated.
78
79 The configuration files are read in the order given above.
80
81 =cut
82
83 sub parse_config_file {
84      my ($repos,$filename,$home) = @_;
85      return unless -e $filename and -r _;
86      my $fh = new IO::File $filename, 'r' or die "Unable to read configuration file $filename $!";
87      while (<$fh>) {
88           chomp;
89           next if /^#/;
90           my ($repo,$command) = split /\t/,$_,2;
91           $repo =~ s/^\~/$home/;
92           $$repos{$repo} = $command;
93      }
94 }
95
96 my $HOME=$ENV{HOME};
97 my $HOSTNAME=qx(hostname);
98 $HOSTNAME=~s/\n//g;
99 my $CAN_IGNORE_EXTERNALS = 0;
100 if (not $options{hooks_only}) {
101      qx(svn --version) =~ /\(r(\d+)\)/;
102      if ($1 > 13838) {
103           $CAN_IGNORE_EXTERNALS = 1;
104      }
105 }
106
107 sub available_config_files{
108      my $dir;
109      opendir($dir, "$HOME/.sa.d/") or return ();
110      return map {"$HOME/.sa.d/$_"} grep /^[\w\d][\w\d_.-]+$/, readdir $dir;
111 }
112
113 my %repos;
114 for ('/etc/sa.conf', available_config_files()) {
115      if (-e $_) {
116           parse_config_file(\%repos,$_,$HOME);
117      }
118 }
119
120 $DEBUG = $options{debug};
121 $VERBOSE = $options{verbose};
122
123 my $command;
124
125 if (@ARGV and $ARGV[0] =~ /^(st(?:atus)?|up(?:date)?|checkout)$/) {
126      $command = $ARGV[0];
127 }
128 else {
129      $command = 'status';
130 }
131
132 while (my ($repo,$run_after) = each(%repos)) {
133      print "Checking [$repo]\n";
134      if (-e "$repo/.svn" and not $options{hooks_only}) {
135           system('svn',
136                  $command,
137                  (not $VERBOSE and $options{quiet})?'-q':(),
138                  ($VERBOSE >= 2)?'-v':(),
139                  ($options{quick} and $CAN_IGNORE_EXTERNALS)?'--ignore-externals':(),
140                  $options{quick}>1?'-N':(),
141                  $repo,
142                 );
143      }
144      if ($command =~ /^up(?:date)?|checkout$/) {
145           system('sh', '-c',"$run_after $repo") if defined $run_after and length $run_after;
146      }
147 }