--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bldsystemtools/commonbldutils/ReleaseNotes.pl Tue Feb 02 01:39:43 2010 +0200
@@ -0,0 +1,580 @@
+#!perl
+
+# Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+# All rights reserved.
+# This component and the accompanying materials are made available
+# under the terms of "Eclipse Public License v1.0"
+# which accompanies this distribution, and is available
+# at the URL "http://www.eclipse.org/legal/epl-v10.html".
+#
+# Initial Contributors:
+# Nokia Corporation - initial contribution.
+#
+# Contributors:
+#
+# Description:
+# GT and TV Release notes generator
+# How this script works...
+# 1.Creates a list of all GT and TV components with their MRP file locations at both the current and previous CL.
+# 2.Iterates through the previous CL list for any components that are not in the current CL list and adds these to
+# the currentCL list.
+# 3.Runs a p4 print for each MRP file and stores each component and its source(s) to an array. Component names in uppercase
+# and source lines in lowercase.
+# 4.Iterates through this array extracting each component name and runs "p4 changes -l -s submitted" between the
+# previous and current CL for each component source.
+# 5.Outputs this data to a HTML file
+#
+#
+
+use strict;
+
+#----------------------------GLOBAL DEFINITIONS-------------------------------------#
+my $Product = $ARGV[0];
+my $Srcpath = $ARGV[1];
+my $PrevCL = $ARGV[2]; #Previous external release changelist number
+my $CurrentCL = $ARGV[3]; #Current external release changelist number
+
+my @PrevMrpComponents; #Array of Components at Previous changelist number
+my @CurrMrpComponents; #Array of Components at Current changelist number
+my @NewMrpComponents; #Array of Merged Components
+
+my @ComponentAndSource; #Array of all components and source
+my @Components; #Array of component names
+
+my $GTfilename; #Location of GTComponents.txt
+my $TVfilename; #Location of TVComponents.txt
+my $GTcomponents; #List of all GTComponents and their MRP file locations
+my $TVcomponents; #List of all TVComponents and their MRP file locations
+
+my $CurrentMrps; #List of all GT and TV components at the current CL number
+my $PreviousMrps; #List of all GT and TV components at the previous CL number
+my $Platform; #Platform of product specified, i.e. beech or cedar
+
+my @CompChange; #Array of component change information
+my @CompLines; #Array of just component changes
+my @CompChangelists; #Array of component changelist numbers
+
+my $CompName; #Component name
+my $Topdir; #Directory of component source
+
+my @NochangeComponents; #Array of components which have not been changed (may contain duplicate components)
+my @UnchangedComponents; #Array of non-duplicate components which have not been changed
+my @ChangedComponents; #Array of components which have been changed
+my @NewComponents; #Array of new components
+my $ProductName; #Name of product
+
+my $ChangeExists; #Flag which indicates any duplicate changes for a component
+my $NewComponent; #Flag which indicates if a component is new or not
+
+my %CodeLine; #Hash for holding main Codeline for each product
+
+my $Marker = "**TECHVIEWCOMPONENTS**\n"; #Marker for splitting GT and TV Components
+
+#-----------------------------------------------------------------------------------#
+
+#Check that correct number of arguments were specified by the user
+#If not then print out Usage instructions to the command window
+Usage() if (@ARGV!=4);
+
+#Check that the inputs are valid
+CheckInputs();
+
+#Assign codeline for product
+%CodeLine = (
+ "8.0" => "//EPOC/release/8.0",
+ "8.1a" => "//EPOC/release/8.1",
+ "8.1b" => "//EPOC/release/8.1",
+ "9.1" => "//EPOC/master",
+ "9.2" => "//EPOC/master",
+ );
+
+#Create a list of all components and their MRP files at both the current and previous CL's
+CreateMRPLists();
+
+#Merge and process the lists
+ProcessLists($PreviousMrps, $CurrentMrps);
+
+#Begin creation of release notes using the merged list of MRPs
+$NewComponent = 0;
+$NewComponent = 1 if ($PrevCL == 0);
+
+$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
+
+$ProductName = "Symbian_OS_v$Product Delivery Release Notes" if($Srcpath =~ m/deliver/i);
+$ProductName = "Symbian_OS_v$Product Release Notes" if ($Srcpath =~ m/release/i);
+if ($Srcpath =~ m/master/i)
+{
+ $ProductName = "Symbian_OS_v$Product MCL Release Notes";
+}
+
+my ( $s, $min, $hour, $mday, $mon, $year, $w, $y, $i)= localtime(time);
+$year+= 1900;
+$mon++;
+
+open OUTFILE, "> $ProductName.html"
+ or die "ERROR: Can't open $ProductName.html for output\n$!";
+print OUTFILE <<HEADING_EOF;
+<html>\n\n<head>\n<title>$ProductName</title>\n</head>\n\n
+<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#5F9F9F\" vlink=\"5F9F9F\">\n
+<font face=verdana,arial,helvetica size=4>\n\n<hr>\n\n
+<a name=\"list\"><h1><center>$ProductName</center></h1></a>
+<p><center>Created - $mday/$mon/$year</center>\n
+<p><center>----------------------------------------</center>\n
+<h2><center>GT Components</center></h2>\n
+HEADING_EOF
+
+foreach my $element(@ComponentAndSource)
+ {
+ my $Preform = 0;
+ my $ChangeCount = 0;
+ my $Exists = 0;
+ my $IsAFile = 0;
+
+ if($element =~ /\*\*TECHVIEWCOMPONENTS\*\*/)
+ {
+ print OUTFILE "<h2><center>Techview Components</center></h2>\n";
+ }
+
+ if($element =~ /^([A-Z].*)/) #Look for component names in array
+ {
+ $CompName = $1;
+ @CompChangelists = ();
+ }
+
+ elsif($element =~ /^([a-z].*)/) #Look for source directories in array
+ {
+ $Topdir = $1;
+ $Topdir =~ s/\s+$//; #drop any trailing spaces
+
+
+ if($Topdir =~ /.*\s+.*/)
+ {
+ $Topdir = "\"$Topdir\"";
+ }
+
+ my $command = "p4 changes -l -s submitted $Srcpath/$Topdir...\@$PrevCL,$CurrentCL";
+ @CompChange = `$command`;
+ die "ERROR: Could not execute: $command\n" if $?;
+
+ foreach my $line(@CompChange)
+ {
+ if ($line !~ /\S/) { next; } # ignore lines with no text
+ chomp $line;
+ $line =~ s/\&/&/g;
+ $line =~ s/\</</g;
+ $line =~ s/\>/>/g;
+ $line =~ s/\"/"/g;
+
+ if($line =~ /^Change\s(\d+)\s/)
+ {
+ my $Change = $1;
+
+ $ChangeExists = 0;
+
+ $line =~ s|\s+by.*||;
+ if ($Preform)
+ {
+ push @CompLines, "</pre>";
+ $Preform = 0;
+ }
+
+ #Check if this change has already been accounted for in this component
+ foreach my $ChangeList(@CompChangelists)
+ {
+ if($ChangeList == $Change)
+ {
+ $ChangeExists = 1;
+ }
+ }
+
+ #If the change is not a duplicate then add it to the changes array and output the change
+ #to Relnotes.
+ if($ChangeExists == 0)
+ {
+ $ChangeCount+=1;
+ push @CompChangelists, $Change;
+ push @CompLines, "<p><b>$line</b>";
+ push @CompLines, "<pre>";
+ }
+
+ $Preform = 1;
+ next;
+ }
+
+ $line =~ s/^\s//; # drop first leading whitespace
+ $line =~ s/^\t/ /; # shorten any leading tab
+
+ if($ChangeExists == 0)
+ {
+ push @CompLines, $line;
+ }
+ }
+
+ if ($ChangeCount == 0)
+ {
+ if ($NewComponent)
+ {
+ push @NewComponents, $CompName;
+ }
+ else
+ {
+ push @NochangeComponents, $CompName;
+ }
+ next;
+ }
+
+ # Component with real change descriptions
+ if ($Preform)
+ {
+ push @CompLines, "</pre>";
+ }
+
+ #Populate the changed components array with all changed components
+ foreach my $entry(@ChangedComponents)
+ {
+ if($entry eq $CompName)
+ {
+ $Exists = 1;
+ }
+ }
+
+ if($Exists == 0)
+ {
+ &PrintLines("<h2>$CompName</h2>",@CompLines);
+ push @ChangedComponents, $CompName;
+ }
+
+ else
+ {
+ &PrintLines("",@CompLines);
+ }
+ }
+
+ @CompLines = ();
+ }
+
+#Get rid of any duplicate component entries in the Unchanged Components list.
+for(my $ii = 0; $ii < @NochangeComponents; $ii++)
+ {
+ if($NochangeComponents[$ii] ne $NochangeComponents[$ii + 1])
+ {
+ push @UnchangedComponents, $NochangeComponents[$ii];
+ }
+ }
+
+#Check for components which have been changed but still appear in the unchanged components list.
+#This can occur when a component has more than one one source. i.e.one source could be changed while the other source
+#remains unchanged.
+foreach my $changed(@ChangedComponents)
+ {
+ foreach my $unchanged(@UnchangedComponents)
+ {
+ if($changed eq $unchanged)
+ {
+ $unchanged = ""; #Empty this array element
+ }
+ }
+ }
+
+#Get rid of any empty elements in the unchanged component array
+my @FinalUnchangedList;
+foreach my $element(@UnchangedComponents)
+ {
+ if($element ne "")
+ {
+ push @FinalUnchangedList, $element;
+ }
+ }
+
+if (scalar @NewComponents)
+ {
+ &PrintLines("<h2>New Components</h2>", join(", ", sort @NewComponents));
+ }
+
+if (scalar @FinalUnchangedList)
+ {
+ if($Srcpath =~ m/deliver/i)
+ {
+ &PrintLines("<h2>Unchanged Components (Delivery)</h2>", join(", ", sort @FinalUnchangedList));
+ }
+ elsif($Srcpath =~ m/release/i)
+ {
+ &PrintLines("<h2>Unchanged Components</h2>", join(", ", sort @FinalUnchangedList));
+ }
+ else
+ {
+ &PrintLines("<h2>Unchanged Components (MCL)</h2>", join(", ", sort @FinalUnchangedList));
+ }
+ }
+
+&PrintLines("</BODY></HTML>");
+close OUTFILE;
+
+#-------------------------------------------SUB-ROUTINES----------------------------------------------#
+
+# CheckInputs
+#
+# Outputs the required platform and an error message if CL numbers are input incorrectly by the user
+#
+#
+sub CheckInputs
+ {
+ #Assign appropriate platform
+ if($Product eq "8.1a"||$Product eq "8.0")
+ {
+ $Platform = "beech";
+ }
+
+ elsif($Product eq "8.1b"||$Product eq "9.0"||$Product eq "9.1"||$Product eq "9.2")
+ {
+ $Platform = "cedar";
+ }
+
+ else
+ {
+ print "Product not recognised or not entered as first command line argument!!\n";
+ exit 1;
+ }
+
+ #Protect against CL numbers being input incorrectly
+ if($PrevCL >= $CurrentCL)
+ {
+ print "Changelist numbers must be entered in the order <Previous> <Current>\n";
+ exit 1;
+ }
+
+ #Remove any trailing / from $Srcpath
+ $Srcpath =~ s|/$||;
+ }
+
+# CreateMRPLists
+#
+# Outputs two lists of components and their MRP file locations at the previous and current CL's
+#
+
+sub CreateMRPLists
+ {
+ my $Prod; #Temporary variable for product. Needed because of 8.0a directory in Perforce
+
+ #Change directory name to 8.0a if product is 8.0
+ if($Product eq "8.0")
+ {
+ $Prod = "8.0a";
+ }
+ else
+ {
+ $Prod = $Product;
+ }
+
+ #Obtain GT and TV MRP File locations from Options.txt
+ my $command = "p4 print -q $CodeLine{$Product}/$Platform/product/tools/makecbr/files/$Prod/options.txt 2>&1";
+ my $OptionsFile = `$command`;
+ die "ERROR: Could not execute: $command\n" if $?;
+
+ my @OptionsFile = split /\n/m, $OptionsFile;
+ foreach my $line(@OptionsFile)
+ {
+ if($line =~ /^Techview component list:(.*)/i)
+ {
+ $TVfilename = $1;
+ $TVfilename =~ s|\\|\/|g;
+ $TVfilename =~ s|/src/.*?/|$CodeLine{$Product}/$Platform/|;
+ }
+ elsif($line =~ /^GT component list:(.*)/i)
+ {
+ $GTfilename = $1;
+ $GTfilename =~ s|\\|\/|g;
+ $GTfilename =~ s|/src/.*?/|$CodeLine{$Product}/$Platform/|;
+ }
+ }
+
+ #Create List of Previous MRPs
+ my $PrevGT = "p4 print -q $GTfilename...\@$PrevCL 2>&1";
+ $GTcomponents = `$PrevGT`;
+ die "ERROR: Could not execute: $PrevGT\n" if $?;
+
+ my $PrevTV = "p4 print -q $TVfilename...\@$PrevCL 2>&1";
+ $TVcomponents = `$PrevTV`;
+ die "ERROR: Could not execute: $PrevTV\n" if $?;
+
+ $GTcomponents = $GTcomponents.$Marker;
+ $PreviousMrps = $GTcomponents.$TVcomponents;
+
+ #Create List of Current MRPs
+ my $CurrGT = "p4 print -q $GTfilename...\@$CurrentCL 2>&1";
+ $GTcomponents = `$CurrGT`;
+ die "ERROR: Could not execute: $CurrGT\n" if $?;
+
+ my $CurrTV = "p4 print -q $TVfilename...\@$CurrentCL 2>&1";
+ $TVcomponents = `$CurrTV`;
+ die "ERROR: Could not execute: $CurrTV\n" if $?;
+
+ $GTcomponents = $GTcomponents.$Marker;
+ $CurrentMrps = $GTcomponents.$TVcomponents;
+ }
+
+# ProcessLists
+#
+# Inputs - Two lists of Components and their MRP file locations at the previous and current CL's
+#
+# Outputs a merged list containing all Components in uppercase and their sourcelines in lowercase
+#
+# Description
+# This function creates a list of all components and their MRP files. The MRP files are then used
+# to obtain the source for each component. This information is then input to an array in the form
+# [COMPONENT1] [source] [COMPONENT2] [source] [source] [COMPONENT3] [source] ..........
+#
+
+sub ProcessLists
+ {
+ if(@_ != 2)
+ {
+ print "Could not process MRP lists as both lists were not provided.\n";
+ exit 1;
+ }
+
+ my $PreviousMrps = shift;
+ my $CurrentMrps = shift;
+ my @MrpContents;
+
+ #Do some slight modifications to source path for both lists
+ $PreviousMrps =~ s|\\|\/|g;
+ $PreviousMrps =~ s|/src/|$CodeLine{$Product}/|ig;
+ $PreviousMrps =~ s|/product/|$CodeLine{$Product}/$Platform/product/|ig;
+
+ $CurrentMrps =~ s|\\|\/|g;
+ $CurrentMrps =~ s|/src/|$CodeLine{$Product}/|ig;
+ $CurrentMrps =~ s|/product/|$CodeLine{$Product}/$Platform/product/|ig;
+
+ @PrevMrpComponents = split /\n/m, $PreviousMrps;
+ @CurrMrpComponents = split /\n/m, $CurrentMrps;
+
+ foreach my $PrevComp(@PrevMrpComponents)
+ {
+ my $match = 0;
+
+ #Compare component lists to ensure they contain the same components.
+ foreach my $CurrComp(@CurrMrpComponents)
+ {
+ if($PrevComp eq $CurrComp)
+ {
+ $match = 1;
+ }
+ }
+
+ #If a component is found in the Previous list which isn't in the Current list, then insert it into the Current list
+ if($match == 0)
+ {
+ push @CurrMrpComponents, $PrevComp;
+ }
+ }
+
+ #Use the MRP locations of each component to obtain the source for each component
+ foreach my $ComponentLine(@CurrMrpComponents)
+ {
+ if($ComponentLine =~ /.*\s+(.*)/)
+ {
+ my $MrpFile = $1;
+
+ my $Temp = `p4 print -q $MrpFile 2>&1`;
+
+ #If a component has been removed between the PrevCL and CurrentCL then its MRP file will
+ #only exist at the PrevCL
+ unless($Temp =~ /source/i)
+ {
+ $Temp = `p4 print -q $MrpFile\@$PrevCL 2>&1`;
+ }
+
+ @MrpContents = split /\n+/m, $Temp;
+ }
+ elsif($ComponentLine =~ /\*\*TECHVIEWCOMPONENTS\*\*/)
+ {
+ push @MrpContents, $ComponentLine;
+ }
+
+ #Construct an array containing components in uppercase followed by all their sourcelines in lowercase
+ foreach my $line(@MrpContents)
+ {
+ if($line =~ /^component\s+(.*)/i)
+ {
+ my $ComponentName = uc($1);
+ push @ComponentAndSource, $ComponentName;
+ }
+
+ if($line =~ /^source\s+(.*)/i)
+ {
+ my $Source = lc($1);
+ $Source =~ s/\\/\//g;
+ $Source =~ s|/src/||;
+ $Source =~ s|/product/|$Platform/product|ig;
+ push @ComponentAndSource, $Source;
+ }
+
+ if($line =~ /TECHVIEWCOMPONENTS/)
+ {
+ push @ComponentAndSource, $line;
+ }
+ }
+ }
+ }
+
+# PrintLines
+#
+# Input - An array containing text information
+#
+# Outputs each element of the input array seperated by a newline to the OUTFILE
+#
+
+sub PrintLines
+ {
+ print OUTFILE join("\n",@_),"\n";
+ }
+
+# Usage
+#
+# Outputs instructions on how to run this script
+#
+
+sub Usage
+ {
+ print <<USAGE_EOF;
+
+Usage
+-----
+perl ReleaseNotes.pl <product> <codeline> <previous CL Num> <current CL Num>
+
+Generates an HTML document containing release notes for the specified product.
+
+<product> The product for which the release notes are to be generated
+eg
+ 8.0, 8.1a, 8.1b, 9.0, 9.1
+
+
+<codeline> The codeline on which the perl tool is to be run
+eg
+ For MCL - //EPOC/master
+ For 8.0 - //EPOC/release/8.0
+ For Delivery (MCL) - //EPOC/deliver/master/2004/<snapshot_number>
+ For Delivery (8.0) - //EPOC/deliver/product/8.0/2004/<snapshot_number>/src
+
+<previous CL Num> The changelist number of the previous external build
+
+<current CL Num> The changelist number of the current external build candidate
+
+
+Example for MCL codeline
+------------------------
+
+perl ReleaseNotes.pl 9.0 //EPOC/Master 438931 442567
+
+This generates release notes in a file named
+Symbian_OS_v9.0 MCL Release Notes.html
+
+USAGE_EOF
+ exit 1;
+ }
+
+
+
+
+