bldsystemtools/commonbldutils/ReleaseNotes.pl
changeset 0 83f4b4db085c
child 1 d4b442d23379
equal deleted inserted replaced
-1:000000000000 0:83f4b4db085c
       
     1 #!perl
       
     2 
       
     3 # Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 # All rights reserved.
       
     5 # This component and the accompanying materials are made available
       
     6 # under the terms of "Eclipse Public License v1.0"
       
     7 # which accompanies this distribution, and is available
       
     8 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     9 #
       
    10 # Initial Contributors:
       
    11 # Nokia Corporation - initial contribution.
       
    12 #
       
    13 # Contributors:
       
    14 #
       
    15 # Description:
       
    16 # GT and TV Release notes generator
       
    17 # How this script works...
       
    18 # 1.Creates a list of all GT and TV components with their MRP file locations at both the current and previous CL.
       
    19 # 2.Iterates through the previous CL list for any components that are not in the current CL list and adds these to 
       
    20 # the currentCL list.
       
    21 # 3.Runs a p4 print for each MRP file and stores each component and its source(s) to an array. Component names in uppercase
       
    22 # and source lines in lowercase.
       
    23 # 4.Iterates through this array extracting each component name and runs "p4 changes -l -s submitted" between the
       
    24 # previous and current CL for each component source.
       
    25 # 5.Outputs this data to a HTML file
       
    26 # 
       
    27 #
       
    28 
       
    29 use strict;
       
    30 
       
    31 #----------------------------GLOBAL DEFINITIONS-------------------------------------#
       
    32 my $Product = $ARGV[0];
       
    33 my $Srcpath = $ARGV[1];
       
    34 my $PrevCL = $ARGV[2];       #Previous external release changelist number
       
    35 my $CurrentCL = $ARGV[3];    #Current external release changelist number
       
    36 
       
    37 my @PrevMrpComponents;	  #Array of Components at Previous changelist number
       
    38 my @CurrMrpComponents;    #Array of Components at Current changelist number
       
    39 my @NewMrpComponents;     #Array of Merged Components
       
    40 
       
    41 my @ComponentAndSource;   #Array of all components and source
       
    42 my @Components;           #Array of component names
       
    43 
       
    44 my $GTfilename;           #Location of GTComponents.txt
       
    45 my $TVfilename;			  #Location of TVComponents.txt
       
    46 my $GTcomponents;         #List of all GTComponents and their MRP file locations
       
    47 my $TVcomponents;		  #List of all TVComponents and their MRP file locations
       
    48 
       
    49 my $CurrentMrps;          #List of all GT and TV components at the current CL number
       
    50 my $PreviousMrps;         #List of all GT and TV components at the previous CL number
       
    51 my $Platform;             #Platform of product specified, i.e. beech or cedar
       
    52 
       
    53 my @CompChange;           #Array of component change information
       
    54 my @CompLines;            #Array of just component changes
       
    55 my @CompChangelists;      #Array of component changelist numbers
       
    56 
       
    57 my $CompName;             #Component name
       
    58 my $Topdir;               #Directory of component source
       
    59 
       
    60 my @NochangeComponents;   #Array of components which have not been changed (may contain duplicate components)
       
    61 my @UnchangedComponents;  #Array of non-duplicate components which have not been changed
       
    62 my @ChangedComponents;    #Array of components which have been changed
       
    63 my @NewComponents;        #Array of new components
       
    64 my $ProductName;          #Name of product
       
    65 
       
    66 my $ChangeExists;         #Flag which indicates any duplicate changes for a component
       
    67 my $NewComponent;         #Flag which indicates if a component is new or not
       
    68 
       
    69 my %CodeLine;             #Hash for holding main Codeline for each product
       
    70 
       
    71 my $Marker = "**TECHVIEWCOMPONENTS**\n";   #Marker for splitting GT and TV Components
       
    72 
       
    73 #-----------------------------------------------------------------------------------#
       
    74 
       
    75 #Check that correct number of arguments were specified by the user
       
    76 #If not then print out Usage instructions to the command window	
       
    77 Usage() if (@ARGV!=4);
       
    78 
       
    79 #Check that the inputs are valid
       
    80 CheckInputs();
       
    81 
       
    82 #Assign codeline for product
       
    83 %CodeLine = (
       
    84 	     "8.0" => "//EPOC/release/8.0",
       
    85 	     "8.1a" => "//EPOC/release/8.1",
       
    86 	     "8.1b" => "//EPOC/release/8.1",
       
    87 	     "9.1" => "//EPOC/master",
       
    88 	     "9.2" => "//EPOC/master",
       
    89 	    );
       
    90 
       
    91 #Create a list of all components and their MRP files at both the current and previous CL's
       
    92 CreateMRPLists();
       
    93 
       
    94 #Merge and process the lists
       
    95 ProcessLists($PreviousMrps, $CurrentMrps);
       
    96 
       
    97 #Begin creation of release notes using the merged list of MRPs
       
    98 $NewComponent = 0;
       
    99 $NewComponent = 1 if ($PrevCL == 0);
       
   100 
       
   101 $PrevCL++;     # inc changelist number so we don't include the very first submission - it would have been picked up in the last run of this script
       
   102 
       
   103 $ProductName = "Symbian_OS_v$Product Delivery Release Notes" if($Srcpath =~ m/deliver/i);
       
   104 $ProductName = "Symbian_OS_v$Product Release Notes" if ($Srcpath =~ m/release/i);
       
   105 if ($Srcpath =~ m/master/i)
       
   106 {
       
   107 	$ProductName = "Symbian_OS_v$Product MCL Release Notes";
       
   108 }
       
   109 
       
   110 my ( $s, $min, $hour, $mday, $mon, $year, $w, $y, $i)= localtime(time);
       
   111 $year+= 1900;
       
   112 $mon++;
       
   113 
       
   114 open OUTFILE, "> $ProductName.html"
       
   115 	or die "ERROR: Can't open $ProductName.html for output\n$!";
       
   116 print OUTFILE <<HEADING_EOF;
       
   117 <html>\n\n<head>\n<title>$ProductName</title>\n</head>\n\n
       
   118 <body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#5F9F9F\" vlink=\"5F9F9F\">\n
       
   119 <font face=verdana,arial,helvetica size=4>\n\n<hr>\n\n
       
   120 <a name=\"list\"><h1><center>$ProductName</center></h1></a>
       
   121 <p><center>Created - $mday/$mon/$year</center>\n
       
   122 <p><center>----------------------------------------</center>\n
       
   123 <h2><center>GT Components</center></h2>\n
       
   124 HEADING_EOF
       
   125 
       
   126 foreach my $element(@ComponentAndSource)
       
   127 	{
       
   128 	my $Preform = 0;
       
   129 	my $ChangeCount = 0;
       
   130 	my $Exists = 0;
       
   131 	my $IsAFile = 0;
       
   132 	
       
   133 	if($element =~ /\*\*TECHVIEWCOMPONENTS\*\*/)
       
   134 		{
       
   135 		print OUTFILE "<h2><center>Techview Components</center></h2>\n";
       
   136 		}
       
   137 	
       
   138 	if($element =~ /^([A-Z].*)/)  #Look for component names in array
       
   139 		{
       
   140 		$CompName = $1;
       
   141 		@CompChangelists = ();
       
   142 		}
       
   143 	
       
   144 	elsif($element =~ /^([a-z].*)/)  #Look for source directories in array
       
   145 		{
       
   146 		$Topdir = $1;
       
   147 		$Topdir =~ s/\s+$//;  #drop any trailing spaces
       
   148 
       
   149 		
       
   150 		if($Topdir =~ /.*\s+.*/)
       
   151 			{
       
   152 			$Topdir = "\"$Topdir\"";
       
   153 			}
       
   154 		
       
   155 		my $command = "p4 changes -l -s submitted $Srcpath/$Topdir...\@$PrevCL,$CurrentCL";
       
   156 		@CompChange = `$command`;
       
   157 		die "ERROR: Could not execute: $command\n" if $?;
       
   158 		
       
   159 		foreach my $line(@CompChange)
       
   160 			{	
       
   161 			if ($line !~ /\S/) { next; }      # ignore lines with no text 
       
   162 	      	chomp $line;
       
   163 	      	$line =~ s/\&/&amp;/g;
       
   164       		$line =~ s/\</&lt;/g;
       
   165      		$line =~ s/\>/&gt;/g;
       
   166       		$line =~ s/\"/&quot;/g;
       
   167 	      		
       
   168 			if($line =~ /^Change\s(\d+)\s/)
       
   169 				{
       
   170 				my $Change = $1;
       
   171 				
       
   172 				$ChangeExists = 0;
       
   173 				
       
   174 				$line =~ s|\s+by.*||;
       
   175 				if ($Preform) 
       
   176           			{ 
       
   177           			push @CompLines, "</pre>"; 
       
   178           			$Preform = 0; 
       
   179           			}
       
   180           		
       
   181           		#Check if this change has already been accounted for in this component
       
   182           		foreach my $ChangeList(@CompChangelists)
       
   183          			{
       
   184 	          		if($ChangeList == $Change)
       
   185 	          			{
       
   186 		          		$ChangeExists = 1;
       
   187 	          			}
       
   188          			}
       
   189           		
       
   190          		#If the change is not a duplicate then add it to the changes array and output the change
       
   191          		#to Relnotes.
       
   192           		if($ChangeExists == 0)
       
   193           			{
       
   194 	          		$ChangeCount+=1;
       
   195 	          		push @CompChangelists, $Change;
       
   196        				push @CompLines, "<p><b>$line</b>";
       
   197         			push @CompLines, "<pre>";
       
   198     				}
       
   199     			
       
   200     			$Preform = 1;
       
   201         		next;
       
   202 				}
       
   203 				
       
   204 			$line =~ s/^\s//;                 # drop first leading whitespace
       
   205    			$line =~ s/^\t/  /;               # shorten any leading tab
       
   206       		
       
   207    			if($ChangeExists == 0)
       
   208    				{
       
   209    				push @CompLines, $line;
       
   210 				}
       
   211 			}
       
   212 		
       
   213 		if ($ChangeCount == 0)
       
   214    			{
       
   215     		if ($NewComponent)
       
   216     			{
       
   217     			push @NewComponents, $CompName;
       
   218     			}
       
   219     		else
       
   220     			{	
       
   221     			push @NochangeComponents, $CompName;
       
   222     			}
       
   223     			next;
       
   224     		}
       
   225     		
       
   226     	# Component with real change descriptions
       
   227 		if ($Preform)
       
   228 			{
       
   229 			push @CompLines, "</pre>";
       
   230 			}
       
   231 		
       
   232 		#Populate the changed components array with all changed components
       
   233 		foreach my $entry(@ChangedComponents)
       
   234 			{
       
   235 			if($entry eq $CompName)
       
   236 				{
       
   237 				$Exists = 1;
       
   238 				}
       
   239 			}
       
   240 			
       
   241 		if($Exists == 0)
       
   242 			{
       
   243 			&PrintLines("<h2>$CompName</h2>",@CompLines);
       
   244 			push @ChangedComponents, $CompName;
       
   245 			}
       
   246 		
       
   247 		else
       
   248 			{
       
   249 			&PrintLines("",@CompLines);
       
   250 			}
       
   251 		}
       
   252 		
       
   253 		@CompLines = ();
       
   254 	}
       
   255 
       
   256 #Get rid of any duplicate component entries in the Unchanged Components list.
       
   257 for(my $ii = 0; $ii < @NochangeComponents; $ii++)
       
   258 	{
       
   259 	if($NochangeComponents[$ii] ne $NochangeComponents[$ii + 1])
       
   260 		{
       
   261 		push @UnchangedComponents, $NochangeComponents[$ii];
       
   262 		}
       
   263 	}
       
   264 
       
   265 #Check for components which have been changed but still appear in the unchanged components list.
       
   266 #This can occur when a component has more than one one source. i.e.one source could be changed while the other source
       
   267 #remains unchanged.
       
   268 foreach my $changed(@ChangedComponents)
       
   269 	{
       
   270 	foreach my $unchanged(@UnchangedComponents)
       
   271 		{
       
   272 		if($changed eq $unchanged)
       
   273 			{
       
   274 			$unchanged = "";       #Empty this array element
       
   275 			}
       
   276 		}
       
   277 	}
       
   278 
       
   279 #Get rid of any empty elements in the unchanged component array
       
   280 my @FinalUnchangedList;
       
   281 foreach my $element(@UnchangedComponents)
       
   282 	{
       
   283 	if($element ne "")
       
   284 		{
       
   285 		push @FinalUnchangedList, $element;
       
   286 		}
       
   287 	}
       
   288 
       
   289 if (scalar @NewComponents)
       
   290 	{
       
   291 	&PrintLines("<h2>New Components</h2>", join(", ", sort @NewComponents));
       
   292 	}
       
   293 	
       
   294 if (scalar @FinalUnchangedList)
       
   295 	{
       
   296 	if($Srcpath =~ m/deliver/i)
       
   297 		{
       
   298 		&PrintLines("<h2>Unchanged Components (Delivery)</h2>", join(", ", sort @FinalUnchangedList));
       
   299 		}
       
   300 	elsif($Srcpath =~ m/release/i)
       
   301 		{
       
   302 		&PrintLines("<h2>Unchanged Components</h2>", join(", ", sort @FinalUnchangedList));
       
   303 		}
       
   304 	else
       
   305 		{
       
   306 		&PrintLines("<h2>Unchanged Components (MCL)</h2>", join(", ", sort @FinalUnchangedList));
       
   307 		}
       
   308 	}
       
   309 
       
   310 &PrintLines("</BODY></HTML>");
       
   311 close OUTFILE;
       
   312 
       
   313 #-------------------------------------------SUB-ROUTINES----------------------------------------------#
       
   314 
       
   315 # CheckInputs
       
   316 #
       
   317 # Outputs the required platform and an error message if CL numbers are input incorrectly by the user
       
   318 #
       
   319 #
       
   320 sub CheckInputs
       
   321 	{
       
   322 	#Assign appropriate platform
       
   323 	if($Product eq "8.1a"||$Product eq "8.0")
       
   324 		{
       
   325 		$Platform = "beech";
       
   326 		}
       
   327 
       
   328 	elsif($Product eq "8.1b"||$Product eq "9.0"||$Product eq "9.1"||$Product eq "9.2")
       
   329 		{
       
   330 		$Platform = "cedar";
       
   331 		}
       
   332 
       
   333 	else
       
   334 		{
       
   335 		print "Product not recognised or not entered as first command line argument!!\n";
       
   336 		exit 1;
       
   337 		}
       
   338 
       
   339 	#Protect against CL numbers being input incorrectly
       
   340 	if($PrevCL >= $CurrentCL)
       
   341 		{
       
   342 		print "Changelist numbers must be entered in the order <Previous> <Current>\n";
       
   343 		exit 1;
       
   344 		}
       
   345         
       
   346         #Remove any trailing / from $Srcpath
       
   347         $Srcpath =~ s|/$||;
       
   348 	}
       
   349 
       
   350 # CreateMRPLists
       
   351 #
       
   352 # Outputs two lists of components and their MRP file locations at the previous and current CL's
       
   353 #
       
   354 
       
   355 sub CreateMRPLists
       
   356 	{
       
   357 	my $Prod;       #Temporary variable for product.  Needed because of 8.0a directory in Perforce
       
   358 	
       
   359 	#Change directory name to 8.0a if product is 8.0
       
   360 	if($Product eq "8.0")
       
   361 		{
       
   362 		$Prod = "8.0a";
       
   363 		}
       
   364 	else
       
   365 		{
       
   366 		$Prod = $Product;
       
   367 		}
       
   368 		
       
   369 	#Obtain GT and TV MRP File locations from Options.txt
       
   370 	my $command = "p4 print -q $CodeLine{$Product}/$Platform/product/tools/makecbr/files/$Prod/options.txt 2>&1";
       
   371 	my $OptionsFile = `$command`;
       
   372 	die "ERROR: Could not execute: $command\n" if $?;
       
   373 	
       
   374 	my @OptionsFile = split /\n/m, $OptionsFile;
       
   375 	foreach my $line(@OptionsFile)
       
   376 		{
       
   377 		if($line =~ /^Techview component list:(.*)/i)
       
   378 			{
       
   379 				$TVfilename = $1;
       
   380 				$TVfilename =~ s|\\|\/|g;
       
   381 				$TVfilename =~ s|/src/.*?/|$CodeLine{$Product}/$Platform/|;
       
   382 			}
       
   383 		elsif($line =~ /^GT component list:(.*)/i)
       
   384 			{
       
   385 				$GTfilename = $1;
       
   386 				$GTfilename =~ s|\\|\/|g;
       
   387 				$GTfilename =~ s|/src/.*?/|$CodeLine{$Product}/$Platform/|;
       
   388 			}
       
   389 		}
       
   390 
       
   391 	#Create List of Previous MRPs
       
   392 	my $PrevGT = "p4 print -q $GTfilename...\@$PrevCL 2>&1";
       
   393 	$GTcomponents = `$PrevGT`;
       
   394 	die "ERROR: Could not execute: $PrevGT\n" if $?;
       
   395 	
       
   396 	my $PrevTV = "p4 print -q $TVfilename...\@$PrevCL 2>&1";
       
   397 	$TVcomponents = `$PrevTV`;
       
   398 	die "ERROR: Could not execute: $PrevTV\n" if $?;
       
   399 	
       
   400 	$GTcomponents = $GTcomponents.$Marker;
       
   401 	$PreviousMrps = $GTcomponents.$TVcomponents;
       
   402 
       
   403 	#Create List of Current MRPs
       
   404 	my $CurrGT = "p4 print -q $GTfilename...\@$CurrentCL 2>&1";
       
   405 	$GTcomponents = `$CurrGT`;
       
   406 	die "ERROR: Could not execute: $CurrGT\n" if $?;
       
   407 	
       
   408 	my $CurrTV = "p4 print -q $TVfilename...\@$CurrentCL 2>&1";
       
   409 	$TVcomponents = `$CurrTV`;
       
   410 	die "ERROR: Could not execute: $CurrTV\n" if $?;
       
   411 	
       
   412 	$GTcomponents = $GTcomponents.$Marker;
       
   413 	$CurrentMrps = $GTcomponents.$TVcomponents;
       
   414 	}
       
   415 
       
   416 # ProcessLists
       
   417 #
       
   418 # Inputs - Two lists of Components and their MRP file locations at the previous and current CL's
       
   419 #
       
   420 # Outputs a merged list containing all Components in uppercase and their sourcelines in lowercase
       
   421 #
       
   422 # Description
       
   423 # This function creates a list of all components and their MRP files. The MRP files are then used
       
   424 # to obtain the source for each component. This information is then input to an array in the form
       
   425 # [COMPONENT1] [source] [COMPONENT2] [source] [source] [COMPONENT3] [source] ..........
       
   426 #
       
   427 
       
   428 sub ProcessLists
       
   429 	{
       
   430 	if(@_ != 2)
       
   431 	{
       
   432 		print "Could not process MRP lists as both lists were not provided.\n";
       
   433 		exit 1;
       
   434 	}
       
   435 	
       
   436 	my $PreviousMrps = shift;
       
   437 	my $CurrentMrps = shift;
       
   438 	my @MrpContents;
       
   439 	
       
   440 	#Do some slight modifications to source path for both lists
       
   441 	$PreviousMrps =~ s|\\|\/|g;
       
   442 	$PreviousMrps =~ s|/src/|$CodeLine{$Product}/|ig;
       
   443 	$PreviousMrps =~ s|/product/|$CodeLine{$Product}/$Platform/product/|ig;
       
   444 	
       
   445 	$CurrentMrps =~ s|\\|\/|g;
       
   446 	$CurrentMrps =~ s|/src/|$CodeLine{$Product}/|ig;
       
   447 	$CurrentMrps =~ s|/product/|$CodeLine{$Product}/$Platform/product/|ig;
       
   448 	
       
   449 	@PrevMrpComponents = split /\n/m, $PreviousMrps;
       
   450 	@CurrMrpComponents = split /\n/m, $CurrentMrps;
       
   451 	
       
   452 	foreach my $PrevComp(@PrevMrpComponents)
       
   453 		{
       
   454 		my $match = 0;
       
   455 		
       
   456 		#Compare component lists to ensure they contain the same components.
       
   457 		foreach my $CurrComp(@CurrMrpComponents)
       
   458 			{
       
   459 			if($PrevComp eq $CurrComp)
       
   460 				{
       
   461 				$match = 1;
       
   462 				}
       
   463 			}
       
   464 		
       
   465 		#If a component is found in the Previous list which isn't in the Current list, then insert it into the Current list
       
   466 		if($match == 0)
       
   467 			{
       
   468 			push @CurrMrpComponents, $PrevComp;
       
   469 			}
       
   470 		}
       
   471 
       
   472 	#Use the MRP locations of each component to obtain the source for each component
       
   473 	foreach my $ComponentLine(@CurrMrpComponents)
       
   474 		{
       
   475 		if($ComponentLine =~ /.*\s+(.*)/)
       
   476 			{
       
   477 			my $MrpFile = $1;
       
   478 		
       
   479 			my $Temp = `p4 print -q $MrpFile 2>&1`;
       
   480 			
       
   481 			#If a component has been removed between the PrevCL and CurrentCL then its MRP file will
       
   482 			#only exist at the PrevCL
       
   483 			unless($Temp =~ /source/i)
       
   484 				{
       
   485 				$Temp = `p4 print -q $MrpFile\@$PrevCL 2>&1`;
       
   486 				}
       
   487 				
       
   488 			@MrpContents = split /\n+/m, $Temp;
       
   489 			}
       
   490 		elsif($ComponentLine =~ /\*\*TECHVIEWCOMPONENTS\*\*/)
       
   491 			{
       
   492 			push @MrpContents, $ComponentLine;
       
   493 			}
       
   494 		
       
   495 		#Construct an array containing components in uppercase followed by all their sourcelines in lowercase
       
   496 		foreach my $line(@MrpContents)
       
   497 			{
       
   498 			if($line =~ /^component\s+(.*)/i)
       
   499 				{
       
   500 				my $ComponentName = uc($1);
       
   501 				push @ComponentAndSource, $ComponentName;
       
   502 				}
       
   503 			
       
   504 			if($line =~ /^source\s+(.*)/i)
       
   505 				{
       
   506 				my $Source = lc($1);
       
   507 				$Source =~ s/\\/\//g;
       
   508 				$Source =~ s|/src/||;
       
   509 				$Source =~ s|/product/|$Platform/product|ig;
       
   510 				push @ComponentAndSource, $Source;
       
   511 				}
       
   512 				
       
   513 			if($line =~ /TECHVIEWCOMPONENTS/)
       
   514 				{
       
   515 				push @ComponentAndSource, $line;
       
   516 				}
       
   517 			}
       
   518 		}
       
   519 	}
       
   520 
       
   521 # PrintLines
       
   522 #
       
   523 # Input - An array containing text information
       
   524 #
       
   525 # Outputs each element of the input array seperated by a newline to the OUTFILE
       
   526 #
       
   527 
       
   528 sub PrintLines 
       
   529 	{ 
       
   530 	print OUTFILE join("\n",@_),"\n"; 
       
   531 	}
       
   532 
       
   533 # Usage
       
   534 #
       
   535 # Outputs instructions on how to run this script
       
   536 #
       
   537 
       
   538 sub Usage
       
   539 	{
       
   540 	 print <<USAGE_EOF;
       
   541 
       
   542 Usage
       
   543 -----
       
   544 perl ReleaseNotes.pl <product> <codeline> <previous CL Num> <current CL Num>
       
   545 
       
   546 Generates an HTML document containing release notes for the specified product.
       
   547 
       
   548 <product> The product for which the release notes are to be generated
       
   549 eg
       
   550   8.0, 8.1a, 8.1b, 9.0, 9.1
       
   551 
       
   552 
       
   553 <codeline> The codeline on which the perl tool is to be run
       
   554 eg
       
   555   For MCL - //EPOC/master
       
   556   For 8.0 - //EPOC/release/8.0
       
   557   For Delivery (MCL) - //EPOC/deliver/master/2004/<snapshot_number>
       
   558   For Delivery (8.0) - //EPOC/deliver/product/8.0/2004/<snapshot_number>/src
       
   559 
       
   560 <previous CL Num> The changelist number of the previous external build
       
   561 
       
   562 <current CL Num> The changelist number of the current external build candidate
       
   563 
       
   564 
       
   565 Example for MCL codeline
       
   566 ------------------------
       
   567 
       
   568 perl ReleaseNotes.pl 9.0 //EPOC/Master 438931 442567
       
   569 
       
   570 This generates release notes in a file named
       
   571 Symbian_OS_v9.0 MCL Release Notes.html
       
   572 
       
   573 USAGE_EOF
       
   574   	exit 1;
       
   575 	}
       
   576 
       
   577 
       
   578 
       
   579 
       
   580