#!/usr/bin/perl -w # $Id: dasscm 203 2005-12-05 10:50:40Z joergs $ use strict; use Env qw($DASSCM_PROD $DASSCM_REPO $USER $DASSCM_USER $DASSCM_PW); use Cwd; use File::Basename; use File::stat; use File::Path; use File::Copy; #use POSIX qw/getpgrp tcgetpgrp/; use Getopt::Long; ##################################################################### # # global # my $SVN = "svn "; my $svnOptions = ""; # command line options get stored in options hash my %options = (); # subcommand, that gets executed (add, commit, ...) my $command; ##################################################################### # # util functions # sub usage() { print "usage: dasscm [options] [args]\n"; print "\n"; print "dasscm is intended to help versioning configuration files\n"; print "\n"; print "Available subcommands:\n"; print " add \n"; print " commit \n"; print " diff \n"; print " help \n"; print "\n"; print "preperation:\n"; print "check out the configuration repository, e.g.\n"; print "svn checkout --no-auth-cache --username USERNAME https://dass-it.de/svn/lvermgeo/technical/config/\n"; print "environment variables DASSCM_REPO, DASSCM_PROD and DASSCM_USER are evaluated.\n"; print "\n"; } sub check_env() { # DASSCM_PROD if ( ! $DASSCM_PROD ) { $DASSCM_PROD = "/"; } print "DASSCM_PROD: ".$DASSCM_PROD."\n"; if ( ! -d $DASSCM_PROD ) { die "DASSCM_PROD is not set to a directory.\n"; } # DASSCM_REPO if ( ! $DASSCM_REPO ) { die "Envirnonment variable DASSCM_REPO not set.\nSet DASSCM_REPO to the directory of the versioning system checkout for this machine.\n"; } print "DASSCM_REPO: ".$DASSCM_REPO."\n"; if ( ! -d $DASSCM_REPO ) { die "DASSCM_REPO must be is not set to the directory of the versioning system checkout for this machine.\n"; } # User settings # user root is not allowed for checkins. # if user is root, DASSCM_USER has to be set, # otherwise USER can be used if ( "$USER" eq "root" ) { if ( ! $DASSCM_USER ) { die "Envirnonment variable DASSCM_USER not set.\nSet DASSCM_USER to your subversion user account.\n"; } $svnOptions .= " --no-auth-cache " } elsif ( ! $DASSCM_USER ) { $DASSCM_USER=$USER; } #$svnOptions .= " --username $DASSCM_USER " } sub check_parameter(@) { } sub get_filenames(@) { my $filename_prod = $_[0]; if ( !($filename_prod =~ m/^\//) ) { $filename_prod = cwd()."/".$filename_prod; } -r $filename_prod or die "$filename_prod is not accessable"; # TODO: dirname buggy: eg. "/etc/" is reduced to "/", # "/etc" is used as filename my $dirname_prod = dirname($filename_prod); chdir $dirname_prod or die $!; $dirname_prod = cwd(); my $basename = basename($filename_prod); print "dir: ".$dirname_prod."\n"; print "fn: ".$basename."\n"; my $dirname_repo = $DASSCM_REPO."/".$dirname_prod; my $filename_repo = "$dirname_repo/$basename"; return ($basename,$dirname_prod,$dirname_repo,$filename_prod,$filename_repo); } sub run_command { my $command = shift; #print "executing command: " . $command . "\n"; open(RESULT, $command . ' 2>&1 |' ); my @result = ; close(RESULT); my $retcode = $?>>8; #print @result; #if( $retcode ) { print "return code: " . $retcode . "\n"; } return($retcode, @result); } sub run_interactive { system( @_ ); if ($? == -1) { printf "failed to execute: $!\n"; } elsif ($? & 127) { printf "child died with signal %d, %s coredump\n", ($? & 127), ($? & 128) ? 'with' : 'without'; } elsif( $? >> 8 != 0 ) { printf "child exited with value %d\n", $? >> 8; } return( $? >> 8 ); } ##################################################################### # # functions sub help(;@) { if( @_ == 0 ) { usage(); } else { print "help for @_: ...\n"; } } sub login(@) { check_parameter(@_,1); #check_env(); #$DASSCM_USER $DASSCM_PW my $output_user = ""; if( $DASSCM_USER ) { $output_user = " ($DASSCM_USER)"; } print "Enter DASSCM user name",$output_user,": "; my $input_user = ; chomp($input_user); print "Enter DASSCM user password: "; my $input_pw = ; chomp($input_pw); # TODO: test svn login $ENV{'DASSCM_USER'} = $input_user; $ENV{'DASSCM_PW'} = $input_pw; exec( "bash" ) or die "can't login"; } # # add (is used for command add and commit) # sub add(@) { check_parameter(@_,1); check_env(); (my $basename, my $dirname_prod, my $dirname_repo, my $filename_prod, my $filename_repo) = get_filenames($_[0]); if( $command eq "add" ) { mkpath($dirname_repo); } # update complete repository my $retcode = run_interactive( "$SVN update $svnOptions $DASSCM_REPO" ); copy( $filename_prod, $filename_repo ) or die $!; if( $command eq "add" ) { # already checked in? chdir($DASSCM_REPO); # also add the path to filename. for my $dir (split('/', $dirname_prod) ) { if( $dir ) { run_command( "$SVN add --non-recursive $dir" ); chdir $dir; } } run_command( "$SVN add $basename" ); } if( $options{'message'} ) { $svnOptions .= " --message \"$options{'message'}\" "; } # commit calls $EDITOR. uses "system" here, to display output $retcode = run_interactive( "$SVN commit $svnOptions --username $DASSCM_USER $DASSCM_REPO" ); print $filename_prod."\n"; print $dirname_repo."\n"; } sub blame(@) { check_parameter(@_,1); check_env(); (my $basename, my $dirname_prod, my $dirname_repo, my $filename_prod, my $filename_repo) = get_filenames($_[0]); my $retcode = run_interactive( "$SVN blame $svnOptions $filename_repo" ); } sub diff(@) { check_parameter(@_,1); check_env(); (my $basename, my $dirname_prod, my $dirname_repo, my $filename_prod, my $filename_repo) = get_filenames($_[0]); #print "$basename,$dirname_prod,$dirname_repo\n"; (my $rc_update, my @result)=run_command( "$SVN update $filename_repo" ); if( $rc_update != 0 ) { print @result; die; } (my $rc_diff, my @diff)=run_command( "diff $filename_repo $filename_prod" ); print @diff; } ##################################################################### # # main # my $number_arguments = @ARGV; if ($number_arguments > 0) { # get subcommand and remove it from @ARGV $command = $ARGV[0]; shift @ARGV; # get command line options and store them in options hash my $result = GetOptions ( \%options, 'message=s' ); # print options foreach my $option (keys %options) { print $option.": ".$options{$option}."\n"; } $_=$command; if (m/help/i) { help(@ARGV); } elsif (m/login/i) { # rewrite command. just to make sure login( @ARGV ); } elsif (m/add/i) { # rewrite command. just to make sure $command = "add"; add( @ARGV); } elsif (m/commit/i) { # rewrite command. just to make sure $command = "commit"; add( @ARGV); } elsif (m/blame/i) { blame(@ARGV); } elsif (m/diff/i) { diff(@ARGV); } elsif (m/activate/i) { activate(@ARGV); } else { usage(); check_env(); } # login # commitall # revert # status (chkconf) }