releasing/cbrtools/perl/cleanremote
changeset 602 3145852acc89
equal deleted inserted replaced
600:6d08f4a05d93 602:3145852acc89
       
     1 #!perl
       
     2 # Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of the License "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 # 
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 # 
       
    12 # Contributors:
       
    13 # 
       
    14 # Description:
       
    15 # 
       
    16 #
       
    17 
       
    18 use strict;
       
    19 use FindBin;
       
    20 use lib "$FindBin::Bin";
       
    21 use Getopt::Long;
       
    22 use IniData;
       
    23 use RelData;
       
    24 use CommandController;
       
    25 use Cleaner;
       
    26 use Utils;
       
    27 
       
    28 
       
    29 #
       
    30 # Globals.
       
    31 #
       
    32 
       
    33 my $verbose = 0;
       
    34 my $dummyRun = 0;
       
    35 my $descriptionFile;
       
    36 my $iniData = IniData->New();
       
    37 my $commandController = CommandController->New($iniData, 'CleanRemote');
       
    38 my $keepAfter;
       
    39 my %envsToKeep;
       
    40 my %relsToKeep;
       
    41 my %relsToClean;
       
    42 my @filesToDelete;
       
    43 my $remoteSite = $iniData->RemoteSite;
       
    44 my $cleaner;
       
    45 my $doall = 0; # skips prompting
       
    46 my $skipWarnings;
       
    47 
       
    48 #
       
    49 # Main.
       
    50 #
       
    51 ProcessCommandLine();
       
    52 $cleaner = Cleaner->New($iniData, 1, $verbose, 0); # 1 = remote
       
    53 $cleaner->SetCleaningSubroutine(\&CleaningSubroutine);
       
    54 ParseDescriptionFile($descriptionFile);
       
    55 $cleaner->Clean();
       
    56 
       
    57 #
       
    58 # Subs.
       
    59 #
       
    60 
       
    61 sub ProcessCommandLine {
       
    62   Getopt::Long::Configure ("bundling");
       
    63   my $help;
       
    64   GetOptions('h' => \$help, 'd' => \$dummyRun, 'v+' => \$verbose, 'f' => \$skipWarnings);
       
    65 
       
    66   if ($help) {
       
    67     Usage(0);
       
    68   }
       
    69 
       
    70   $descriptionFile = shift @ARGV;
       
    71 
       
    72   unless ($descriptionFile) {
       
    73     print "Error: Archive cleaning description file not specified\n";
       
    74     Usage(1);
       
    75   }
       
    76 
       
    77   unless ($#ARGV == -1) {
       
    78     print "Error: Invalid number of arguments\n";
       
    79     Usage(1);
       
    80   }
       
    81 
       
    82   if ($dummyRun and not $verbose) {
       
    83     $verbose = 1;
       
    84   }
       
    85 }
       
    86 
       
    87 sub Usage {
       
    88   my $exitCode = shift;
       
    89 
       
    90   Utils::PrintDeathMessage($exitCode, "\nUsage: cleanremote [options] <description_file>
       
    91 
       
    92 options:
       
    93 
       
    94 -h  help
       
    95 -d  dummy run (don't do anything) - assumes -v
       
    96 -f  (deprecated)
       
    97 -v  verbose output (-vv very verbose).\n");
       
    98 
       
    99 }
       
   100 
       
   101 sub ParseDescriptionFile {
       
   102   if ($verbose) { print "Parsing \"$descriptionFile\"...\n"; }
       
   103   open (DES, $descriptionFile) or die "Unable to open \"$descriptionFile\" for reading: $!\n";
       
   104 
       
   105   while (my $line = <DES>) {
       
   106     # Remove line feed, white space and comments.
       
   107     chomp($line);
       
   108     $line =~ s/^\s*$//;
       
   109     $line =~ s/#.*//;
       
   110     if ($line eq '') {
       
   111       # Nothing left.
       
   112       next;
       
   113     }
       
   114 
       
   115     my $keyWord;
       
   116     my @operand;
       
   117     if ($line =~ /^(\w+)\s+(.*)/) {
       
   118       $keyWord = $1;
       
   119       @operand = ();
       
   120       if ($2) {
       
   121         @operand = split /\s+/, $2;
       
   122       }
       
   123     } else {
       
   124       $keyWord = $line;
       
   125     }
       
   126 
       
   127     unless (defined $keyWord) {
       
   128       die "Error: Invalid line in \"$descriptionFile\":\n$line\n";
       
   129       next;
       
   130     }
       
   131 
       
   132     if ($cleaner->ProcessDescriptionLine($descriptionFile, $keyWord, @operand)) {
       
   133       # We're happy because Cleaner.pm knows what to do with this line
       
   134     }
       
   135     elsif ($keyWord =~ /^(?:no_prompt)$/ ) {
       
   136       $doall = 1;    
       
   137     } elsif ($keyWord =~ /^(?:clean_to|expunge)$/ ) {
       
   138       my $msg = "You have accidentally left a \"$keyWord\" keyword in your configuration file. That's appropriate for cleaning local archives, but cleanremote just completely deletes stuff. Do you want to continue?";
       
   139       die unless $cleaner->Query($msg);
       
   140     }
       
   141     else {
       
   142       die "Error: Unknown keyword \'$keyWord\' in \"$descriptionFile\"\n";
       
   143     }
       
   144   }
       
   145 
       
   146   close (DES);
       
   147 
       
   148   if ($verbose > 1) {
       
   149     $cleaner->PrintEnvsToKeep();
       
   150   }
       
   151 }
       
   152 
       
   153 sub CleaningSubroutine {
       
   154   # This actually gets run by Cleaner.pm (it's a callback)
       
   155   my $thisComp = shift;
       
   156   my $thisVer = shift;
       
   157   my $relDir = shift;
       
   158   print "Cleaning $thisComp $thisVer from $relDir...\n" if ($verbose);
       
   159   unless ($doall) {
       
   160     print "Do it?\n";
       
   161     my $ans = <STDIN>;
       
   162     die "Not doing" unless $ans =~ m/[ay]/i;
       
   163     $doall = 1 if $ans =~ m/a/i;
       
   164   }
       
   165   die "Couldn't delete $relDir because it didn't exist" unless $remoteSite->DirExists($relDir);
       
   166   my $fullfile = "$relDir/$thisComp$thisVer.zip";
       
   167   print "Actually deleting release file $fullfile\n";
       
   168   DeleteFile($fullfile);
       
   169   my @files = @{$remoteSite->DirList($relDir) || []};
       
   170   foreach my $fullfile (@files) {
       
   171     if ($fullfile =~ m/lpdrt\d{5}\.tmp$/) {
       
   172       # Remove temp files older than $keepAfter time
       
   173       my $modifiedTime = $remoteSite->FileModifiedTime($fullfile);
       
   174       my $keepAfter = $cleaner->{keepAfter};
       
   175       if ($modifiedTime and (not defined $keepAfter or $modifiedTime <= $keepAfter)) {
       
   176         print "Actually deleting temp file $fullfile\n";
       
   177         DeleteFile($fullfile);
       
   178       } else {
       
   179         print "Not deleting temp file $fullfile because too new\n";
       
   180       }
       
   181     }
       
   182   }
       
   183   if (!$dummyRun) {
       
   184     # Now check the directory is empty and delete the directory if so
       
   185     @files = @{$remoteSite->DirList($relDir) || []};
       
   186     @files = map { m/.*\/(.*?)$/; $1 } @files;
       
   187     print "Wanting to remove directory $relDir - @files files left in it\n" if ($verbose);
       
   188     DeleteFile($relDir) unless @files;
       
   189   }
       
   190 
       
   191   return 1; # This cleaner doesn't currently support returning of any errors
       
   192 }
       
   193 
       
   194 sub DeleteFile {
       
   195   my $file = shift;
       
   196   print "Deleting \"$file\"\n" if ($verbose);
       
   197 	eval {
       
   198 		$remoteSite->DeleteFile($file) unless ($dummyRun);
       
   199 	};
       
   200 	if ($@) {
       
   201 		print "Warning: Couldn't delete \"$file\" because \"$@\"\n";
       
   202 		# Usually because $file is a directory, which turns out not to be
       
   203 		# empty.
       
   204 	}
       
   205 }
       
   206 
       
   207 __END__
       
   208 
       
   209 =head1 NAME
       
   210 
       
   211 CleanRemote - Cleans unwanted releases and files from a remote archive.
       
   212 
       
   213 =head1 SYNOPSIS
       
   214 
       
   215   cleanremote [options] <description_file>
       
   216 
       
   217 options:
       
   218 
       
   219   -h  help
       
   220   -d  dummy run (don't do anything) - assumes -v
       
   221   -f  (deprecated)
       
   222   -v  verbose output (-vv very verbose)
       
   223 
       
   224 =head1 DESCRIPTION
       
   225 
       
   226 C<cleanremote> allows releases to be cleaned out of a remote archive. This may be useful if a remote archive is consuming a large amount of disk space and there are old releases present that are no longer required.
       
   227 
       
   228 B<Warning: C<cleanremote> has the potential to seriously alter the state of a remote archive, and hence seriously damage productivity of all users of the remote archive. Be very careful using it.>
       
   229 
       
   230 Before using C<cleanremote> you must write a plain text file that describes which releases you want to keep etc. The following keywords are supported:
       
   231 
       
   232 =over 4
       
   233 
       
   234 =item keep_env <component> <version>
       
   235 
       
   236 Instructs C<cleanremote> to keep all the component versions in the environment from which the specified component was released. This keyword may be used multiple times.
       
   237 
       
   238 =item keep_rel <component> <version>
       
   239 
       
   240 Instructs C<cleanremote> to keep a specific component release. This keyword may be used multiple times.
       
   241 
       
   242 =item keep_recent_env <component> <num_days>
       
   243 
       
   244 Instructs C<cleanremote> to keep all named component releases, including their environments, where the component release has been exported within the specified number of days (since the current time) (note: the export time, rather than release time is used).
       
   245 
       
   246 It should be noted that for this keyword to work, an accessible local archive must contain copies of the same component releases as are identified on the remote server as ones to keep.
       
   247 
       
   248 This keyword may be used multiple times provided it is used for different components each time.
       
   249 
       
   250 =item keep_recent_rel [component] <num_days>
       
   251 
       
   252 Instructs C<cleanremote> to keep any component releases exported within the specified number of days (since the current time). If a component name is specified, C<cleanremote> will only keep component releases which match that name (and are sufficiently recent). Please note that the time is taken from time of export, not time of release.
       
   253 
       
   254 This keyword may be used multiple times if the command is used for different components. 
       
   255 
       
   256 =item keep_recent <num_days>
       
   257 
       
   258 B<Depricated:> Equivalent to keep_recent_rel without a component name entered.
       
   259 
       
   260 =item no_prompt
       
   261 
       
   262 Instructs C<cleanremote> to not prompt the user to delete every component. This is equivalent to typing 'a' (all) at the first component prompt.
       
   263 
       
   264 =back
       
   265 
       
   266 For example:
       
   267 
       
   268  keep_env     pixie alpha
       
   269  keep_env     pixie beta
       
   270  keep_rel     comp1 rel1
       
   271  keep_recent  10
       
   272 
       
   273 C<cleanremote> will work out which component releases need to be kept in order to satisfy the specified keep criteria. All other component releases found in the archive will be deleted (along with temporary files used during FTP uploads). B<It is therefore extremely important that the list of environments to keep is complete>. It is recommended that this file be controlled using a configuration management tool. It is also recommended that each project has only one description file, and that all users of C<cleanremote> know where to find it.
       
   274 
       
   275 Recommended procedure for using C<cleanremote>:
       
   276 
       
   277 =over 4
       
   278 
       
   279 =item 1
       
   280 
       
   281 Inform all users of the archive that a clean is about to be performed, and that the archive will be unavailable whilst this is happening.
       
   282 
       
   283 =item 2
       
   284 
       
   285 Take the archive off-line or alter permissions such that you are the only person that can access it.
       
   286 
       
   287 =item 3
       
   288 
       
   289 Backup the archive.
       
   290 
       
   291 =item 4
       
   292 
       
   293 Run C<cleanremote> and carefully check the list of components that are about to be cleaned. If you are happy, type 'yes' to continue, otherwise type 'no', modify your description file and re-run C<cleanremote>.
       
   294 
       
   295 =item 5
       
   296 
       
   297 Bring the archive back on-line.
       
   298 
       
   299 =item 6
       
   300 
       
   301 Inform all users of the archive that it is available for use once more.
       
   302 
       
   303 =back
       
   304 
       
   305 =head1 STATUS
       
   306 
       
   307 Supported. If you find a problem, please report it to us.
       
   308 
       
   309 =head1 KNOWN BUGS
       
   310 
       
   311 None.
       
   312 
       
   313 =head1 COPYRIGHT
       
   314 
       
   315  Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
   316  All rights reserved.
       
   317  This component and the accompanying materials are made available
       
   318  under the terms of the License "Eclipse Public License v1.0"
       
   319  which accompanies this distribution, and is available
       
   320  at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
   321  
       
   322  Initial Contributors:
       
   323  Nokia Corporation - initial contribution.
       
   324  
       
   325  Contributors:
       
   326  
       
   327  Description:
       
   328  
       
   329 
       
   330 =cut