[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Partial read-only repository?

From: David Mankin <mankin_at_ants.com>
Date: 2002-04-16 17:56:20 CEST

On Tue, 16 Apr 2002, Tim Moloney wrote:

> I think that I have a pre-commit script that verifies that only copies
> are made to the tags directory. This is implemented in the two files
> below.
>
> Please note that I haven't done perl in a while (and I probably wasn't
> any good then either). If there are any perl gurus out there, feel
> free to clean up the style, "perlize" it (versus my lame C-like style),
> etc.

I haven't done a full perlizing review. (It looks pretty good except for
the use of $#array which I don't think is used much; use @array instead).
I did spot one probable bug; see below.

-David Mankin

>
> Hopefully, somebody else will find this useful. =)
>
> ===== begin svn_hook_utils.pm =====
> #!/usr/bin/perl -w
>
> #
> # /usr/lib/perl/site_perl/5.6.0/i386-linux/svn_hook_utils.pm
> #
>
> package svn_hook_utils;
> require Exporter;
> @ISA =qw(Exporter);
> @EXPORT = qw(
> svn_hook_init svn_fatal_error svn_mail_error svn_svnlook
> svn_check_log svn_check_tags
> );
> @EXPORT_OK = qw($author $date $log_size $log_msg @changed @dirs_changed);
>
>
> #
> # Configuration
> #
> $domain = 'mrsl.com';
> $sendmail = '/usr/sbin/sendmail';
> $svnlook = '/usr/local/bin/svnlook';
> $svn_dir = '/var/svn';
> $svn_admin = 'moloney';
>
>
> #
> # Constants
> #
> @months = ('Jan' ,'Feb', 'Mar', 'Apr', 'May', 'Jun',
> 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
>
>
> #
> # Functions
> #
>
> #
> # svn_fatal_error()
> #
> # Write a time-stamped message to the error log.
> #
> sub svn_fatal_error {
>
> my($msg) = @_;
>
> my($sec, $min, $hour, $day, $mon) = localtime;
>
> if (open(ERROR_LOG, ">>$svn_dir/error.log")) {
> printf(ERROR_LOG "\n");
> printf(ERROR_LOG "%s %2d %02d:%02d:%02d\n",
> $months[$mon], $day, $hour, $min, $sec);
> printf(ERROR_LOG "\n");
> printf(ERROR_LOG "%s", $msg);
> }
> else {
> #
> # Don't bother doing anything here because no one will ever see it.
> #
> }
>
> exit(1);
>
> }
>
>
> #
> # svn_mail_error()
> #
> # Mail an error message to the author.
> #
> sub svn_mail_error {
>
> my($msg) = @_;
>
> my($cmd) = "| $sendmail $author\@$domain";
> if (open(SENDMAIL, $cmd)) {
> print(SENDMAIL "To: $author\@$domain\n");
> print(SENDMAIL "From: svn_server\n");
> print(SENDMAIL "Subject: Subversion Commit Error\n");
> print(SENDMAIL "Reply-to: $svn_admin\@$domain\n");

You need to print an extra \n here in order to separate the headers from
the message body. (Unless you're sure the $msg will always start with a
blank line, which I doubt.)

> print(SENDMAIL $msg);
> close(SENDMAIL);
> }
> else {
> svn_fatal_error("Failed to execute '$cmd'\n");
> }
>
> exit(1);
>
> }
>
>
> #
> # svn_get_args()
> #
> # Verify and load the command line arguments based on the hook type.
> #
> # TODO - Add the following hook types:
> # post-commit, read-sentinels, write-sentinals
> #
> sub svn_get_args {
>
> my($hook_type, @in_args) = @_;
>
> my(%out_args);
>
> if ($hook_type eq 'precommit') {
> if ($#in_args != 1) {
> $msg = " Invalid number of parameters for pre-commit script.\n";
> $msg .= " The following arguments were passed:\n";
> $msg .= "\n";
> if ($#in_args == -1) {
> $msg .= " <none>\n";
> }
> else {
> for ($i = 0; $i <= $#in_args; $i++) {
> $msg .= sprintf(" %d - '%s'\n", $i, $in_args[$i]);
> }
> }
> svn_fatal_error($msg);
> }
>
> $out_args{repos} = $in_args[0];
> $out_args{txn_rev} = "txn $in_args[1]";
> }
>
> return(%out_args);
>
> }
>
>
> #
> # svn_hook_init()
> #
> # Get all of the transaction data based on the hook type and command line
> # arguments.
> #
> sub svn_hook_init {
>
> my($hook_type, @args) = @_;
>
> %args = svn_get_args($hook_type, @args);
>
> ($author, $date, $log_size, $log_msg) = svn_svnlook('info');
> chomp($author);
> chomp($date);
> chomp($log_size);
>
> @changed = svn_svnlook('changed');
>
> @dirs_changed = svn_svnlook('dirs-changed');
>
> }
>
>
> #
> # svn_svnlook()
> #
> # Get the specified transaction data.
> #
> sub svn_svnlook {
>
> my($subcmd) = @_;
>
> my($cmd) = "$svnlook $args{repos} $args{txn_rev} $subcmd";
>
> return(`$cmd`);
>
> }
>
>
> #
> # svn_check_log()
> #
> # Verifies that some sort of log was entered.
> #
> sub svn_check_log {
>
> if ($log_msg !~ m/[a-zA-Z0-9]/) {
> return(1);
> }
>
> return(0);
>
> }
>
>
> #
> # build_id_table()
> #
> # Builds the table that contains the directory entries and their node ids.
> #
> sub build_id_table {
> my(@lines) = split(/\n/, svn_svnlook('ids'));
> my($line);
> my(@parents);
> my($full_dir);
> my($dir);
> my($id);
> my(%table);
> foreach $line (@lines) {
> chomp($line);
> $full_dir = '';
> for ($i = 0; substr($line, $i, 1) eq ' '; $i++) {
> $full_dir .= $parents[$i];
> };
> ($dir, $id) = split(/ /, substr($line, $i));
> $parents[$i] = $dir;
> $full_dir .= $dir;
> $table{$full_dir} = $id;
> }
> return(%table);
> }
>
>
> #
> # svn_check_tags()
> #
> # Verifies that no changes are made to the tags directory. Only copies are
> # made.
> #
> sub svn_check_tags {
>
> $check = 0;
> foreach $dir (@dirs_changed) {
> if ($dir =~ m/^tags/) {
> $check = 1;
> last;
> }
> }
>
> if ($check) {
> my(%ids) = build_id_table();
> my($key);
> my($tag_file);
> my($trunk_file);
> foreach $key (sort keys %ids) {
> if ($key =~ m/$dirs_changed[1].+/) {
> $tag_file = $key;
> $trunk_file = $key;
> $trunk_file =~ s/$dirs_changed[1]/trunk\//;
> if ($ids{$tag_file} ne $ids{$trunk_file}) {
> return(1);
> }
> }
> }
> }
>
> return(0);
>
> }
> ===== end svn_hook_utils.pm =====
>
> ===== begin pre-commit =====
> #!/usr/bin/perl -w
>
> #
> # <repos-dir>/hooks/pre-commit
> #
>
> use svn_hook_utils;
>
> svn_hook_init('precommit', @ARGV);
>
> $changed = join('', @svn_hook_utils::changed);
>
> #
> # Make sure that some sort of log message was provided.
> #
> if (svn_check_log() != 0) {
> $msg = "
> The following commit was rejected because there was no log message.
>
> Changes
> =========
> $changed
> ";
> svn_mail_error($msg);
> }
>
> #
> # Make sure that no changes to the tags directory were made.
> #
> if (svn_check_tags() != 0) {
> $msg = "
> The following commit was rejected because it attempted to change
> the tags directory.
>
> Changes
> =========
> $changed
>
> Log
> =====
> $svn_hook_utils::log_msg
> ";
> svn_mail_error($msg);
> }
>
> #
> # Return success.
> #
> exit(0);
> ===== end pre-commit =====
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Tue Apr 16 17:57:26 2002

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.