1*b1cdbd2cSJim Jagielski: 2*b1cdbd2cSJim Jagielskieval 'exec perl -wS $0 ${1+"$@"}' 3*b1cdbd2cSJim Jagielski if 0; 4*b1cdbd2cSJim Jagielski#************************************************************** 5*b1cdbd2cSJim Jagielski# 6*b1cdbd2cSJim Jagielski# Licensed to the Apache Software Foundation (ASF) under one 7*b1cdbd2cSJim Jagielski# or more contributor license agreements. See the NOTICE file 8*b1cdbd2cSJim Jagielski# distributed with this work for additional information 9*b1cdbd2cSJim Jagielski# regarding copyright ownership. The ASF licenses this file 10*b1cdbd2cSJim Jagielski# to you under the Apache License, Version 2.0 (the 11*b1cdbd2cSJim Jagielski# "License"); you may not use this file except in compliance 12*b1cdbd2cSJim Jagielski# with the License. You may obtain a copy of the License at 13*b1cdbd2cSJim Jagielski# 14*b1cdbd2cSJim Jagielski# http://www.apache.org/licenses/LICENSE-2.0 15*b1cdbd2cSJim Jagielski# 16*b1cdbd2cSJim Jagielski# Unless required by applicable law or agreed to in writing, 17*b1cdbd2cSJim Jagielski# software distributed under the License is distributed on an 18*b1cdbd2cSJim Jagielski# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19*b1cdbd2cSJim Jagielski# KIND, either express or implied. See the License for the 20*b1cdbd2cSJim Jagielski# specific language governing permissions and limitations 21*b1cdbd2cSJim Jagielski# under the License. 22*b1cdbd2cSJim Jagielski# 23*b1cdbd2cSJim Jagielski#************************************************************** 24*b1cdbd2cSJim Jagielski 25*b1cdbd2cSJim Jagielski 26*b1cdbd2cSJim Jagielski# 27*b1cdbd2cSJim Jagielski# 28*b1cdbd2cSJim Jagielski# checkdeliver.pl - compare delivered files on solver with those on SRC_ROOT 29*b1cdbd2cSJim Jagielski# 30*b1cdbd2cSJim Jagielski 31*b1cdbd2cSJim Jagielskiuse strict; 32*b1cdbd2cSJim Jagielskiuse Getopt::Long; 33*b1cdbd2cSJim Jagielskiuse File::stat; 34*b1cdbd2cSJim Jagielskiuse IO::Handle; 35*b1cdbd2cSJim Jagielski 36*b1cdbd2cSJim Jagielskiuse lib ("$ENV{SOLARENV}/bin/modules"); 37*b1cdbd2cSJim Jagielski 38*b1cdbd2cSJim Jagielski#### globals ##### 39*b1cdbd2cSJim Jagielski 40*b1cdbd2cSJim Jagielskimy $err = 0; 41*b1cdbd2cSJim Jagielskimy $srcrootdir = ''; 42*b1cdbd2cSJim Jagielskimy $solverdir = ''; 43*b1cdbd2cSJim Jagielskimy $platform = ''; 44*b1cdbd2cSJim Jagielskimy $logfile = ''; 45*b1cdbd2cSJim Jagielskimy $milestoneext = ''; 46*b1cdbd2cSJim Jagielskimy $local_env = 0; 47*b1cdbd2cSJim Jagielskimy @exceptionmodlist = ( 48*b1cdbd2cSJim Jagielski "postprocess", 49*b1cdbd2cSJim Jagielski "instset.*native", 50*b1cdbd2cSJim Jagielski "smoketest.*native", 51*b1cdbd2cSJim Jagielski "testgraphical" 52*b1cdbd2cSJim Jagielski ); # modules not yet delivered 53*b1cdbd2cSJim Jagielski 54*b1cdbd2cSJim Jagielski#### main ##### 55*b1cdbd2cSJim Jagielski 56*b1cdbd2cSJim Jagielskiprint_logged("checkdeliver.pl - checking delivered binaries\n"); 57*b1cdbd2cSJim Jagielski 58*b1cdbd2cSJim Jagielskiget_globals(); # get global variables 59*b1cdbd2cSJim Jagielskimy $deliverlists_ref = get_deliver_lists(); # get deliver log files 60*b1cdbd2cSJim Jagielskiforeach my $listfile ( @$deliverlists_ref ) { 61*b1cdbd2cSJim Jagielski $err += check( $listfile ); # check delivered files 62*b1cdbd2cSJim Jagielski} 63*b1cdbd2cSJim Jagielskiprint_logged("OK\n") if ( ! $err ); 64*b1cdbd2cSJim Jagielskiexit $err; 65*b1cdbd2cSJim Jagielski 66*b1cdbd2cSJim Jagielski#### subroutines #### 67*b1cdbd2cSJim Jagielski 68*b1cdbd2cSJim Jagielskisub get_globals 69*b1cdbd2cSJim Jagielski# set global variables using environment variables and command line options 70*b1cdbd2cSJim Jagielski{ 71*b1cdbd2cSJim Jagielski my $help; 72*b1cdbd2cSJim Jagielski 73*b1cdbd2cSJim Jagielski # set global variables according to environnment 74*b1cdbd2cSJim Jagielski $platform = $ENV{INPATH}; 75*b1cdbd2cSJim Jagielski $srcrootdir = $ENV{SOURCE_ROOT_DIR}; 76*b1cdbd2cSJim Jagielski $solverdir = $ENV{SOLARVERSION}; 77*b1cdbd2cSJim Jagielski $milestoneext = $ENV{UPDMINOREXT}; 78*b1cdbd2cSJim Jagielski 79*b1cdbd2cSJim Jagielski # override environment with command line options 80*b1cdbd2cSJim Jagielski GetOptions('help' => \$help, 81*b1cdbd2cSJim Jagielski 'l=s' => \$logfile, 82*b1cdbd2cSJim Jagielski 'p=s' => \$platform 83*b1cdbd2cSJim Jagielski ) or usage (1); 84*b1cdbd2cSJim Jagielski 85*b1cdbd2cSJim Jagielski if ( $help ) { 86*b1cdbd2cSJim Jagielski usage(0); 87*b1cdbd2cSJim Jagielski } 88*b1cdbd2cSJim Jagielski 89*b1cdbd2cSJim Jagielski #do some sanity checks 90*b1cdbd2cSJim Jagielski if ( ! ( $platform && $srcrootdir && $solverdir ) ) { 91*b1cdbd2cSJim Jagielski die "Error: please set environment\n"; 92*b1cdbd2cSJim Jagielski } 93*b1cdbd2cSJim Jagielski if ( ! -d $solverdir ) { 94*b1cdbd2cSJim Jagielski die "Error: cannot find solver directory '$solverdir'\n"; 95*b1cdbd2cSJim Jagielski } 96*b1cdbd2cSJim Jagielski 97*b1cdbd2cSJim Jagielski # Check for local env., taken from solenv/bin/modules/installer/control.pm 98*b1cdbd2cSJim Jagielski # In this case the content of SOLARENV starts with the content of SOL_TMP 99*b1cdbd2cSJim Jagielski my $solarenv = ""; 100*b1cdbd2cSJim Jagielski my $sol_tmp; 101*b1cdbd2cSJim Jagielski if ( $ENV{'SOLARENV'} ) { 102*b1cdbd2cSJim Jagielski $solarenv = $ENV{'SOLARENV'}; 103*b1cdbd2cSJim Jagielski } 104*b1cdbd2cSJim Jagielski if ( $ENV{'SOL_TMP'} ) { 105*b1cdbd2cSJim Jagielski $sol_tmp = $ENV{'SOL_TMP'}; 106*b1cdbd2cSJim Jagielski } 107*b1cdbd2cSJim Jagielski if ( defined $sol_tmp && ( $solarenv =~ /^\s*\Q$sol_tmp\E/ )) { 108*b1cdbd2cSJim Jagielski # Content of SOLARENV starts with the content of SOL_TMP: Local environment 109*b1cdbd2cSJim Jagielski $local_env = 1; 110*b1cdbd2cSJim Jagielski } 111*b1cdbd2cSJim Jagielski} 112*b1cdbd2cSJim Jagielski 113*b1cdbd2cSJim Jagielskisub get_deliver_lists 114*b1cdbd2cSJim Jagielski# find deliver log files on solver 115*b1cdbd2cSJim Jagielski{ 116*b1cdbd2cSJim Jagielski my @files; 117*b1cdbd2cSJim Jagielski my $pattern = "$solverdir/$platform/inc"; 118*b1cdbd2cSJim Jagielski $pattern .= "$milestoneext" if ( $milestoneext ); 119*b1cdbd2cSJim Jagielski $pattern .= "/*/deliver.log"; 120*b1cdbd2cSJim Jagielski 121*b1cdbd2cSJim Jagielski @files = glob( $pattern ); 122*b1cdbd2cSJim Jagielski # do not check modules not yet built 123*b1cdbd2cSJim Jagielski foreach my $exceptionpattern ( @exceptionmodlist ) { 124*b1cdbd2cSJim Jagielski @files = grep ! /\/$exceptionpattern\//, @files; 125*b1cdbd2cSJim Jagielski } 126*b1cdbd2cSJim Jagielski if ( ! @files ) { 127*b1cdbd2cSJim Jagielski print_logged( "Error: cannot find deliver log files\n" ); 128*b1cdbd2cSJim Jagielski exit 1; 129*b1cdbd2cSJim Jagielski } 130*b1cdbd2cSJim Jagielski return \@files; 131*b1cdbd2cSJim Jagielski} 132*b1cdbd2cSJim Jagielski 133*b1cdbd2cSJim Jagielskisub check 134*b1cdbd2cSJim Jagielski# reads deliver log file given as parameter and compares pairs of files listed there. 135*b1cdbd2cSJim Jagielski{ 136*b1cdbd2cSJim Jagielski my $listname = shift; 137*b1cdbd2cSJim Jagielski my $error = 0; 138*b1cdbd2cSJim Jagielski my %delivered; 139*b1cdbd2cSJim Jagielski my $module; 140*b1cdbd2cSJim Jagielski my $repository; 141*b1cdbd2cSJim Jagielski STDOUT->autoflush(1); 142*b1cdbd2cSJim Jagielski # which module are we checking? 143*b1cdbd2cSJim Jagielski if ( $listname =~ /\/([\w-]+?)\/deliver\.log$/o) { 144*b1cdbd2cSJim Jagielski $module = $1; 145*b1cdbd2cSJim Jagielski } else { 146*b1cdbd2cSJim Jagielski print_logged( "Error: cannot determine module name from \'$listname\'\n" ); 147*b1cdbd2cSJim Jagielski return 1; 148*b1cdbd2cSJim Jagielski } 149*b1cdbd2cSJim Jagielski 150*b1cdbd2cSJim Jagielski if ( -z $listname ) { 151*b1cdbd2cSJim Jagielski print_logged( "Warning: empty deliver log file \'$listname\'. Module '$module' not delivered correctly?\n\n" ); 152*b1cdbd2cSJim Jagielski return 0; 153*b1cdbd2cSJim Jagielski } 154*b1cdbd2cSJim Jagielski 155*b1cdbd2cSJim Jagielski # read deliver log file 156*b1cdbd2cSJim Jagielski if ( ! open( DELIVERLOG, "< $listname" ) ) { 157*b1cdbd2cSJim Jagielski print_logged( "Error: cannot open file \'$listname\'\n$!" ); 158*b1cdbd2cSJim Jagielski exit 2; 159*b1cdbd2cSJim Jagielski } 160*b1cdbd2cSJim Jagielski while ( <DELIVERLOG> ) { 161*b1cdbd2cSJim Jagielski next if ( /^LINK / ); 162*b1cdbd2cSJim Jagielski # What's this modules' repository? 163*b1cdbd2cSJim Jagielski if ( /COPY\s+(.+?)\/$module\/prj\/build.lst/ ) { 164*b1cdbd2cSJim Jagielski# if ( /COPY (\w[\w\s-]*?)\/$module\/prj\/build.lst/ ) { 165*b1cdbd2cSJim Jagielski $repository = $1; 166*b1cdbd2cSJim Jagielski } 167*b1cdbd2cSJim Jagielski # For now we concentrate on binaries, located in 'bin' or 'lib' and 'misc/build/<...>/[bin|lib]'. 168*b1cdbd2cSJim Jagielski next if ( (! /\/$module\/$platform\/[bl]i[nb]\//) && (! /\/$module\/$platform\/misc\/build\//)); 169*b1cdbd2cSJim Jagielski next if (! /[bl]i[nb]/); 170*b1cdbd2cSJim Jagielski next if ( /\.html$/ ); 171*b1cdbd2cSJim Jagielski chomp; 172*b1cdbd2cSJim Jagielski if ( /^\w+? (\S+) (\S+)\s*$/o ) { 173*b1cdbd2cSJim Jagielski my $origin = $1; 174*b1cdbd2cSJim Jagielski $delivered{$origin} = $2; 175*b1cdbd2cSJim Jagielski } else { 176*b1cdbd2cSJim Jagielski print_logged( "Warning: cannot parse \'$listname\' line\n\'$_\'\n" ); 177*b1cdbd2cSJim Jagielski } 178*b1cdbd2cSJim Jagielski } 179*b1cdbd2cSJim Jagielski close( DELIVERLOG ); 180*b1cdbd2cSJim Jagielski 181*b1cdbd2cSJim Jagielski if ( ! $repository ) { 182*b1cdbd2cSJim Jagielski print_logged( "Error parsing \'$listname\': cannot determine repository. Module '$module' not delivered correctly?\n\n" ); 183*b1cdbd2cSJim Jagielski $error ++; 184*b1cdbd2cSJim Jagielski return $error; 185*b1cdbd2cSJim Jagielski } 186*b1cdbd2cSJim Jagielski 187*b1cdbd2cSJim Jagielski my $path = "$srcrootdir/$repository/$module"; 188*b1cdbd2cSJim Jagielski # is module physically accessible? 189*b1cdbd2cSJim Jagielski # there are valid use cases where we build against a prebuild solver whithout having 190*b1cdbd2cSJim Jagielski # all modules at disk 191*b1cdbd2cSJim Jagielski my $canread = is_moduledirectory( $path ); 192*b1cdbd2cSJim Jagielski if ( ! $canread ) { 193*b1cdbd2cSJim Jagielski # do not bother about non existing modules in local environment 194*b1cdbd2cSJim Jagielski # or on childworkspaces 195*b1cdbd2cSJim Jagielski if (( $local_env ) || ( $ENV{CWS_WORK_STAMP} )) { 196*b1cdbd2cSJim Jagielski return $error; 197*b1cdbd2cSJim Jagielski } 198*b1cdbd2cSJim Jagielski # in a master build it is considered an error to have deliver leftovers 199*b1cdbd2cSJim Jagielski # from non exising (removed) modules 200*b1cdbd2cSJim Jagielski print_logged( "Error: module '$module' not found.\n" ); 201*b1cdbd2cSJim Jagielski $error++; 202*b1cdbd2cSJim Jagielski return $error; 203*b1cdbd2cSJim Jagielski } 204*b1cdbd2cSJim Jagielski if ( $canread == 2 ) { 205*b1cdbd2cSJim Jagielski # module is linked and not built, no need for checking 206*b1cdbd2cSJim Jagielski # should not happen any more nowadays ... 207*b1cdbd2cSJim Jagielski return $error; 208*b1cdbd2cSJim Jagielski } 209*b1cdbd2cSJim Jagielski 210*b1cdbd2cSJim Jagielski # compare all delivered files with their origin 211*b1cdbd2cSJim Jagielski # no strict 'diff' allowed here, as deliver may alter files (hedabu, strip, ...) 212*b1cdbd2cSJim Jagielski foreach my $file ( sort keys %delivered ) { 213*b1cdbd2cSJim Jagielski my $ofile = "$srcrootdir/$file"; 214*b1cdbd2cSJim Jagielski my $sfile = "$solverdir/$delivered{$file}"; 215*b1cdbd2cSJim Jagielski if ( $milestoneext ) { 216*b1cdbd2cSJim Jagielski # deliver log files do not contain milestone extension on solver 217*b1cdbd2cSJim Jagielski $sfile =~ s/\/$platform\/(...)\//\/$platform\/$1$milestoneext\//; 218*b1cdbd2cSJim Jagielski } 219*b1cdbd2cSJim Jagielski my $orgfile_stats = stat($ofile); 220*b1cdbd2cSJim Jagielski next if ( -d _ ); # compare files, not directories 221*b1cdbd2cSJim Jagielski my $delivered_stats = lstat($sfile); 222*b1cdbd2cSJim Jagielski next if ( -d _ ); # compare files, not directories 223*b1cdbd2cSJim Jagielski if ( $^O !~ /^MSWin/ ) { 224*b1cdbd2cSJim Jagielski # windows does not know about links. 225*b1cdbd2cSJim Jagielski # Therefore lstat() is not a lstat, and the following check would break 226*b1cdbd2cSJim Jagielski next if ( -l _ ); # compare files, not links 227*b1cdbd2cSJim Jagielski } 228*b1cdbd2cSJim Jagielski 229*b1cdbd2cSJim Jagielski if ( $orgfile_stats && $delivered_stats ) { 230*b1cdbd2cSJim Jagielski # Stripping (on unix like platforms) and signing (for windows) 231*b1cdbd2cSJim Jagielski # changes file size. Therefore we have to compare for file dates. 232*b1cdbd2cSJim Jagielski # File modification time also can change after deliver, f.e. by 233*b1cdbd2cSJim Jagielski # rebasing, but only increase. It must not happen that a file on 234*b1cdbd2cSJim Jagielski # solver is older than it's source. 235*b1cdbd2cSJim Jagielski if ( ( $orgfile_stats->mtime - $delivered_stats->mtime ) gt 1 ) { 236*b1cdbd2cSJim Jagielski print_logged( "Error: " ); 237*b1cdbd2cSJim Jagielski print_logged( "delivered file is older than it's source '$ofile' '$sfile'\n" ); 238*b1cdbd2cSJim Jagielski $error ++; 239*b1cdbd2cSJim Jagielski } 240*b1cdbd2cSJim Jagielski } elsif ( !$orgfile_stats && $delivered_stats ) { 241*b1cdbd2cSJim Jagielski # This is not an error if we have a solver and did not build the 242*b1cdbd2cSJim Jagielski # module! 243*b1cdbd2cSJim Jagielski } elsif ( !$orgfile_stats && !$delivered_stats ) { 244*b1cdbd2cSJim Jagielski # This is not necessarily an error. 245*b1cdbd2cSJim Jagielski # Instead, this seems to be an error of the deliver.log file. 246*b1cdbd2cSJim Jagielski } else { 247*b1cdbd2cSJim Jagielski print_logged( "Error: no such file '$ofile'\n" ) if ( ! $orgfile_stats ); 248*b1cdbd2cSJim Jagielski print_logged( "Error: no such file '$sfile'\n" ) if ( ! $delivered_stats ); 249*b1cdbd2cSJim Jagielski $error ++; 250*b1cdbd2cSJim Jagielski } 251*b1cdbd2cSJim Jagielski } 252*b1cdbd2cSJim Jagielski if ( $error ) { 253*b1cdbd2cSJim Jagielski print_logged( "$error errors found: Module '$module' not delivered correctly?\n\n" ); 254*b1cdbd2cSJim Jagielski } 255*b1cdbd2cSJim Jagielski STDOUT->autoflush(0); 256*b1cdbd2cSJim Jagielski return $error; 257*b1cdbd2cSJim Jagielski} 258*b1cdbd2cSJim Jagielski 259*b1cdbd2cSJim Jagielskisub is_moduledirectory 260*b1cdbd2cSJim Jagielski# Test whether we find a module having a d.lst file at a given path. 261*b1cdbd2cSJim Jagielski# Return value: 1: path is valid directory 262*b1cdbd2cSJim Jagielski# 2: path.link is a valid link 263*b1cdbd2cSJim Jagielski# 0: module not found 264*b1cdbd2cSJim Jagielski{ 265*b1cdbd2cSJim Jagielski my $dirname = shift; 266*b1cdbd2cSJim Jagielski if ( -e "$dirname/prj/d.lst" ) { 267*b1cdbd2cSJim Jagielski return 1; 268*b1cdbd2cSJim Jagielski } elsif ( -e "$dirname.link/prj/d.lst" ) { 269*b1cdbd2cSJim Jagielski return 2 270*b1cdbd2cSJim Jagielski } else { 271*b1cdbd2cSJim Jagielski return 0; 272*b1cdbd2cSJim Jagielski } 273*b1cdbd2cSJim Jagielski} 274*b1cdbd2cSJim Jagielski 275*b1cdbd2cSJim Jagielskisub print_logged 276*b1cdbd2cSJim Jagielski# Print routine. 277*b1cdbd2cSJim Jagielski# If a log file name is specified with '-l' option, print_logged() prints to that file 278*b1cdbd2cSJim Jagielski# as well as to STDOUT. If '-l' option is not set, print_logged() just writes to STDOUT 279*b1cdbd2cSJim Jagielski{ 280*b1cdbd2cSJim Jagielski my $message = shift; 281*b1cdbd2cSJim Jagielski print "$message"; 282*b1cdbd2cSJim Jagielski if ( $logfile ) { 283*b1cdbd2cSJim Jagielski open ( LOGFILE, ">> $logfile" ) or die "Can't open logfile '$logfile'\n"; 284*b1cdbd2cSJim Jagielski print LOGFILE "$message"; 285*b1cdbd2cSJim Jagielski close ( LOGFILE) ; 286*b1cdbd2cSJim Jagielski } 287*b1cdbd2cSJim Jagielski} 288*b1cdbd2cSJim Jagielski 289*b1cdbd2cSJim Jagielski 290*b1cdbd2cSJim Jagielskisub usage 291*b1cdbd2cSJim Jagielski# print usage message and exit 292*b1cdbd2cSJim Jagielski{ 293*b1cdbd2cSJim Jagielski my $retval = shift; 294*b1cdbd2cSJim Jagielski print STDERR "Usage: checkdeliver.pl [-h] [-p <platform>]\n"; 295*b1cdbd2cSJim Jagielski print STDERR "Compares delivered files on solver with original ones in build tree\n"; 296*b1cdbd2cSJim Jagielski print STDERR "Options:\n"; 297*b1cdbd2cSJim Jagielski print STDERR " -h print this usage message\n"; 298*b1cdbd2cSJim Jagielski print STDERR " -p platform specify platform\n"; 299*b1cdbd2cSJim Jagielski 300*b1cdbd2cSJim Jagielski exit $retval; 301*b1cdbd2cSJim Jagielski} 302*b1cdbd2cSJim Jagielski 303