source: dasscm/trunk/usr/bin/dasscm@ 884

Last change on this file since 884 was 884, checked in by joergs, on Jun 15, 2010 at 11:21:02 PM

preparation for bash completion

  • Property keyword set to id
  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 41.8 KB
RevLine 
[186]1#!/usr/bin/perl -w
2
3# $Id: dasscm 884 2010-06-15 21:21:02Z joergs $
4
5use strict;
6
[208]7use Env
[235]8 qw($DASSCM_PROD $DASSCM_REPO $USER $DASSCM_USERNAME $DASSCM_USER $DASSCM_PASSWORD $SHELL);
[186]9use Cwd;
[214]10use Getopt::Long;
[186]11use File::Basename;
[209]12use File::Compare;
[802]13# used system("cp -a"), because File::Copy does not keep permissions
14#use File::Copy;
[237]15use File::Find;
[186]16use File::stat;
17use File::Path;
[214]18use Term::ReadKey;
[239]19
[234]20#use Data::Dumper;
[186]21
[189]22#####################################################################
23#
[186]24# global
[189]25#
[205]26
[253]27# shell exit codes
[252]28my $RETURN_OK = 0;
29my $RETURN_NOK = 1;
30
[277]31# Nagios return codes
[290]32my $RETURN_WARN = 1;
33my $RETURN_CRIT = 2;
[277]34my $RETURN_UNKNOWN = 3;
35
[238]36# documentation file (for usage)
37my $doc_file = "/usr/share/doc/packages/dasscm/dasscm_howto.txt";
38
[884]39my $config_file = "/etc/dasscm.conf";
40my $config = get_config($config_file);
[252]41
[884]42
43
44my %COMMANDS = (
45 '--help' => 'help',
46 'help' => 'help',
47 'login' => 'login',
48 'init' => 'init',
49 'ls' => 'ls',
50 'update' => 'update',
51 'up' => 'update',
52 'add' => 'add',
53 'commit' => 'commit',
54 'checkin' => 'commit',
55 'ci' => 'commit',
56 'revert' => 'revert',
57 'blame' => 'blame',
58 'diff' => 'diff',
59 'status' => 'status',
60 'st' => 'status',
61 'check' => 'check',
62 'permissions' => 'permissions',
63 'cleanup' => 'cleanup',
64 'complete' => 'complete'
65);
66
67# desc: description (eg. for usage)
68# params: parameters
69# CMD
70# USER
71# PATH
72# REPOPATH
73# require:
74# WRITE commands that require write access (and therefore a login)
75my %COMMAND_DEFINITIONS = (
76 'help' => {
77 'desc' => [],
78 'params' => [ "CMD" ],
79 'function' => \&help,
80 },
81 'login' => {
82 'desc' => [],
83 'params' => [ "USER" ],
84 'function' => \&login
85 },
86 'init' => {
87 'desc' => [ "initialize local subversion checkout.", "This is the first thing to do (after configuring $config_file)" ],
88 'params' => [],
89 'function' => \&init
90 },
91 'ls' => {
92 'desc' => [],
93 'params' => [ "PATH" ],
94 'function' => \&ls
95 },
96 'update' => {
97 'desc' => [],
98 'params' => [ "PATH" ],
99 'function' => \&update
100 },
101 'add' => {
102 'desc' => [],
103 'params' => [ "PATH" ],
104 'require' => [ "WRITE" ],
105 'function' => \&add
106 },
107 'commit' => {
108 'desc' => [],
109 'params' => [ "PATH" ],
110 'require' => [ "WRITE" ],
111 'function' => \&commit
112 },
113 'revert' => {
114 'desc' => [ "revert local changes back to version from repository" ],
115 'params' => [ "REPOPATH" ],
116 'function' => \&revert
117 },
118 'blame' => {
119 'desc' => [],
120 'params' => [ "PATH" ],
121 'function' => \&blame
122 },
123 'diff' => {
124 'desc' => [],
125 'params' => [ "PATH" ],
126 'function' => \&diff
127 },
128 'status' => {
129 'desc' => [],
130 'params' => [ "PATH" ],
131 'function' => \&status
132 },
133 'check' => {
134 'desc' => [ "perform Nagios NRPE conform check" ],
135 'params' => [],
136 'function' => \&check
137 },
138 'permissions' => {
139 'desc' => [],
140 'params' => [],
141 'function' => \&permissions
142 },
143 'cleanup' => {
144 'desc' => [],
145 'params' => [],
146 'function' => \&cleanup
147 },
148 'complete' => {
149 'desc' => [ "internally, used for bash completion" ],
150 'params' => [ "CMD" ],
151 'function' => \&complete
152 },
153);
154
155
[215]156# configuration file
[205]157my $DASSCM_LOCAL_REPOSITORY_BASE;
158my $DASSCM_REPOSITORY_NAME;
159my $DASSCM_SVN_REPOSITORY;
[247]160my $DASSCM_CHECKOUT_USERNAME;
161my $DASSCM_CHECKOUT_PASSWORD;
[286]162my $DASSCM_PERMISSION_FILE;
[205]163
[238]164# current directory at program start
165my $StartDirectory = cwd();
166
[268]167my $diff = "diff --exclude .svn ";
[205]168my $SVN = "svn ";
169my $svnOptions = "";
170my $svnCheckoutCredentials = "";
171my $svnPasswordCredentials = "";
[275]172
[268]173# flag. Set to true by svn_update
174# This prevents, that svn_update is called multiple times
175my $svnRepositoryIsUptodate = 0;
[205]176
[196]177# command line options get stored in options hash
[205]178my %options = ();
179
[197]180# subcommand, that gets executed (add, commit, ...)
[196]181my $command;
[186]182
[205]183my $verbose = 0;
184
[189]185#####################################################################
186#
[186]187# util functions
[189]188#
[187]189sub usage()
190{
[283]191 print '$Id: dasscm 884 2010-06-15 21:21:02Z joergs $';
192 print "\n\n";
[205]193 print "usage: dasscm <subcommand> [options] [args]\n";
194 print "\n";
195 print "dasscm is intended to help versioning configuration files\n";
196 print "\n";
197 print "Available subcommands:\n";
[884]198 # print " help <subcommand>\n";
199 # print " init\n";
200 # print " login <username>\n";
201 # print " up <path>\n";
202 # print " ls <path>\n";
203 # print " add <path>\n";
204 # print " commit <path>\n";
205 # print " revert <path>\n";
206 # print " diff <path>\n";
207 # print " status <path>\n";
208 # print " check\n";
209 # print " cleanup\n";
210 # print " permissions\n";
211 foreach my $i (sort keys(%COMMAND_DEFINITIONS)) {
212 print " ", $i, " ", join( " ", get_command_possible_params($i) ), "\n";
213 foreach my $line ( get_command_desc($i) ) {
214 print " "x20, $line, "\n";
215 }
216 }
[205]217 print "\n";
[800]218 print "If dasscm is not yet configured, read $doc_file\n";
[187]219}
220
[233]221sub warning(@)
222{
223 print "Warning: " . join( "\n ", @_ ) . "\n";
224}
225
226sub error(@)
227{
228 print "Error: " . join( "\n ", @_ ) . "\n";
229}
230
231sub fatalerror(@)
232{
[239]233 error(@_);
234
[233]235 #print "Exiting\n";
[239]236 exit 1;
[233]237}
238
[238]239#
240# reading config file and return key/value pairs as hash
241#
[234]242sub get_config
243{
[239]244 my $file = $_[0];
[234]245
[239]246 if ( !$file ) {
[234]247 fatalerror( "failed to open config file" . $file );
248 }
249
250 my $data = {};
251
252 # try to open config file
253 if ( !open( FH, $file ) ) {
254 fatalerror( "failed to open config file" . $file );
255 } else {
256 while (<FH>) {
257 chomp;
258 if (/^#/) {
259 next;
260 }
261 if ( $_ =~ /=/g ) {
[239]262
[238]263 # splitting in 2 fields at maximum
[234]264 my ( $option, $value ) = split( /=/, $_, 2 );
265 $option =~ s/^\s+//g;
266 $option =~ s/\s+$//g;
267 $option =~ s/\"+//g;
268 $value =~ s/^\s+//g;
269 $value =~ s/\s+$//g;
270 $value =~ s/\"+//g;
271
272 if ( length($option) ) {
273 $data->{$option} = $value;
274 }
275 }
276 }
277 }
278 close(FH);
279
280 return $data;
281}
282
[270]283#
284# check and evaluate environment variables
285#
[186]286sub check_env()
287{
[205]288
289 # DASSCM_PROD
290 if ( !$DASSCM_PROD ) {
291 $DASSCM_PROD = "/";
292 }
293
294 if ( !-d $DASSCM_PROD ) {
295 die "DASSCM_PROD ($DASSCM_PROD) is not set to a directory.\n";
296 }
297 if ($verbose) { print "DASSCM_PROD: " . $DASSCM_PROD . "\n"; }
298
299 # DASSCM_REPOSITORY_NAME
[208]300 if ( !$DASSCM_REPOSITORY_NAME ) {
301 die
302 "Variable DASSCM_REPOSITORY_NAME is not defined.\nIt needs to be a unique name.\nNormally the full qualified host name is used.\nUse file $config_file to configure it.\n";
303 }
[205]304
305 # DASSCM_REPO
306 if ( !$DASSCM_REPO ) {
307 if ( $DASSCM_LOCAL_REPOSITORY_BASE && $DASSCM_REPOSITORY_NAME ) {
308 $DASSCM_REPO =
309 $DASSCM_LOCAL_REPOSITORY_BASE . "/" . $DASSCM_REPOSITORY_NAME;
310 } else {
311 die
312 "Envirnonment variable DASSCM_REPO not set.\nSet DASSCM_REPO to the directory of the versioning system checkout for this machine.\n";
313 }
314 }
[215]315 if ($verbose) { print "DASSCM_REPO: " . $DASSCM_REPO . "\n"; }
[205]316
317 #
[248]318 # subversion checkout user
319 #
[252]320 if ( !$DASSCM_CHECKOUT_USERNAME ) {
321 fatalerror(
[248]322 "variable DASSCM_CHECKOUT_USERNAME is not defined.",
[252]323 "Use file $config_file to configure it."
324 );
[248]325 }
326
[252]327 if ( !$DASSCM_CHECKOUT_PASSWORD ) {
328 fatalerror(
[248]329 "variable DASSCM_CHECKOUT_PASSWORD is not defined.",
[252]330 "Use file $config_file to configure it."
331 );
[248]332 }
333
334 #
[239]335 # check if local repository directory exist
[235]336 # (if not creating by init)
[205]337 #
338 if ( $command ne "init" ) {
339 if ( not -d $DASSCM_REPO ) {
340 die
[208]341 "Can't access local repository DASSCM_REPO\n($DASSCM_REPO)\nCheck configuration and execute\n dasscm init\n";
[205]342 }
[208]343
[205]344 #
345 # user settings
346 #
[208]347
[205]348 # DASSCM_USER is legacy. Use DASSCM_USERNAME instead
[208]349 if ( !$DASSCM_USERNAME ) {
350 $DASSCM_USERNAME = $DASSCM_USER;
[205]351 }
352
353 # user root is not allowed for checkins.
354 # if user is root, DASSCM_USER has to be set,
355 # otherwise USER can be used
356 if ( "$USER" eq "root" ) {
[252]357 if ( ( not $DASSCM_USERNAME )
[884]358 and ( get_command_requires_write( $command ) ) )
[252]359 {
360
361 #( $command ne "login" ) and ( $command ne "status" ) ) {
362 fatalerror(
363 "Envirnonment variable DASSCM_USERNAME not set.",
364 "Set DASSCM_USERNAME to your subversion user account or",
365 "use 'dasscm login'"
366 );
[205]367 }
368 $svnOptions .= " --no-auth-cache ";
369 } elsif ( !$DASSCM_USERNAME ) {
370 $DASSCM_USERNAME = $USER;
371 }
372
373 #
374 # password
375 #
[208]376 if ($DASSCM_PASSWORD) {
[267]377 $svnPasswordCredentials = " --password '$DASSCM_PASSWORD' ";
[205]378 }
379 }
380
381 #$svnOptions .= " --username $DASSCM_USERNAME "
[186]382}
383
[270]384#
385# has been intendend,
386# to check addtitional parameters.
387# Currently not used.
388#
[186]389sub check_parameter(@)
390{
391}
392
[884]393sub get_command_uniform_name( $ )
394{
395 my $command_abbrivation = $_[0];
396 if( defined($COMMANDS{$command_abbrivation}) ) {
397 return $COMMANDS{$command_abbrivation};
398 }
399 return;
400}
401
402sub get_command_desc( $ )
403{
404 my $command = get_command_uniform_name($_[0]);
405 my @desc = ();
406 if( $command && defined($COMMAND_DEFINITIONS{$command}{'desc'}) ) {
407 @desc = @{$COMMAND_DEFINITIONS{$command}{'desc'}};
408 }
409 return @desc;
410}
411
412sub get_command_function( $ )
413{
414 my $command = get_command_uniform_name($_[0]);
415 my $func;
416 if( $command && defined($COMMAND_DEFINITIONS{$command}{'function'}) ) {
417 $func = $COMMAND_DEFINITIONS{$command}{'function'};
418 }
419 return $func;
420}
421
422sub get_command_possible_params( $ )
423{
424 my $command = get_command_uniform_name($_[0]);
425 my @params = ();
426 if( $command && defined($COMMAND_DEFINITIONS{$command}{'params'}) ) {
427 @params = @{$COMMAND_DEFINITIONS{$command}{'params'}};
428 }
429 return @params;
430}
431
432sub get_command_requirements( $ )
433{
434 my $command = get_command_uniform_name($_[0]);
435 my @requirements = ();
436 if( $command && defined($COMMAND_DEFINITIONS{$command}{'require'}) ) {
437 @requirements = @{$COMMAND_DEFINITIONS{$command}{'require'}};
438 }
439 return @requirements;
440}
441
442sub get_command_requires_write( $ )
443{
444 return grep( /^WRITE$/, get_command_requirements($_[0]) );
445}
446
447
[238]448#
[287]449# normalize path namens:
450# - directories should end with "/"
451# - use only single "/"
452#
453sub normalize_path($)
454{
455 my $path = shift || "";
456
[290]457 if ( $path =~ m|^/| ) {
458
[287]459 # full path
[290]460 if ( -d $path ) {
461
[287]462 # ensure, a directory ends with '/'
463 $path .= '/';
464 }
[290]465 } elsif ( -d cwd() . '/' . $path ) {
466
467 # ensure, a directory ends with '/'
468 $path .= '/';
[287]469 }
470
471 # remove double (triple) slashes (/)
472 $path =~ s|/[/]*|/|g;
473
474 return $path;
475}
476
477#
[239]478# generate from (relative) filename
[238]479# all required file and directory names:
480# $basename, $dirname_prod, $dirname_repo,
481# $filename_prod, $filename_repo
482#
[187]483sub get_filenames(@)
484{
[250]485 my $filename_prod = $_[0] || ".";
[237]486
[238]487 # make filename absolut
[205]488 if ( !( $filename_prod =~ m/^\// ) ) {
[270]489 $filename_prod = cwd() . '/' . $filename_prod;
[205]490 }
[187]491
[800]492 # file must be readable. Only exception is, when file should be reverted
493 if ( $command ne "revert" ) {
494 if ( not -r $filename_prod ) {
495 fatalerror( $filename_prod . " is not accessable" );
496 }
[233]497 }
[205]498
[274]499 # dirname buggy: eg. "/etc/" is reduced to "/",
500 # "/etc" is used as filename
501 # herefore make sure, that if filename is a directory,
502 # it will end by "/"
[290]503 $filename_prod = normalize_path($filename_prod);
[238]504
[270]505 ( my $basename, my $dirname_prod ) = fileparse($filename_prod);
506
[801]507 # normalize path.
[800]508 # not done for reverting, because in this case, the directory may not exist
509 # and the correct path should already be stored in the repository
510 if ( $command ne "revert" ) {
[801]511
[800]512 # uses chdir to determine real directory in a unique way
[801]513 chdir $dirname_prod
514 or fatalerror( "failed to access directory $dirname_prod: " . $! );
[800]515 $dirname_prod = normalize_path( cwd() );
516 chdir $StartDirectory;
517 }
[238]518
[287]519 my $dirname_repo = normalize_path( $DASSCM_REPO . "/" . $dirname_prod );
[290]520 my $filename_repo = normalize_path("$dirname_repo/$basename");
[287]521
[214]522 if ($verbose) {
[287]523 print "filename_repo: " . $filename_repo . "\n";
[290]524 print "dirname_repo: " . $dirname_repo . "\n";
[287]525 print "filename_prod: " . $filename_prod . "\n";
[290]526 print "dirname_prod: " . $dirname_prod . "\n";
[287]527 print "basename: " . $basename . "\n";
[214]528 }
[205]529
530 return (
531 $basename, $dirname_prod, $dirname_repo,
532 $filename_prod, $filename_repo
533 );
[187]534}
535
[271]536sub copy_file_to_repository( $ )
537{
538 my $filename = shift;
[256]539
[271]540 (
541 my $basename,
542 my $dirname_prod,
543 my $dirname_repo,
544 my $filename_prod,
545 my $filename_repo
[801]546 ) = get_filenames($filename);
[271]547
[802]548 #copy( $filename_prod, $filename_repo )
[803]549 ( my $rc, my @result ) = run_command( "cp -a \"$filename_prod\" \"$filename_repo\"" );
[802]550 if( $rc != 0 ) {
551 error( "failed to copy $filename_prod to repository: ", @result );
552 }
553
554 # return success
555 return $rc == 0;
[271]556}
557
[802]558
559
560sub copy_file_from_repository_to_system( $ )
561{
562 my $filename = shift;
563
564 (
565 my $basename,
566 my $dirname_prod,
567 my $dirname_repo,
568 my $filename_prod,
569 my $filename_repo
570 ) = get_filenames($filename);
571
[803]572 ( my $rc, my @result ) = run_command( "cp -a \"$filename_repo\" \"$filename_prod\"" );
[802]573 if( $rc != 0 ) {
574 error( "failed to copy $filename_repo to $filename_prod: ", @result );
575 }
576
577 # return success
578 return $rc == 0;
579}
580
581
582
[256]583#
584# creates a file with permissions
585#
[215]586sub generatePermissionList
[209]587{
588
[215]589 # generieren der Zeilen für Permission-Savefile
590 my @files = @_;
591 my @permlist = ();
592 foreach my $file (@files) {
[227]593 $file = "/" . $file;
[239]594 if ( -e $file ) {
595 my $info = stat($file) || die "failed to stat $file: aborting";
596 my $mode = get_type( $info->mode ) & 07777;
[227]597 my $modestring = sprintf( "%04o", $mode );
[278]598 my $uidnumber = $info->uid;
599 my $uid = getpwuid($uidnumber) || $uidnumber;
600 my $gidnumber = $info->gid;
601 my $gid = getgrgid($gidnumber) || $gidnumber;
[227]602 push(
603 @permlist,
604 sprintf( "%-55s %-17s %4d",
[278]605 $file, "${uid}:${gid}", $modestring )
[227]606 );
607 }
[215]608 }
609 return @permlist;
610}
[209]611
[215]612sub get_type
613{
[209]614
[215]615 # Funktion übernommen aus /usr/bin/chkstat
616 my $S_IFLNK = 0120000; # symbolic link
617 my $S_IFREG = 0100000; # regular file
618 my $S_IFDIR = 0040000; # directory
619 my $S_IFCHAR = 0020000; # character device
620 my $S_IFBLK = 0060000; # block device
621 my $S_IFFIFO = 0010000; # fifo
622 my $S_IFSOCK = 0140000; # socket
623 my $S_IFMT = 0170000; # type of file
[209]624
[215]625 my $S_m;
626 if ( ( $_[0] & $S_IFMT ) == $S_IFLNK ) { $S_m = $_[0] - $S_IFLNK; }
627 elsif ( ( $_[0] & $S_IFMT ) == $S_IFREG ) { $S_m = $_[0] - $S_IFREG; }
628 elsif ( ( $_[0] & $S_IFMT ) == $S_IFDIR ) { $S_m = $_[0] - $S_IFDIR; }
629 elsif ( ( $_[0] & $S_IFMT ) == $S_IFCHAR ) { $S_m = $_[0] - $S_IFCHAR; }
630 elsif ( ( $_[0] & $S_IFMT ) == $S_IFBLK ) { $S_m = $_[0] - $S_IFBLK; }
631 elsif ( ( $_[0] & $S_IFMT ) == $S_IFFIFO ) { $S_m = $_[0] - $S_IFFIFO; }
632 elsif ( ( $_[0] & $S_IFMT ) == $S_IFSOCK ) { $S_m = $_[0] - $S_IFSOCK; }
633 $S_m;
[209]634}
635
[186]636sub run_command
637{
[205]638 my $command = shift;
[186]639
[205]640 #print "executing command: " . $command . "\n";
[186]641
[205]642 open( RESULT, $command . ' 2>&1 |' );
643 my @result = <RESULT>;
644 close(RESULT);
645 my $retcode = $? >> 8;
[186]646
[205]647 #print @result;
648 #if( $retcode ) { print "return code: " . $retcode . "\n"; }
[186]649
[205]650 return ( $retcode, @result );
[186]651}
652
[205]653sub run_interactive
654{
[186]655
[208]656 if ($verbose) {
[205]657 print "run_interactive:" . join( " ", @_ ) . "\n";
658 }
[196]659
[205]660 system(@_);
661 if ( $? == -1 ) {
662 printf "failed to execute: $!\n";
663 } elsif ( $? & 127 ) {
664 printf "child died with signal %d, %s coredump\n", ( $? & 127 ),
665 ( $? & 128 ) ? 'with' : 'without';
666 } elsif ( $? >> 8 != 0 ) {
667 printf "child exited with value %d\n", $? >> 8;
668 }
669 return ( $? >> 8 );
670}
671
[247]672sub svn_check_credentials( $$;$$ )
[196]673{
[205]674 my $username = shift;
675 my $password = shift;
676
[252]677 # check silently are allow user interaction?
[247]678 my $interactive = shift || 0;
[220]679
[247]680 # default: exit program, if repository is not accessable
681 # (do not exit for 'init')
682 my $fatalerror = shift || 1;
683
684 print "checking credentials ";
685
[239]686 if ( !$username ) {
687 fatalerror("no username given");
[238]688 }
689
[239]690 if ( !$password ) {
691 fatalerror("no password given");
[238]692 }
693
[247]694 print "for " . $username . "@" . $DASSCM_SVN_REPOSITORY . ": ";
695
[220]696 # Options for "svn info" are not supported by subversion 1.0.0 (SLES9),
697 # therefore switching to "svn status"
698 # ( my $rc_update, my @result ) =
699 # run_command(
700 # "$SVN info --non-interactive --no-auth-cache --username $username --password $password $DASSCM_SVN_REPOSITORY"
701 # );
702 #print @result;
703
[247]704 my $rc_update;
[252]705 if ($interactive) {
[801]706 $rc_update = run_interactive(
[267]707 "$SVN ls --no-auth-cache --username '$username' --password '$password' $DASSCM_SVN_REPOSITORY"
[801]708 );
[247]709 } else {
[801]710 ( $rc_update, my @result ) = run_command(
[267]711 "$SVN ls --non-interactive --no-auth-cache --username '$username' --password '$password' $DASSCM_SVN_REPOSITORY"
[801]712 );
[252]713
[247]714 if ( $rc_update != 0 ) {
715 print "\n", @result;
[252]716 if ($fatalerror) {
[247]717 fatalerror();
718 }
719 return;
720 }
[205]721 }
722
[247]723 # return success
724 return $rc_update == 0;
[196]725}
726
[205]727sub svn_update( ;$ )
728{
[270]729 my $update_path = shift || "";
730
[797]731 # return value
732 my $update_ok = 1;
733
[270]734 # use this flag to do only one update per run
[275]735 if ( !$svnRepositoryIsUptodate ) {
[801]736 ( my $rc_update, my @result ) = run_command(
[275]737 "$SVN update --non-interactive $svnCheckoutCredentials '$DASSCM_REPO/$update_path'"
[801]738 );
[268]739 print @result;
740 if ( $rc_update != 0 ) {
[290]741 error("failed to update local repository ($update_path)");
[797]742 $update_ok = 0;
[270]743 } elsif ( not $update_path ) {
[275]744
[270]745 # set this flag if a full update is done
[268]746 $svnRepositoryIsUptodate = 1;
747 }
[205]748 }
[797]749 return $update_ok;
[215]750}
[196]751
[271]752sub svn_ls( ;@ )
[215]753{
[270]754 (
755 my $basename,
756 my $dirname_prod,
757 my $dirname_repo,
758 my $filename_prod,
759 my $filename_repo
[801]760 ) = get_filenames( $_[0] );
[220]761
[218]762 # svn ls -R is better, but much, much slower
763 # ( my $rc, my @result ) = run_command("$SVN ls --recursive $svnCheckoutCredentials $path");
[270]764
[271]765 my @files = ();
766 my @links = ();
767 my @dirs = ();
768 my @others = ();
769
[289]770 find(
771 {
772 wanted => sub {
773 my $name = normalize_path($File::Find::name);
774 $name =~ s|^$dirname_repo||;
[290]775
[289]776 #print "($name)\n";# . $File::Find::dir . "\n";
777 if ( not $name ) {
[290]778
[289]779 # name string is empty (top directory).
780 # do nothing
781 } elsif ( $name =~ m/\.svn/ ) {
[275]782
[289]783 # skip svn meta data
784 } elsif ( -l $_ ) {
[275]785
[289]786 # soft link
787 # important: check for links first
788 # to exclude them from further checks
789 push( @links, $name );
790 } elsif ( -d $_ ) {
[290]791
792 # directories
793 push( @dirs, $name );
[289]794 } elsif ( -f $_ ) {
[275]795
[289]796 # regular file
797 push( @files, $name );
798 } else {
799 push( @others, $name );
800 }
[290]801 }
[289]802 },
803 ($filename_repo)
804 );
[271]805
[287]806 return ( sort( @dirs, @files ) );
[205]807}
808
[274]809sub svn_revert( ;$ )
810{
811 my $path = shift || $DASSCM_REPO;
812
[275]813 ( my $rc_update, my @result ) = run_command("$SVN revert -R '$path'");
[274]814
815 if ( $rc_update != 0 ) {
816 print "\n", @result;
[275]817 error("failed to revert subversion repository changes");
[274]818 }
819}
820
[285]821sub svn_remove_unknown_files( ;$ )
822{
823 my $path = shift || $DASSCM_REPO;
824
[290]825 ( my $rc_update, my @result ) = run_command("$SVN status '$path'");
[285]826
827 if ( $rc_update != 0 ) {
828 print "\n", @result;
829 error("failed to receive subversion repository information");
830 } else {
[290]831 foreach (@result) {
832 if (s/^\? +//) {
[285]833 chomp;
[290]834
[285]835 # if file is unknown to subversion (line starts with "?")
836 # remove it
837 print "removing $_\n";
[801]838
[800]839 # unlink doesn't work recursive, there "rm -rf" is used
840 #unlink($_);
[801]841 system("rm -rf $_");
[285]842 }
843 }
844 }
845}
846
[268]847sub getModifiedFiles( ;$ )
848{
[270]849 (
850 my $basename,
851 my $dirname_prod,
852 my $dirname_repo,
853 my $filename_prod,
854 my $filename_repo
[801]855 ) = get_filenames( $_[0] );
[268]856
[275]857 my @files = svn_ls($filename_prod);
[270]858
[268]859 # stores result from status (cvscheck)
860 my %removedfiles = ();
861 my %changedfiles = ();
[278]862 my %unknownfiles = ();
[268]863
864 # create list of modified files
865 if (@files) {
866
867 foreach my $file (@files) {
868
[271]869 my $realfile = $dirname_prod . $file;
870 my $cvsworkfile = $dirname_repo . $file;
[268]871
872 if ( -d $realfile ) {
[290]873
[278]874 # directory
[290]875 if ( !-d "$cvsworkfile" ) {
876
[278]877 # real is directory, repository is not. This is a problem
878 $changedfiles{"$realfile"} = $cvsworkfile;
879 }
880 } elsif ( !-e $realfile ) {
881 $removedfiles{"$realfile"} = $cvsworkfile;
[268]882 } elsif ( !-r $realfile ) {
[290]883
[278]884 # don't have permission to read the file,
885 # can't check it
886 $unknownfiles{"$realfile"} = $cvsworkfile;
[268]887 } else {
888 ( -r "$cvsworkfile" )
[278]889 || fatalerror("failed to read $cvsworkfile");
[268]890 if ( compare( $cvsworkfile, $realfile ) != 0 ) {
891 $changedfiles{"$realfile"} = $cvsworkfile;
892 }
893 }
894 }
895 }
896
[278]897 return ( \%changedfiles, \%removedfiles, \%unknownfiles );
[268]898}
899
[238]900#
901# from an array of files/dirs,
902# generates list of files
903# sorted by type
904#
[237]905sub get_files( @ )
906{
907 my @files = ();
908 my @links = ();
909 my @dirs = ();
910 my @others = ();
911
[239]912 if (@_) {
913 find(
914 {
915 wanted => sub {
916 my $fullname = cwd() . "/" . $_;
917 if ( -l $_ ) {
918
919 # soft link
920 # important: check for links first
921 # to exclude them from further checks
922 push( @links, $fullname );
923 } elsif ( -d $_ ) {
[271]924
925 # directories
[239]926 push( @dirs, $fullname );
927 } elsif ( -f $_ ) {
928
929 # regular file
930 push( @files, $fullname );
931 } else {
932 push( @others, $fullname );
933 }
934 }
935 },
936 @_
937 );
[237]938 }
939
[239]940 # don't rely on others.
[237]941 # If more specific file types are needed,
942 # they will be added
943 return {
[239]944 files => \@files,
945 links => \@links,
946 dirs => \@dirs,
947 others => \@others
948 };
[237]949}
950
[189]951#####################################################################
952#
[186]953# functions
954sub help(;@)
955{
[205]956 if ( @_ == 0 ) {
957 usage();
958 } else {
959 print "help for @_: ...\n";
[214]960 usage();
[205]961 }
[186]962}
963
[203]964sub login(@)
965{
[205]966 check_parameter( @_, 1 );
967 check_env();
[203]968
[235]969 my $input_username = $_[0];
[214]970
971 if ( not $input_username ) {
972 my $output_username = "";
973 if ($DASSCM_USERNAME) {
974 $output_username = " ($DASSCM_USERNAME)";
975 }
976
977 print "Enter DASSCM user name", $output_username, ": ";
978 $input_username = <STDIN>;
979 chomp($input_username);
[247]980
981 $input_username = $input_username || $DASSCM_USERNAME;
[205]982 }
[203]983
[205]984 # hidden password input
[247]985 print "Enter password for $input_username: ";
[205]986 ReadMode('noecho');
987 my $input_password = <STDIN>;
988 ReadMode('normal');
989 chomp($input_password);
[220]990 print "\n";
[203]991
[247]992 # checking checkout username/password
[252]993 svn_check_credentials( $DASSCM_CHECKOUT_USERNAME,
994 $DASSCM_CHECKOUT_PASSWORD );
[247]995 print "checkout access okay\n";
[205]996
[247]997 svn_check_credentials( $input_username, $input_password );
998
[205]999 #
1000 # set environment variables
1001 #
[267]1002 $ENV{'DASSCM_USERNAME'} = "$input_username";
1003 $ENV{'DASSCM_PASSWORD'} = "$input_password";
[205]1004
[209]1005 print "subversion access okay\n\n", "DASSCM_USERNAME: $input_username\n",
1006 "DASSCM_PASSWORD: (hidden)\n", "DASSCM_PROD: $DASSCM_PROD\n",
1007 "DASSCM_REPO: $DASSCM_REPO\n",
[278]1008 "Server Repository: $DASSCM_SVN_REPOSITORY\n", "\n";
[205]1009
[278]1010 status();
1011
1012 print "\n[dasscm shell]\n\n";
[235]1013 my $shell = $SHELL || "bash";
1014 exec($shell) or die "failed to start new shell";
[203]1015}
1016
[260]1017#
1018# initialize local checkout directory (initial checkout)
1019#
[205]1020sub init(@)
1021{
1022 check_parameter( @_, 1 );
1023 check_env();
1024
[235]1025 # don't do repository creation (svn mkdir) here,
1026 # because then their must be a lot of prior checks
1027
[205]1028 # update complete repository
[216]1029 # and create permission file
[801]1030 my $retcode = run_interactive(
[286]1031 "cd $DASSCM_LOCAL_REPOSITORY_BASE; $SVN checkout $svnCheckoutCredentials $svnOptions $DASSCM_SVN_REPOSITORY; mkdir -p `dirname $DASSCM_PERMISSION_FILE`; touch $DASSCM_PERMISSION_FILE"
[801]1032 );
[205]1033}
1034
[215]1035sub ls(@)
[186]1036{
[205]1037 check_parameter( @_, 1 );
1038 check_env();
[186]1039
[271]1040 my @files = svn_ls(@_);
[215]1041
[275]1042 if (@files) {
[274]1043 print join( "\n", @files );
1044 print "\n";
1045 }
[215]1046}
1047
1048sub update(@)
1049{
1050 check_parameter( @_, 1 );
1051 check_env();
1052
1053 #
1054 # update local repository
1055 #
1056 svn_update();
1057}
1058
[237]1059#
1060# helper function for "add" command
1061#
[215]1062sub add_helper(@)
1063{
[205]1064 (
1065 my $basename,
1066 my $dirname_prod,
1067 my $dirname_repo,
1068 my $filename_prod,
1069 my $filename_repo
[801]1070 ) = get_filenames( $_[0] );
[186]1071
[274]1072 mkpath($dirname_repo);
[802]1073 copy_file_to_repository( $filename_prod );
[186]1074
[274]1075 # already checked in?
1076 chdir $DASSCM_REPO;
[205]1077
[274]1078 # also add the path to filename.
1079 for my $dir ( split( '/', $dirname_prod ) ) {
1080 if ($dir) {
[275]1081 my ( $rc, @out ) = run_command("$SVN add --non-recursive '$dir'");
[274]1082 if ( $rc > 0 ) {
1083 print join( "\n", @out );
[205]1084 }
[274]1085 chdir $dir;
[205]1086 }
1087 }
[275]1088 my ( $rc, @out ) = run_command("$SVN add '$basename'");
[274]1089 if ( $rc > 0 ) {
1090 print join( "\n", @out );
1091 }
1092 chdir $StartDirectory;
1093
[215]1094}
[205]1095
[215]1096#
[274]1097# adding new files (or directories)
[215]1098#
1099sub add(@)
1100{
1101 check_parameter( @_, 1 );
1102 check_env();
1103
1104 #
1105 # update local repository
1106 #
1107 svn_update();
1108
[237]1109 # get all regular files and links
[239]1110 my $href_files = get_files(@_);
[220]1111
[237]1112 #print Dumper( $href_files );
1113
[239]1114 my @files = @{ $href_files->{files} };
1115 my @links = @{ $href_files->{links} };
[237]1116
[239]1117 if (@files) {
[237]1118 my $number = $#files + 1;
1119 print "files to check-in ($number): \n";
1120 print join( "\n", @files );
1121 print "\n";
1122 }
1123
[268]1124 # TODO: check in links and also link target? At least warn about link target
[239]1125 if (@links) {
[237]1126 my $number = $#links + 1;
1127 print "\n";
1128 print "ignoring links ($number):\n";
1129 print join( "\n", @links );
1130 print "\n";
1131 }
1132
[238]1133 # TODO: confirm
1134
[237]1135 # copy files one by one to local repository
1136 for my $file (@files) {
[239]1137
[233]1138 # add file
[239]1139 add_helper($file);
[233]1140 }
1141
[215]1142 # create new permissions file
1143 permissions();
[220]1144
[215]1145 # add permissions file
[286]1146 add_helper($DASSCM_PERMISSION_FILE);
[215]1147
[205]1148 if ( $options{'message'} ) {
1149 $svnOptions .= " --message \"$options{'message'}\" ";
1150 }
1151
[239]1152 # commit calls $EDITOR.
[237]1153 # use "interactive" here, to display output
[801]1154 my $retcode = run_interactive(
[267]1155 "$SVN commit $svnOptions --username '$DASSCM_USERNAME' $svnPasswordCredentials $DASSCM_REPO"
[801]1156 );
[205]1157
[274]1158 # svn commit does not deliever an error return code, if commit is canceld,
1159 # so a revert is performed in any case
1160 svn_revert();
[186]1161}
1162
[271]1163#
1164# checks in all modified files
1165#
1166sub commit(@)
1167{
1168 check_parameter( @_, 1 );
1169 check_env();
1170
1171 (
1172 my $basename,
1173 my $dirname_prod,
1174 my $dirname_repo,
1175 my $filename_prod,
1176 my $filename_repo
[801]1177 ) = get_filenames( $_[0] );
[271]1178
1179 #
1180 # update local repository
1181 #
1182 svn_update();
1183
[275]1184 ( my $refChangedFiles, my $refRemovedFiles ) =
1185 getModifiedFiles($filename_prod);
[271]1186 my %changedfiles = %{$refChangedFiles};
1187 my %removedfiles = %{$refRemovedFiles};
1188
[275]1189 if (%removedfiles) {
1190 my $removedFilesString =
1191 '"' . join( '" "', values(%removedfiles) ) . '"';
1192 my ( $rc, @out ) = run_command("$SVN rm $removedFilesString");
[271]1193 if ( $rc > 0 ) {
1194 print join( "\n", @out );
1195 }
1196 }
1197
1198 # copy files one by one to local repository
1199 for my $file ( keys(%changedfiles) ) {
[275]1200 copy_file_to_repository($file);
[271]1201 }
1202
1203 # create new permissions file
1204 permissions();
1205
1206 # add permissions file
[286]1207 add_helper($DASSCM_PERMISSION_FILE);
[271]1208
1209 if ( $options{'message'} ) {
1210 $svnOptions .= " --message \"$options{'message'}\" ";
1211 }
1212
1213 # commit calls $EDITOR.
1214 # use "interactive" here, to display output
[801]1215 my $retcode = run_interactive(
[271]1216 "$SVN commit $svnOptions --username '$DASSCM_USERNAME' $svnPasswordCredentials $DASSCM_REPO"
[801]1217 );
[274]1218
1219 # svn commit does not deliever an error return code, if commit is canceld,
1220 # so a revert is performed in any case
1221 svn_revert();
[271]1222}
1223
[800]1224#
1225# revert: copies files back from repository to system
1226#
1227sub revert(@)
1228{
1229 check_parameter( @_, 1 );
1230 check_env();
1231
1232 (
1233 my $basename,
1234 my $dirname_prod,
1235 my $dirname_repo,
1236 my $filename_prod,
1237 my $filename_repo
[801]1238 ) = get_filenames( $_[0] );
[800]1239
1240 # return code for the shell
1241 # default: error
1242 my $return_code = $RETURN_OK;
1243
1244 # cleanup repository
[801]1245 cleanup();
[800]1246 #svn_update();
1247
1248 ( my $refChangedFiles, my $refRemovedFiles, my $refUnknownFiles ) =
1249 getModifiedFiles($filename_prod);
1250 my %changedfiles = %{$refChangedFiles};
1251 my %removedfiles = %{$refRemovedFiles};
1252 my %unknownfiles = %{$refUnknownFiles};
1253
1254 if ( %removedfiles or %changedfiles or %unknownfiles ) {
1255
1256 if (%removedfiles) {
1257 print "DELETED files and directories. Recreated from repository:\n";
[801]1258 my @removedPaths =
1259 ( sort { length $a > length $b } keys %removedfiles );
[800]1260 print join( "\n", @removedPaths ) . "\n\n";
1261
1262 # copy files one by one from local repository to system
1263 # and also create directories
1264 # paths are sorted, so that directories are created first
[801]1265 for my $real_path (@removedPaths) {
1266 if ( -d $removedfiles{"$real_path"} ) {
[800]1267 mkpath("$real_path");
1268 } else {
[802]1269 copy_file_from_repository_to_system( $real_path );
[800]1270 }
1271 }
1272 }
1273
1274 if (%changedfiles) {
1275 print "MODIFIED files. Copied from repository to the system:\n";
1276 print join( "\n", ( keys %changedfiles ) ) . "\n\n";
1277
1278 # copy files one by one from local repository to system
1279 for my $real_file ( keys(%changedfiles) ) {
[802]1280 copy_file_from_repository_to_system( $real_file );
[800]1281 }
1282
1283 }
1284
1285 if (%unknownfiles) {
1286 print "UNKNOWN: insufficient permission to check files:\n";
1287 print join( "\n", ( keys %unknownfiles ) ) . "\n\n";
1288
1289 $return_code = $RETURN_NOK;
1290 }
1291
1292 } else {
1293 print "no modified files found in $dirname_repo\n";
1294 }
1295
1296 return $return_code;
1297}
1298
[193]1299sub blame(@)
1300{
[205]1301 check_parameter( @_, 1 );
1302 check_env();
[193]1303
[205]1304 (
1305 my $basename,
1306 my $dirname_prod,
1307 my $dirname_repo,
1308 my $filename_prod,
1309 my $filename_repo
[801]1310 ) = get_filenames( $_[0] );
[205]1311
1312 my $retcode = run_interactive("$SVN blame $svnOptions $filename_repo");
[193]1313}
1314
[187]1315sub diff(@)
1316{
[205]1317 check_parameter( @_, 1 );
1318 check_env();
[187]1319
[205]1320 (
1321 my $basename,
1322 my $dirname_prod,
1323 my $dirname_repo,
1324 my $filename_prod,
1325 my $filename_repo
[801]1326 ) = get_filenames( $_[0] );
[205]1327
1328 #print "$basename,$dirname_prod,$dirname_repo\n";
1329
[797]1330 svn_update();
[205]1331
[238]1332 ( my $rc_diff, my @diff_result ) =
[239]1333 run_command( $diff . " $filename_repo $filename_prod" );
[238]1334
1335 print @diff_result;
[187]1336}
1337
[209]1338sub status(@)
1339{
1340 check_parameter( @_, 1 );
1341 check_env();
1342
[270]1343 (
1344 my $basename,
1345 my $dirname_prod,
1346 my $dirname_repo,
1347 my $filename_prod,
1348 my $filename_repo
[801]1349 ) = get_filenames( $_[0] || "/" );
[270]1350
[252]1351 # return code for the shell
1352 # default: error
1353 my $return_code = $RETURN_NOK;
1354
[209]1355 #
1356 # update local repository
1357 #
[278]1358 #svn_update( $filename_prod );
[209]1359
[278]1360 # check, if permissions have changed
1361 permissions();
1362
1363 # get modified files
1364 ( my $refChangedFiles, my $refRemovedFiles, my $refUnknownFiles ) =
[275]1365 getModifiedFiles($dirname_prod);
[268]1366 my %changedfiles = %{$refChangedFiles};
1367 my %removedfiles = %{$refRemovedFiles};
[278]1368 my %unknownfiles = %{$refUnknownFiles};
[209]1369
[278]1370 if ( %removedfiles or %changedfiles or %unknownfiles ) {
1371
[215]1372 if (%removedfiles) {
[278]1373 print "DELETED: files found in repository, but not in system:\n";
[800]1374 print join( "\n", sort ( keys %removedfiles ) ) . "\n\n";
[209]1375 }
1376
[215]1377 if (%changedfiles) {
[278]1378 print "MODIFIED: files differs between repository and system:\n";
1379 print join( "\n", ( keys %changedfiles ) ) . "\n\n";
[209]1380 }
[278]1381
1382 if (%unknownfiles) {
1383 print "UNKNOWN: insufficient permission to check files:\n";
1384 print join( "\n", ( keys %unknownfiles ) ) . "\n\n";
1385 }
1386
[209]1387 } else {
[270]1388 print "no modified files found in $dirname_repo\n";
[252]1389 $return_code = $RETURN_OK;
[209]1390 }
[215]1391
[252]1392 return $return_code;
[215]1393}
[209]1394
[277]1395#
1396# return short status in Nagios plugin conform way
1397#
1398sub check()
1399{
1400 check_env();
1401
1402 # return code for the shell
[290]1403 my $return_code = $RETURN_OK;
[277]1404 my $return_string = "OK: no modified files";
1405
[278]1406 # check, if permissions have changed
1407 permissions();
1408
1409 # get modified files
1410 ( my $refChangedFiles, my $refRemovedFiles, my $refUnknownFiles ) =
[290]1411 getModifiedFiles("/");
[277]1412 my %changedfiles = %{$refChangedFiles};
1413 my %removedfiles = %{$refRemovedFiles};
[278]1414 my %unknownfiles = %{$refUnknownFiles};
[277]1415
1416 if ( %removedfiles or %changedfiles ) {
1417 $return_string = "Warning: ";
[290]1418 if (%changedfiles) {
1419 $return_string .=
1420 "changed: " . join( ", ", ( keys %changedfiles ) ) . ". ";
[277]1421 }
[290]1422 if (%removedfiles) {
1423 $return_string .=
1424 "removed: " . join( ", ", ( keys %removedfiles ) ) . ". ";
[277]1425 }
[278]1426 if (%unknownfiles) {
[290]1427 $return_string .=
1428 "unknown: " . join( ", ", ( keys %unknownfiles ) ) . ". ";
[278]1429 }
[277]1430 $return_code = $RETURN_WARN;
1431 }
1432
1433 # addition nagios Service Status
1434 #Critical
1435 #Unknown
1436
[290]1437 print "$return_string\n";
[277]1438 return $return_code;
1439}
1440
[270]1441sub permissions()
[215]1442{
1443 check_env();
1444
[278]1445 my $return_code = $RETURN_OK;
1446
[215]1447 #
1448 # update local repository
1449 #
1450 #svn_update();
1451
[220]1452 my $dir = $DASSCM_REPO;
[275]1453 my @files = svn_ls("/");
[215]1454
1455 if (@files) {
1456
1457 # generieren der Permissions
1458 my @permissions = generatePermissionList(@files);
1459 my $OUTFILE;
1460 my $tofile = 0; # Status für schreiben in File
[220]1461
[286]1462 if ( -w dirname($DASSCM_PERMISSION_FILE) ) {
[215]1463
1464 # Verzeichnis existiert => schreiben
[286]1465 open( OUTFILE, ">$DASSCM_PERMISSION_FILE" )
1466 || die("failed to write to $DASSCM_PERMISSION_FILE: $!");
[215]1467 $tofile = 1; # Merken, daß in File geschrieben wird
1468 print OUTFILE "#\n";
1469 print OUTFILE "# created by dasscm permissions\n";
[220]1470 print OUTFILE
1471 "# It is intended to be used for restoring permissions\n";
[287]1472 print OUTFILE "#\n";
[215]1473 } else {
1474
[290]1475 if ( $command eq "permission" ) {
1476
[278]1477 # Pfad für Sicherungsdatei existiert nicht => schreiben auf stdout
1478 # Alias Filehandle für stdout erzeugen
1479 $return_code = $RETURN_WARN;
[290]1480 *OUTFILE = *STDOUT;
[278]1481 } else {
[290]1482
[278]1483 # TODO: improve this. Check for diff?
1484 $return_code = $RETURN_CRIT;
1485 return $return_code;
1486 }
[215]1487 }
[278]1488
[215]1489 foreach my $line (@permissions) {
1490 print OUTFILE "$line\n";
1491 }
1492
[220]1493 if ($tofile) {
[215]1494 close(OUTFILE);
1495 }
1496 }
[278]1497
1498 return $return_code;
[209]1499}
1500
[274]1501#
1502# remove all uncommited changes in the repository
1503#
1504sub cleanup()
1505{
1506 check_env();
[268]1507
[275]1508 svn_revert($DASSCM_REPO);
[285]1509 svn_remove_unknown_files($DASSCM_REPO);
[274]1510}
1511
[884]1512#
1513# used for bash completion
1514# prints the next possible command line parameters
1515#
1516sub complete(@)
1517{
1518 use Data::Dumper;
1519
1520 my $number_arguments = @_;
1521 my $input_command = $_[0] || "";
1522
1523 print "args: $number_arguments\n";
1524 if ( $number_arguments <= 1 ) {
1525
1526 foreach my $i ( keys %COMMANDS ) {
1527 #print "$i: ";
1528 #print get_command_requires_write( $i ), " ";
1529 $_ = $i;
1530 if( m/^$input_command/ ) {
1531 my $command = get_command_uniform_name($i);
1532 print $command, " ";
1533 print join( ",", get_command_possible_params($i) ) ;
1534 #print " (", get_command_desc( $i ), ") ";
1535 print "\n";
1536 }
1537 #print "\n";
1538 }
1539 } else {
1540 my $command = get_command_uniform_name($input_command);
1541 my @params = get_command_possible_params($input_command);
1542 print "params: ", Dumper(@params);
1543 if( defined($params[$number_arguments-2]) && $params[$number_arguments-2] ) {
1544 my $param = $params[$number_arguments-2];
1545 print "param: $param\n";
1546 print Dumper($param);
1547 }
1548 }
1549}
1550
1551
1552
[189]1553#####################################################################
1554#
[186]1555# main
[189]1556#
[186]1557
[252]1558my $return_code = $RETURN_OK;
[186]1559my $number_arguments = @ARGV;
1560
[205]1561if ( $number_arguments > 0 ) {
[186]1562
[205]1563 # get subcommand and remove it from @ARGV
[884]1564 $command = get_command_uniform_name($ARGV[0]);
[205]1565 shift @ARGV;
[196]1566
[205]1567 $DASSCM_LOCAL_REPOSITORY_BASE = $config->{'DASSCM_LOCAL_REPOSITORY_BASE'};
1568 $DASSCM_REPOSITORY_NAME = $config->{'DASSCM_REPOSITORY_NAME'};
[196]1569
[205]1570 # TODO: check variables
1571 $DASSCM_SVN_REPOSITORY =
1572 $config->{'DASSCM_SVN_REPOSITORY_BASE'} . "/" . $DASSCM_REPOSITORY_NAME;
1573
[247]1574 $DASSCM_CHECKOUT_USERNAME = $config->{'DASSCM_CHECKOUT_USERNAME'};
1575 $DASSCM_CHECKOUT_PASSWORD = $config->{'DASSCM_CHECKOUT_PASSWORD'};
[205]1576
1577 #
1578 # if a user is given by dasscm configuration file, we use it.
1579 # Otherwise we expect that read-only account is configured
1580 # as local subversion configuration.
1581 # If this is also not the case,
1582 # user is required to type username and password.
1583 # This will be stored as local subversion configuration thereafter.
1584 #
1585 if ( $DASSCM_CHECKOUT_USERNAME && $DASSCM_CHECKOUT_PASSWORD ) {
1586 $svnCheckoutCredentials =
1587 " --username $DASSCM_CHECKOUT_USERNAME --password $DASSCM_CHECKOUT_PASSWORD ";
1588 }
1589
[290]1590 $DASSCM_PERMISSION_FILE = $config->{'DASSCM_PERMISSION_FILE'}
1591 || "/etc/permissions.d/dasscm.permission_backup";
[286]1592
[205]1593 # get command line options and store them in options hash
[214]1594 my $result = GetOptions( \%options, 'verbose', 'message=s' );
[205]1595
1596 # print options
1597 foreach my $option ( keys %options ) {
[215]1598 print "${option}: $options{$option}\n";
[205]1599 }
1600
[214]1601 # set verbose to command line option
1602 $verbose = $options{'verbose'};
1603
1604 #
1605 # action accordinly to command are taken
1606 # $command is rewritten in standard format,
1607 # so we can test for it later on more simply
1608 #
[884]1609
1610 # $_ = $command;
1611 # if (m/^help$/i) {
1612 # help(@ARGV);
1613 # } elsif (m/^login$/i) {
1614 # $command = "login";
1615 # login(@ARGV);
1616 # } elsif (m/^init$/i) {
1617 # $command = "init";
1618 # init(@ARGV);
1619 # } elsif (m/^ls$/i) {
1620 # $command = "ls";
1621 # ls(@ARGV);
1622 # } elsif ( (m/^update$/i) || (m/^up$/i) ) {
1623 # $command = "update";
1624 # update(@ARGV);
1625 # } elsif (m/^add$/i) {
1626 # $command = "add";
1627 # add(@ARGV);
1628 # } elsif ( (m/^commit$/i) || (m/^checkin$/i) || (m/^ci$/i) ) {
1629 # $command = "commit";
1630 # commit(@ARGV);
1631 # } elsif (m/^revert$/i) {
1632 # $command = "revert";
1633 # $return_code = revert(@ARGV);
1634 # } elsif (m/^blame$/i) {
1635 # $command = "blame";
1636 # blame(@ARGV);
1637 # } elsif (m/^diff$/i) {
1638 # $command = "diff";
1639 # diff(@ARGV);
1640 # } elsif ( (m/^status$/i) || (m/^st$/i) ) {
1641 # $command = "status";
1642 # $return_code = status(@ARGV);
1643 # } elsif (m/^check$/i) {
1644 # $command = "check";
1645 # $return_code = check();
1646 # } elsif (m/^permissions$/i) {
1647 # $command = "permissions";
1648 # $return_code = permissions();
1649 # } elsif (m/^cleanup$/i) {
1650 # $command = "cleanup";
1651 # cleanup();
1652 # } elsif (m/^complete$/i) {
1653 # $command = "complete";
1654 # $return_code = complete(@ARGV);
1655
1656 if( get_command_function( $command ) ) {
1657 &{get_command_function( $command )}( @ARGV );
[205]1658 } else {
[215]1659 print "unknown command: $command\n\n";
[205]1660 usage();
1661 check_env();
[252]1662 $return_code = $RETURN_NOK;
[205]1663 }
[186]1664}
[252]1665
1666exit $return_code;
Note: See TracBrowser for help on using the repository browser.