source: trunk/dasscm/dasscm@ 235

Last change on this file since 235 was 235, checked in by joergs, on Oct 8, 2008 at 5:25:26 PM

added /bin/bash evaluation, added alternative commands st and update, login USER works now

  • Property keyword set to id
  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 21.2 KB
Line 
1#!/usr/bin/perl -w
2
3# $Id: dasscm 235 2008-10-08 15:25:26Z joergs $
4
5use strict;
6
7use Env
8 qw($DASSCM_PROD $DASSCM_REPO $USER $DASSCM_USERNAME $DASSCM_USER $DASSCM_PASSWORD $SHELL);
9use Cwd;
10use Getopt::Long;
11use File::Basename;
12use File::Compare;
13use File::Copy;
14use File::stat;
15use File::Path;
16use Term::ReadKey;
17#use Data::Dumper;
18
19#####################################################################
20#
21# global
22#
23
24# file to store permissions
25my $permissions_file = "/etc/permissions.d/dasscm.permission_backup";
26
27# configuration file
28my $config_file = "/etc/dasscm.conf";
29my $config = get_config($config_file);
30my $DASSCM_LOCAL_REPOSITORY_BASE;
31my $DASSCM_REPOSITORY_NAME;
32my $DASSCM_SVN_REPOSITORY;
33
34my $SVN = "svn ";
35my $svnOptions = "";
36my $svnCheckoutCredentials = "";
37my $svnPasswordCredentials = "";
38
39# command line options get stored in options hash
40my %options = ();
41
42# subcommand, that gets executed (add, commit, ...)
43my $command;
44
45my $verbose = 0;
46
47#####################################################################
48#
49# util functions
50#
51sub usage()
52{
53 print "usage: dasscm <subcommand> [options] [args]\n";
54 print "\n";
55 print "dasscm is intended to help versioning configuration files\n";
56 print "\n";
57 print "Available subcommands:\n";
58 print " help <subcommand>\n";
59 print " init\n";
60 print " login\n";
61 print " up\n";
62 print " ls\n";
63 print " add <filename>\n";
64 print " commit <filename>\n";
65 print " status <filename>\n";
66 print " diff <filename>\n";
67 print " permissions\n";
68 print "\n";
69 print "preperation:\n", " if dasscm is already configured,\n",
70 " use 'dasscm login' and than eg. 'add'.\n",
71 " The environment variables\n", " DASSCM_REPO\n", " DASSCM_PROD\n",
72 " DASSCM_USERNAME\n", " DASSCM_PASSWORD\n",
73 " are evaluated, but set automatically by 'dasscm login'.\n", "\n",
74 " If dasscm is not yet configured, read",
75 " /usr/share/doc/packages/dasscm/dasscm_howto.txt\n";
76}
77
78sub warning(@)
79{
80 print "Warning: " . join( "\n ", @_ ) . "\n";
81}
82
83sub error(@)
84{
85 print "Error: " . join( "\n ", @_ ) . "\n";
86}
87
88sub fatalerror(@)
89{
90 error( @_ );
91 #print "Exiting\n";
92 exit 1
93}
94
95sub get_config
96{
97 my $file = $_[0];
98
99 if( ! $file ) {
100 fatalerror( "failed to open config file" . $file );
101 }
102
103 my $data = {};
104
105 # try to open config file
106 if ( !open( FH, $file ) ) {
107 fatalerror( "failed to open config file" . $file );
108 } else {
109 while (<FH>) {
110 chomp;
111 if (/^#/) {
112 next;
113 }
114 if ( $_ =~ /=/g ) {
115 ## splitting in 2 fields at maximum
116 my ( $option, $value ) = split( /=/, $_, 2 );
117 $option =~ s/^\s+//g;
118 $option =~ s/\s+$//g;
119 $option =~ s/\"+//g;
120 $value =~ s/^\s+//g;
121 $value =~ s/\s+$//g;
122 $value =~ s/\"+//g;
123
124 if ( length($option) ) {
125 $data->{$option} = $value;
126 }
127 }
128 }
129 }
130 close(FH);
131
132 return $data;
133}
134
135
136sub check_env()
137{
138
139 # DASSCM_PROD
140 if ( !$DASSCM_PROD ) {
141 $DASSCM_PROD = "/";
142 }
143
144 if ( !-d $DASSCM_PROD ) {
145 die "DASSCM_PROD ($DASSCM_PROD) is not set to a directory.\n";
146 }
147 if ($verbose) { print "DASSCM_PROD: " . $DASSCM_PROD . "\n"; }
148
149 # DASSCM_REPOSITORY_NAME
150 if ( !$DASSCM_REPOSITORY_NAME ) {
151 die
152 "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";
153 }
154
155 # DASSCM_REPO
156 if ( !$DASSCM_REPO ) {
157 if ( $DASSCM_LOCAL_REPOSITORY_BASE && $DASSCM_REPOSITORY_NAME ) {
158 $DASSCM_REPO =
159 $DASSCM_LOCAL_REPOSITORY_BASE . "/" . $DASSCM_REPOSITORY_NAME;
160 } else {
161 die
162 "Envirnonment variable DASSCM_REPO not set.\nSet DASSCM_REPO to the directory of the versioning system checkout for this machine.\n";
163 }
164 }
165 if ($verbose) { print "DASSCM_REPO: " . $DASSCM_REPO . "\n"; }
166
167 #
168 # check if local repository directory exist
169 # (if not creating by init)
170 #
171 if ( $command ne "init" ) {
172 if ( not -d $DASSCM_REPO ) {
173 die
174 "Can't access local repository DASSCM_REPO\n($DASSCM_REPO)\nCheck configuration and execute\n dasscm init\n";
175 }
176
177 #
178 # user settings
179 #
180
181 # DASSCM_USER is legacy. Use DASSCM_USERNAME instead
182 if ( !$DASSCM_USERNAME ) {
183 $DASSCM_USERNAME = $DASSCM_USER;
184 }
185
186 # user root is not allowed for checkins.
187 # if user is root, DASSCM_USER has to be set,
188 # otherwise USER can be used
189 if ( "$USER" eq "root" ) {
190 if ( ( not $DASSCM_USERNAME ) and ( $command ne "login" ) ) {
191 die
192 "Envirnonment variable DASSCM_USERNAME not set.\nSet DASSCM_USERNAME to your subversion user account.\n";
193 }
194 $svnOptions .= " --no-auth-cache ";
195 } elsif ( !$DASSCM_USERNAME ) {
196 $DASSCM_USERNAME = $USER;
197 }
198
199 #
200 # password
201 #
202 if ($DASSCM_PASSWORD) {
203 $svnPasswordCredentials = " --password $DASSCM_PASSWORD ";
204 }
205 }
206
207 #$svnOptions .= " --username $DASSCM_USERNAME "
208}
209
210sub check_parameter(@)
211{
212 if( not @_ ) {
213 fatalerror( "no files specified. See 'dasscm --help'" );
214 }
215}
216
217sub get_filenames(@)
218{
219 my $filename_prod = $_[0];
220 if ( !( $filename_prod =~ m/^\// ) ) {
221 $filename_prod = cwd() . "/" . $filename_prod;
222 }
223
224 if( not -r $filename_prod ) {
225 fatalerror( $filename_prod . " is not accessable" );
226 } elsif( -l $filename_prod ) {
227 my $dest = readlink($filename_prod);
228 # TODO:
229 # default: disallow, but offer cmd switch to activate
230 # (or check, if file is already checked in and has been a link before)
231 warning( "'$filename_prod' is a link to '$dest'.", "Please check, if '$dest' should be stored in repository instead" );
232 if( ! -f $dest ) {
233 fatalerror( "link target '$dest' is not a regular file. Giving up" );
234 }
235 } elsif( ! -f $filename_prod ) {
236 fatalerror( $filename_prod . " is not a regular file. Only regular files can be checked in." );
237 }
238
239 # TODO: dirname buggy: eg. "/etc/" is reduced to "/",
240 # "/etc" is used as filename
241 my $dirname_prod = dirname($filename_prod);
242 chdir $dirname_prod or die $!;
243 $dirname_prod = cwd();
244 my $basename = basename($filename_prod);
245
246 if ($verbose) {
247 print "dir: " . $dirname_prod . "\n";
248 print "fn: " . $basename . "\n";
249 }
250
251 my $dirname_repo = $DASSCM_REPO . "/" . $dirname_prod;
252 my $filename_repo = "$dirname_repo/$basename";
253
254 return (
255 $basename, $dirname_prod, $dirname_repo,
256 $filename_prod, $filename_repo
257 );
258}
259
260sub generatePermissionList
261{
262
263 # generieren der Zeilen für Permission-Savefile
264 my @files = @_;
265 my @permlist = ();
266 foreach my $file (@files) {
267 $file = "/" . $file;
268 if( -e $file ) {
269 my $info = stat( $file ) || die "failed to stat $file: aborting";
270 my $mode = get_type( $info->mode ) & 07777;
271 my $modestring = sprintf( "%04o", $mode );
272 my $uid = $info->uid;
273 my $uidname = getpwuid($uid);
274 my $gid = $info->gid;
275 my $gidname = getgrgid($gid);
276 push(
277 @permlist,
278 sprintf( "%-55s %-17s %4d",
279 $file, "${uidname}:${gidname}", $modestring )
280 );
281 } else {
282 print "failed to get status of $file. It exists in the repository, but not on the system\n";
283 }
284 }
285 return @permlist;
286}
287
288sub get_type
289{
290
291 # Funktion übernommen aus /usr/bin/chkstat
292 my $S_IFLNK = 0120000; # symbolic link
293 my $S_IFREG = 0100000; # regular file
294 my $S_IFDIR = 0040000; # directory
295 my $S_IFCHAR = 0020000; # character device
296 my $S_IFBLK = 0060000; # block device
297 my $S_IFFIFO = 0010000; # fifo
298 my $S_IFSOCK = 0140000; # socket
299 my $S_IFMT = 0170000; # type of file
300
301 my $S_m;
302 if ( ( $_[0] & $S_IFMT ) == $S_IFLNK ) { $S_m = $_[0] - $S_IFLNK; }
303 elsif ( ( $_[0] & $S_IFMT ) == $S_IFREG ) { $S_m = $_[0] - $S_IFREG; }
304 elsif ( ( $_[0] & $S_IFMT ) == $S_IFDIR ) { $S_m = $_[0] - $S_IFDIR; }
305 elsif ( ( $_[0] & $S_IFMT ) == $S_IFCHAR ) { $S_m = $_[0] - $S_IFCHAR; }
306 elsif ( ( $_[0] & $S_IFMT ) == $S_IFBLK ) { $S_m = $_[0] - $S_IFBLK; }
307 elsif ( ( $_[0] & $S_IFMT ) == $S_IFFIFO ) { $S_m = $_[0] - $S_IFFIFO; }
308 elsif ( ( $_[0] & $S_IFMT ) == $S_IFSOCK ) { $S_m = $_[0] - $S_IFSOCK; }
309 $S_m;
310}
311
312sub run_command
313{
314 my $command = shift;
315
316 #print "executing command: " . $command . "\n";
317
318 open( RESULT, $command . ' 2>&1 |' );
319 my @result = <RESULT>;
320 close(RESULT);
321 my $retcode = $? >> 8;
322
323 #print @result;
324 #if( $retcode ) { print "return code: " . $retcode . "\n"; }
325
326 return ( $retcode, @result );
327}
328
329sub run_interactive
330{
331
332 if ($verbose) {
333 print "run_interactive:" . join( " ", @_ ) . "\n";
334 }
335
336 system(@_);
337 if ( $? == -1 ) {
338 printf "failed to execute: $!\n";
339 } elsif ( $? & 127 ) {
340 printf "child died with signal %d, %s coredump\n", ( $? & 127 ),
341 ( $? & 128 ) ? 'with' : 'without';
342 } elsif ( $? >> 8 != 0 ) {
343 printf "child exited with value %d\n", $? >> 8;
344 }
345 return ( $? >> 8 );
346}
347
348sub svn_check_credentials( $$ )
349{
350 my $username = shift;
351 my $password = shift;
352
353 print "checking credentials ... ";
354
355 # Options for "svn info" are not supported by subversion 1.0.0 (SLES9),
356 # therefore switching to "svn status"
357 # ( my $rc_update, my @result ) =
358 # run_command(
359 # "$SVN info --non-interactive --no-auth-cache --username $username --password $password $DASSCM_SVN_REPOSITORY"
360 # );
361 #print @result;
362
363 ( my $rc_update, my @result ) =
364 run_command(
365 "$SVN ls --non-interactive --no-auth-cache --username $username --password $password $DASSCM_SVN_REPOSITORY"
366 );
367
368 if ( $rc_update != 0 ) {
369 print @result;
370 die;
371 }
372
373}
374
375sub svn_update( ;$ )
376{
377 my $update_path = shift || $DASSCM_REPO;
378 ( my $rc_update, my @result ) =
379 run_command(
380 "$SVN update --non-interactive $svnCheckoutCredentials $update_path");
381 print @result;
382 if ( $rc_update != 0 ) {
383 die;
384 }
385}
386
387sub svn_getStoredFiles( ;$ )
388{
389
390 # TODO: get_filenames?
391 #my $rel_path = shift || "";
392 #my $path = "${DASSCM_REPO}/${rel_path}";
393 my $path = ${DASSCM_REPO};
394
395 # svn ls -R is better, but much, much slower
396 # ( my $rc, my @result ) = run_command("$SVN ls --recursive $svnCheckoutCredentials $path");
397 ( my $rc, my @result ) =
398 run_command(
399 "cd $path && find | grep -v '/.svn' | sed -e 's/\.\\///' | grep -v '^\$'"
400 );
401 if ( $rc != 0 ) {
402 print @result;
403 die;
404 }
405 chomp(@result);
406 return @result;
407}
408
409#####################################################################
410#
411# functions
412
413sub help(;@)
414{
415 if ( @_ == 0 ) {
416 usage();
417 } else {
418 print "help for @_: ...\n";
419 usage();
420 }
421}
422
423sub login(@)
424{
425 check_parameter( @_, 1 );
426 check_env();
427
428 my $input_username = $_[0];
429
430 if ( not $input_username ) {
431 my $output_username = "";
432 if ($DASSCM_USERNAME) {
433 $output_username = " ($DASSCM_USERNAME)";
434 }
435
436 print "Enter DASSCM user name", $output_username, ": ";
437 $input_username = <STDIN>;
438 chomp($input_username);
439 }
440
441 # hidden password input
442 print "Enter DASSCM user password: ";
443 ReadMode('noecho');
444 my $input_password = <STDIN>;
445 ReadMode('normal');
446 chomp($input_password);
447 print "\n";
448
449 svn_check_credentials( $input_username, $input_password );
450
451 #
452 # set environment variables
453 #
454 $ENV{'DASSCM_USERNAME'} = $input_username;
455 $ENV{'DASSCM_PASSWORD'} = $input_password;
456
457 print "subversion access okay\n\n", "DASSCM_USERNAME: $input_username\n",
458 "DASSCM_PASSWORD: (hidden)\n", "DASSCM_PROD: $DASSCM_PROD\n",
459 "DASSCM_REPO: $DASSCM_REPO\n",
460 "Server Repository: $DASSCM_SVN_REPOSITORY\n", "\n", "[dasscm shell]\n\n";
461
462 my $shell = $SHELL || "bash";
463 exec($shell) or die "failed to start new shell";
464}
465
466sub init(@)
467{
468 check_parameter( @_, 1 );
469 check_env();
470
471 # don't do repository creation (svn mkdir) here,
472 # because then their must be a lot of prior checks
473
474 # update complete repository
475 # and create permission file
476 my $retcode =
477 run_interactive(
478 "cd $DASSCM_LOCAL_REPOSITORY_BASE; $SVN checkout $svnCheckoutCredentials $svnOptions $DASSCM_SVN_REPOSITORY; touch $permissions_file"
479 );
480}
481
482sub ls(@)
483{
484 check_parameter( @_, 1 );
485 check_env();
486
487 my @files = svn_getStoredFiles(@_);
488
489 print join( "\n", @files );
490 print "\n";
491}
492
493sub update(@)
494{
495 check_parameter( @_, 1 );
496 check_env();
497
498 #
499 # update local repository
500 #
501 svn_update();
502}
503
504sub add_helper(@)
505{
506 (
507 my $basename,
508 my $dirname_prod,
509 my $dirname_repo,
510 my $filename_prod,
511 my $filename_repo
512 )
513 = get_filenames( $_[0] );
514
515 if ( $command eq "add" ) {
516 mkpath($dirname_repo);
517 }
518
519 copy( $filename_prod, $filename_repo ) or die "failed to copy $filename_prod to repository: $!";
520
521 if ( $command eq "add" ) {
522
523 # already checked in?
524 chdir($DASSCM_REPO);
525
526 # also add the path to filename.
527 for my $dir ( split( '/', $dirname_prod ) ) {
528 if ($dir) {
529 my( $rc, @out ) = run_command("$SVN add --non-recursive \"" . $dir . "\"" );
530 if( $rc > 0 ) {
531 print join( "\n", @out );
532 }
533 chdir $dir;
534 }
535 }
536 my( $rc, @out ) = run_command("$SVN add \"" . $basename . "\"");
537 if( $rc > 0 ) {
538 print join( "\n", @out );
539 }
540 }
541}
542
543#
544# add (is used for command add and commit)
545#
546sub add(@)
547{
548 check_parameter( @_, 1 );
549 check_env();
550
551 #
552 # update local repository
553 #
554 svn_update();
555
556 # TODO: check all files
557
558 for my $file (@_) {
559 # add file
560 add_helper( $file );
561 }
562
563 # create new permissions file
564 permissions();
565
566 # add permissions file
567 add_helper($permissions_file);
568
569 if ( $options{'message'} ) {
570 $svnOptions .= " --message \"$options{'message'}\" ";
571 }
572
573 # commit calls $EDITOR. uses "interactive" here, to display output
574 my $retcode =
575 run_interactive(
576 "$SVN commit $svnOptions --username $DASSCM_USERNAME $svnPasswordCredentials $DASSCM_REPO"
577 );
578
579 #print $filename_prod. "\n";
580 #print $dirname_repo. "\n";
581}
582
583sub blame(@)
584{
585 check_parameter( @_, 1 );
586 check_env();
587
588 (
589 my $basename,
590 my $dirname_prod,
591 my $dirname_repo,
592 my $filename_prod,
593 my $filename_repo
594 )
595 = get_filenames( $_[0] );
596
597 my $retcode = run_interactive("$SVN blame $svnOptions $filename_repo");
598}
599
600sub diff(@)
601{
602 check_parameter( @_, 1 );
603 check_env();
604
605 (
606 my $basename,
607 my $dirname_prod,
608 my $dirname_repo,
609 my $filename_prod,
610 my $filename_repo
611 )
612 = get_filenames( $_[0] );
613
614 #print "$basename,$dirname_prod,$dirname_repo\n";
615
616 ( my $rc_update, my @result ) = run_command("$SVN update $filename_repo");
617 if ( $rc_update != 0 ) {
618 print @result;
619 die;
620 }
621
622 ( my $rc_diff, my @diff ) =
623 run_command("diff $filename_repo $filename_prod");
624 print @diff;
625}
626
627sub status(@)
628{
629 check_parameter( @_, 1 );
630 check_env();
631
632 #
633 # update local repository
634 #
635 svn_update();
636
637 # TODO: start at subdirectories ?
638 my $dir = $DASSCM_REPO;
639 my @files = svn_getStoredFiles($dir);
640
641 # Liste der geänderten Files ausgeben, falls nicht leer
642 if (@files) {
643
644 # stores result from status (cvscheck)
645 my %removedfiles = ();
646 my %changedfiles = ();
647
648 foreach my $file (@files) {
649
650 my $realfile = "/" . $file;
651 my $cvsworkfile = "${DASSCM_REPO}/${file}";
652
653 if ( -d $realfile ) {
654
655 # directory. do nothing
656 } elsif ( !-r $realfile ) {
657 $removedfiles{"$realfile"} = $cvsworkfile;
658 } else {
659 ( -r "$cvsworkfile" )
660 || die("Fehler: $cvsworkfile ist nicht lesbar");
661 if ( compare( $cvsworkfile, $realfile ) != 0 ) {
662 $changedfiles{"$realfile"} = $cvsworkfile;
663 }
664 }
665 }
666
667 if (%removedfiles) {
668 print "deleted files (found in repository, but not in system):\n";
669 foreach my $key ( values %removedfiles ) {
670 print "$key\n";
671 }
672 print "\n";
673 }
674
675 if (%changedfiles) {
676 print "modified files:\n";
677 foreach my $key ( keys %changedfiles ) {
678 print "$key\n";
679 }
680 }
681 } else {
682 print "no modified files found in $dir\n";
683 }
684
685 print "\n";
686}
687
688sub permissions(@)
689{
690 check_parameter( @_, 1 );
691 check_env();
692
693 #
694 # update local repository
695 #
696 #svn_update();
697
698 # TODO: start at subdirectories ?
699 my $dir = $DASSCM_REPO;
700 my @files = svn_getStoredFiles($dir);
701
702 if (@files) {
703
704 # generieren der Permissions
705 my @permissions = generatePermissionList(@files);
706 my $OUTFILE;
707 my $tofile = 0; # Status für schreiben in File
708
709 if ( -w dirname($permissions_file) ) {
710
711 # Verzeichnis existiert => schreiben
712 print "storing permissions in file $permissions_file\n";
713 open( OUTFILE, ">$permissions_file" )
714 || die("failed to write to $permissions_file: $!");
715 $tofile = 1; # Merken, daß in File geschrieben wird
716 print OUTFILE "#\n";
717 print OUTFILE "# created by dasscm permissions\n";
718 print OUTFILE
719 "# It is intended to be used for restoring permissions\n";
720 } else {
721
722 # Pfad für Sicherungsdatei existiert nicht => schreiben auf stdout
723 # Alias Filehandle für stdout erzeugen
724 *OUTFILE = *STDOUT;
725 }
726 foreach my $line (@permissions) {
727 print OUTFILE "$line\n";
728 }
729
730 if ($tofile) {
731 close(OUTFILE);
732 }
733 }
734}
735
736#####################################################################
737#
738# main
739#
740
741my $number_arguments = @ARGV;
742
743if ( $number_arguments > 0 ) {
744
745 # get subcommand and remove it from @ARGV
746 $command = $ARGV[0];
747 shift @ARGV;
748
749 $DASSCM_LOCAL_REPOSITORY_BASE = $config->{'DASSCM_LOCAL_REPOSITORY_BASE'};
750 $DASSCM_REPOSITORY_NAME = $config->{'DASSCM_REPOSITORY_NAME'};
751
752 # TODO: check variables
753 $DASSCM_SVN_REPOSITORY =
754 $config->{'DASSCM_SVN_REPOSITORY_BASE'} . "/" . $DASSCM_REPOSITORY_NAME;
755
756 my $DASSCM_CHECKOUT_USERNAME = $config->{'DASSCM_CHECKOUT_USERNAME'};
757 my $DASSCM_CHECKOUT_PASSWORD = $config->{'DASSCM_CHECKOUT_PASSWORD'};
758
759 #
760 # if a user is given by dasscm configuration file, we use it.
761 # Otherwise we expect that read-only account is configured
762 # as local subversion configuration.
763 # If this is also not the case,
764 # user is required to type username and password.
765 # This will be stored as local subversion configuration thereafter.
766 #
767 if ( $DASSCM_CHECKOUT_USERNAME && $DASSCM_CHECKOUT_PASSWORD ) {
768 $svnCheckoutCredentials =
769 " --username $DASSCM_CHECKOUT_USERNAME --password $DASSCM_CHECKOUT_PASSWORD ";
770 }
771
772 # get command line options and store them in options hash
773 my $result = GetOptions( \%options, 'verbose', 'message=s' );
774
775 # print options
776 foreach my $option ( keys %options ) {
777 print "${option}: $options{$option}\n";
778 }
779
780 # set verbose to command line option
781 $verbose = $options{'verbose'};
782
783 #
784 # action accordinly to command are taken
785 # $command is rewritten in standard format,
786 # so we can test for it later on more simply
787 #
788 $_ = $command;
789 if (m/help/i) {
790 help(@ARGV);
791 } elsif (m/login/i) {
792 $command = "login";
793 login(@ARGV);
794 } elsif (m/init/i) {
795 $command = "init";
796 init(@ARGV);
797 } elsif (m/ls/i) {
798 $command = "ls";
799 ls(@ARGV);
800 } elsif ( (m/update/i) || (m/up/i) ) {
801 $command = "update";
802 update(@ARGV);
803 } elsif (m/add/i) {
804 $command = "add";
805 add(@ARGV);
806 } elsif (m/commit/i) {
807 $command = "commit";
808 add(@ARGV);
809 } elsif (m/blame/i) {
810 $command = "blame";
811 blame(@ARGV);
812 } elsif (m/diff/i) {
813 $command = "diff";
814 diff(@ARGV);
815 } elsif ( (m/status/i) || (m/st/i) ) {
816 $command = "status";
817 status(@ARGV);
818 } elsif (m/permissions/i) {
819 $command = "permissions";
820 permissions(@ARGV);
821 } else {
822 print "unknown command: $command\n\n";
823 usage();
824 check_env();
825 }
826
827 # cleanup (svn-commit.tmp)
828 # commitall
829 # revert
830 # activate
831 # rm
832}
Note: See TracBrowser for help on using the repository browser.