source: trunk/dasscm/dasscm@ 205

Last change on this file since 205 was 205, checked in by joergs, on Jul 2, 2007 at 5:15:47 PM

improvements. login, password caching, init, config file, perltidy

  • Property keyword set to id
  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 11.7 KB
Line 
1#!/usr/bin/perl -w
2
3# $Id: dasscm 205 2007-07-02 15:15:47Z joergs $
4
5use strict;
6
7use Env qw($DASSCM_PROD $DASSCM_REPO $USER $DASSCM_USERNAME $DASSCM_USER $DASSCM_PASSWORD);
8use Cwd;
9use Term::ReadKey;
10use File::Basename;
11use File::stat;
12use File::Path;
13use File::Copy;
14use Getopt::Long;
15
16#
17# used ConfigFile instead of SmartClient::Config,
18# because the huge amount of SmartClient dependencies
19#use SmartClient::Config;
20use ConfigFile;
21
22#####################################################################
23#
24# global
25#
26
27my $config_file = "/etc/dasscm.conf";
28
29# my $config = SmartClient::Config->( $config_file );
30my $config = ConfigFile::read_config_file($config_file);
31my $DASSCM_LOCAL_REPOSITORY_BASE;
32my $DASSCM_REPOSITORY_NAME;
33my $DASSCM_SVN_REPOSITORY;
34
35my $SVN = "svn ";
36my $svnOptions = "";
37my $svnCheckoutCredentials = "";
38my $svnPasswordCredentials = "";
39
40# command line options get stored in options hash
41my %options = ();
42
43# subcommand, that gets executed (add, commit, ...)
44my $command;
45
46my $verbose = 0;
47
48#####################################################################
49#
50# util functions
51#
52sub usage()
53{
54 print "usage: dasscm <subcommand> [options] [args]\n";
55 print "\n";
56 print "dasscm is intended to help versioning configuration files\n";
57 print "\n";
58 print "Available subcommands:\n";
59 print " init\n";
60 print " login\n";
61 print " add <filename>\n";
62 print " commit <filename>\n";
63 print " diff <filename>\n";
64 print " help <subcommand>\n";
65 print "\n";
66 print "preperation:\n";
67 print "check out the configuration repository, e.g.\n";
68 print
69 "svn checkout --no-auth-cache --username USERNAME https://dass-it.de/svn/dasscm/HOSTNAME\n";
70 print
71 "environment variables\n",
72 " DASSCM_REPO\n",
73 " DASSCM_PROD¸n",
74 " DASSCM_USERNAME\n",
75 " DASSCM_PASSWORD\n",
76 "are evaluated.\n";
77 print "\n";
78}
79
80sub check_env()
81{
82
83 # DASSCM_PROD
84 if ( !$DASSCM_PROD ) {
85 $DASSCM_PROD = "/";
86 }
87
88 if ( !-d $DASSCM_PROD ) {
89 die "DASSCM_PROD ($DASSCM_PROD) is not set to a directory.\n";
90 }
91 if ($verbose) { print "DASSCM_PROD: " . $DASSCM_PROD . "\n"; }
92
93
94 # DASSCM_REPOSITORY_NAME
95 if ( !$DASSCM_REPOSITORY_NAME ) {
96 die
97 "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";
98 }
99
100
101 # DASSCM_REPO
102 if ( !$DASSCM_REPO ) {
103 if ( $DASSCM_LOCAL_REPOSITORY_BASE && $DASSCM_REPOSITORY_NAME ) {
104 $DASSCM_REPO =
105 $DASSCM_LOCAL_REPOSITORY_BASE . "/" . $DASSCM_REPOSITORY_NAME;
106 } else {
107 die
108 "Envirnonment variable DASSCM_REPO not set.\nSet DASSCM_REPO to the directory of the versioning system checkout for this machine.\n";
109 }
110 }
111 print "DASSCM_REPO: " . $DASSCM_REPO . "\n";
112
113 #
114 # check if local repository directory exist (if not creating by init)
115 #
116 if ( $command ne "init" ) {
117 if ( not -d $DASSCM_REPO ) {
118 die
119 "Can't access local repository DASSCM_REPO\n($DASSCM_REPO)\nCheck configuration and execute\n dasscm init\n";
120 }
121
122 #
123 # user settings
124 #
125
126 # DASSCM_USER is legacy. Use DASSCM_USERNAME instead
127 if( !$DASSCM_USERNAME ) {
128 $DASSCM_USERNAME=$DASSCM_USER;
129 }
130
131 # user root is not allowed for checkins.
132 # if user is root, DASSCM_USER has to be set,
133 # otherwise USER can be used
134 if ( "$USER" eq "root" ) {
135 if (( not $DASSCM_USERNAME ) and ( $command ne "login" )) {
136 die
137 "Envirnonment variable DASSCM_USERNAME not set.\nSet DASSCM_USERNAME to your subversion user account.\n";
138 }
139 $svnOptions .= " --no-auth-cache ";
140 } elsif ( !$DASSCM_USERNAME ) {
141 $DASSCM_USERNAME = $USER;
142 }
143
144 #
145 # password
146 #
147 if( $DASSCM_PASSWORD ) {
148 $svnPasswordCredentials = " --password $DASSCM_PASSWORD ";
149 }
150 }
151
152 #$svnOptions .= " --username $DASSCM_USERNAME "
153}
154
155sub check_parameter(@)
156{
157}
158
159sub get_filenames(@)
160{
161 my $filename_prod = $_[0];
162 if ( !( $filename_prod =~ m/^\// ) ) {
163 $filename_prod = cwd() . "/" . $filename_prod;
164 }
165
166 -r $filename_prod or die "$filename_prod is not accessable";
167
168 # TODO: dirname buggy: eg. "/etc/" is reduced to "/",
169 # "/etc" is used as filename
170 my $dirname_prod = dirname($filename_prod);
171 chdir $dirname_prod or die $!;
172 $dirname_prod = cwd();
173 my $basename = basename($filename_prod);
174
175 print "dir: " . $dirname_prod . "\n";
176 print "fn: " . $basename . "\n";
177
178 my $dirname_repo = $DASSCM_REPO . "/" . $dirname_prod;
179 my $filename_repo = "$dirname_repo/$basename";
180
181 return (
182 $basename, $dirname_prod, $dirname_repo,
183 $filename_prod, $filename_repo
184 );
185}
186
187sub run_command
188{
189 my $command = shift;
190
191 #print "executing command: " . $command . "\n";
192
193 open( RESULT, $command . ' 2>&1 |' );
194 my @result = <RESULT>;
195 close(RESULT);
196 my $retcode = $? >> 8;
197
198 #print @result;
199 #if( $retcode ) { print "return code: " . $retcode . "\n"; }
200
201 return ( $retcode, @result );
202}
203
204sub run_interactive
205{
206
207 if( $verbose ) {
208 print "run_interactive:" . join( " ", @_ ) . "\n";
209 }
210
211 system(@_);
212 if ( $? == -1 ) {
213 printf "failed to execute: $!\n";
214 } elsif ( $? & 127 ) {
215 printf "child died with signal %d, %s coredump\n", ( $? & 127 ),
216 ( $? & 128 ) ? 'with' : 'without';
217 } elsif ( $? >> 8 != 0 ) {
218 printf "child exited with value %d\n", $? >> 8;
219 }
220 return ( $? >> 8 );
221}
222
223sub svn_check_credentials( $$ )
224{
225 my $username = shift;
226 my $password = shift;
227
228 ( my $rc_update, my @result ) =
229 run_command(
230 "$SVN info --non-interactive --no-auth-cache --username $username --password $password $DASSCM_SVN_REPOSITORY"
231 );
232
233 print @result;
234
235 if ( $rc_update != 0 ) {
236 print @result;
237 die;
238 }
239
240}
241
242sub svn_update( ;$ )
243{
244 my $update_path = shift || $DASSCM_REPO;
245 ( my $rc_update, my @result ) =
246 run_command("$SVN update $svnCheckoutCredentials $update_path");
247 if ( $rc_update != 0 ) {
248 print @result;
249 die;
250 }
251
252 print @result;
253
254}
255
256#####################################################################
257#
258# functions
259
260sub help(;@)
261{
262 if ( @_ == 0 ) {
263 usage();
264 } else {
265 print "help for @_: ...\n";
266 }
267}
268
269sub login(@)
270{
271 check_parameter( @_, 1 );
272 check_env();
273
274 my $output_username = "";
275 if ($DASSCM_USERNAME) {
276 $output_username = " ($DASSCM_USERNAME)";
277 }
278
279 print "Enter DASSCM user name", $output_username, ": ";
280 my $input_username = <STDIN>;
281 chomp($input_username);
282
283 # hidden password input
284 print "Enter DASSCM user password: ";
285 ReadMode('noecho');
286 my $input_password = <STDIN>;
287 ReadMode('normal');
288 chomp($input_password);
289
290 svn_check_credentials( $input_username, $input_password );
291
292 #
293 # set environment variables
294 #
295 $ENV{'DASSCM_USERNAME'} = $input_username;
296 $ENV{'DASSCM_PASSWORD'} = $input_password;
297
298 # TODO: print environment
299
300 exec("bash") or die "can't login";
301}
302
303
304
305sub init(@)
306{
307 check_parameter( @_, 1 );
308 check_env();
309
310 # update complete repository
311 my $retcode = run_interactive("cd $DASSCM_LOCAL_REPOSITORY_BASE; $SVN checkout $svnCheckoutCredentials $svnOptions $DASSCM_SVN_REPOSITORY");
312}
313
314
315#
316# add (is used for command add and commit)
317#
318sub add(@)
319{
320 check_parameter( @_, 1 );
321 check_env();
322
323 (
324 my $basename,
325 my $dirname_prod,
326 my $dirname_repo,
327 my $filename_prod,
328 my $filename_repo
329 )
330 = get_filenames( $_[0] );
331
332 if ( $command eq "add" ) {
333 mkpath($dirname_repo);
334 }
335
336 # update complete repository
337 my $retcode = run_interactive("$SVN update $svnOptions $DASSCM_REPO");
338
339 copy( $filename_prod, $filename_repo ) or die $!;
340
341 if ( $command eq "add" ) {
342
343 # already checked in?
344 chdir($DASSCM_REPO);
345
346 # also add the path to filename.
347 for my $dir ( split( '/', $dirname_prod ) ) {
348 if ($dir) {
349 run_command("$SVN add --non-recursive $dir");
350 chdir $dir;
351 }
352 }
353 run_command("$SVN add $basename");
354 }
355
356 if ( $options{'message'} ) {
357 $svnOptions .= " --message \"$options{'message'}\" ";
358 }
359
360 # commit calls $EDITOR. uses "interactive" here, to display output
361 $retcode =
362 run_interactive(
363 "$SVN commit $svnOptions --username $DASSCM_USERNAME $svnPasswordCredentials $DASSCM_REPO");
364
365 print $filename_prod. "\n";
366 print $dirname_repo. "\n";
367}
368
369sub blame(@)
370{
371 check_parameter( @_, 1 );
372 check_env();
373
374 (
375 my $basename,
376 my $dirname_prod,
377 my $dirname_repo,
378 my $filename_prod,
379 my $filename_repo
380 )
381 = get_filenames( $_[0] );
382
383 my $retcode = run_interactive("$SVN blame $svnOptions $filename_repo");
384}
385
386sub diff(@)
387{
388 check_parameter( @_, 1 );
389 check_env();
390
391 (
392 my $basename,
393 my $dirname_prod,
394 my $dirname_repo,
395 my $filename_prod,
396 my $filename_repo
397 )
398 = get_filenames( $_[0] );
399
400 #print "$basename,$dirname_prod,$dirname_repo\n";
401
402 ( my $rc_update, my @result ) = run_command("$SVN update $filename_repo");
403 if ( $rc_update != 0 ) {
404 print @result;
405 die;
406 }
407
408 ( my $rc_diff, my @diff ) =
409 run_command("diff $filename_repo $filename_prod");
410 print @diff;
411}
412
413#####################################################################
414#
415# main
416#
417
418my $number_arguments = @ARGV;
419
420if ( $number_arguments > 0 ) {
421
422 # get subcommand and remove it from @ARGV
423 $command = $ARGV[0];
424 shift @ARGV;
425
426 $DASSCM_LOCAL_REPOSITORY_BASE = $config->{'DASSCM_LOCAL_REPOSITORY_BASE'};
427 $DASSCM_REPOSITORY_NAME = $config->{'DASSCM_REPOSITORY_NAME'};
428
429 # TODO: check variables
430 $DASSCM_SVN_REPOSITORY =
431 $config->{'DASSCM_SVN_REPOSITORY_BASE'} . "/" . $DASSCM_REPOSITORY_NAME;
432
433 my $DASSCM_CHECKOUT_USERNAME = $config->{'DASSCM_CHECKOUT_USERNAME'};
434 my $DASSCM_CHECKOUT_PASSWORD = $config->{'DASSCM_CHECKOUT_PASSWORD'};
435
436 #
437 # if a user is given by dasscm configuration file, we use it.
438 # Otherwise we expect that read-only account is configured
439 # as local subversion configuration.
440 # If this is also not the case,
441 # user is required to type username and password.
442 # This will be stored as local subversion configuration thereafter.
443 #
444 if ( $DASSCM_CHECKOUT_USERNAME && $DASSCM_CHECKOUT_PASSWORD ) {
445 $svnCheckoutCredentials =
446 " --username $DASSCM_CHECKOUT_USERNAME --password $DASSCM_CHECKOUT_PASSWORD ";
447 }
448
449 # get command line options and store them in options hash
450 my $result = GetOptions( \%options, 'message=s' );
451
452 # print options
453 foreach my $option ( keys %options ) {
454 print $option. ": " . $options{$option} . "\n";
455 }
456
457 $_ = $command;
458 if (m/help/i) {
459 help(@ARGV);
460 } elsif (m/login/i) {
461 $command ="login";
462 login(@ARGV);
463 } elsif (m/init/i) {
464 $command ="init";
465 init(@ARGV);
466 } elsif (m/add/i) {
467 ## rewrite command
468 $command = "add";
469 add(@ARGV);
470 } elsif (m/commit/i) {
471 $command = "commit";
472 add(@ARGV);
473 } elsif (m/blame/i) {
474 $command ="blame";
475 blame(@ARGV);
476 } elsif (m/diff/i) {
477 $command ="diff";
478 diff(@ARGV);
479 } elsif (m/activate/i) {
480 ## TODO
481 activate(@ARGV);
482 } else {
483 usage();
484 check_env();
485 }
486
487 # login
488 # up
489 # commitall
490 # revert
491 # status (chkconf)
492}
Note: See TracBrowser for help on using the repository browser.