Generated: Sun Aug 21 11:10:48 2011 from cvsversion.pl 2010/12/10 16.8 KB.
#!/usr/bin/perl -w # NAME: cvsversion.pl # AIM: To examine an input directory, seeking CVS folders and files, # and reporting when the last update was done. # 10/12/2010 - Review - remove no warnings message... # 2010/02/14 - add -v[n] to report more. N is size of time list stack, # and added -xf <file>, and -xd <dir> to EXCLUDE these items (CaSe sensitive!) # 10/11/2009 - Some further tidying, and move recursive directory to end of function # Add prtw(), and show_warnings() # 09/11/2009 - Added bytes-to-ks for $total_bytes, and get LOCAL directory sizes # 31/10/2009 - But it reported the latest FILE, but want the latest CVS file # 15/08/2007 - geoff mclane - geoffair.net/mperl use strict; use warnings; use File::stat; # to get the file date use File::Basename; use Time::gmtime; ### prt( "$0 ... Hello, World ...\n" ); my $in_folder = 'C:/FGCVS/xmlrpc-c'; ###my $in_folder = 'C:/FGCVS/Tidy'; my @fnd_files = (); my @fnd_cvs = (); my %cvs_names = (); my @local_totals = (); my ($fcnt, $ccnt, $msg); my $mxlen = 0; my $mxsiz = 0; my $szlen = 0; my $latest = 0; my $largest = 0; my $most_recent = 0; my $recent_file = ''; my $cvs_latest = 0; my $cvs_file = ''; my $total_files = 0; my $total_bytes = 0; my $total_dirs = 0; my $total_all = 0; # options my $exclude_built = 1; my $verbosity = 1; my @excluded_ext = qw( .old .bak .obj .err .pdb .lst .pch .ilk .ncb .plg .OPT .idb .aps .sbr .suo .bsc .manifest .user .res .zip .exe .lib .dll .exp ); my @excluded_vc = qw( .dsw .dsp .sln .vcproj ); my @exclude_others = qw( temp*.* mt.dep Buildlog.htm ); my @user_exclude = (); my @excluded_dirs = (); my %exclude_shown = (); my @warnings = (); # debug my $dbg1 = 0; # show processing folders ... my $dbg2 = 0; # show CVS/SVN file entries my $dbg3 = 0; # show CVS/SVN file types sub prt($) { my ($m) = shift; print $m; } sub mydie($) { my ($m) = shift; die $m; } sub prtw($) { my ($msg) = @_; prt($msg); $msg =~ s/\n$//; push(@warnings,$msg); } sub show_warnings() { if (@warnings) { prt( "Got ".scalar @warnings." WARNINGS...\n" ); foreach my $msg (@warnings) { prt( "$msg\n" ); } } else { # prt( "No warnings issued.\n" ); } } sub pgm_exit($$) { my ($val,$msg) = @_; show_warnings(); if (length($msg)) { $msg .= "\n" if ( !($msg =~ /\n$/) ); prt($msg); } exit($val); } sub get_YYYYMMDD_hhmmss_UTC($) { my ($t) = shift; # sec, min, hour, mday, mon, year, wday, yday, and isdst. my $tm = gmtime($t); my $m = sprintf( "%04d/%02d/%02d %02d:%02d:%02d", $tm->year() + 1900, $tm->mon() + 1, $tm->mday(), $tm->hour(), $tm->min(), $tm->sec()); return $m; } sub get_YYYYMMDD_UTC($) { my ($t) = shift; # sec, min, hour, mday, mon, year, wday, yday, and isdst. my $tm = gmtime($t); my $m = sprintf( "%04d/%02d/%02d", $tm->year() + 1900, $tm->mon() + 1, $tm->mday()); return $m; } sub mycmp_ascend_n2 { # push(@fnd_files, [$ff, $sb->mtime, $sb->size, $lev] ); return 1 if (${$a}[1] < ${$b}[1]); return -1 if (${$a}[1] > ${$b}[1]); return 0; } sub in_excluded_vc($) { my ($lcext) = shift; foreach my $ext (@excluded_vc) { if ($lcext eq $ext) { return 1; } } return 0; } sub in_excluded_ext($) { my ($lcext) = shift; foreach my $ext (@excluded_ext) { if ($lcext eq $ext) { return 1; } } return 0; } sub in_excluded_user($) { my ($tf) = shift; foreach my $fil (@user_exclude) { return 1 if ($tf eq $fil); } return 0; } sub in_excluded_dirs($) { my ($tf) = shift; foreach my $fil (@excluded_dirs) { return 1 if ($tf eq $fil); } return 0; } sub in_excluded($) { my ($lcext) = shift; return 1 if in_excluded_ext($lcext); return 1 if in_excluded_vc($lcext); return 0; } sub is_an_excluded_file($) { my ($ff) = shift; my ($nam,$dir,$ext) = fileparse($ff, qr/\.[^.]*/ ); return 1 if in_excluded(lc($ext)); my $name = $nam . $ext; return 1 if ($name =~ /^temp/i); return 1 if (lc($name) eq 'mt.dep'); return 1 if (lc($name) eq 'buildlog.htm' ); return 1 if in_excluded_user($name); return 1 if ($name =~ /^generate\.stamp/i); return 0; } sub dos_2_unix($) { my ($du) = shift; $du =~ s/\\/\//g; return $du; } ################################################## # My particular 'nice number' sub get_nn($) { # perl nice number nicenum add commas my ($n) = shift; if (length($n) > 3) { my $mod = length($n) % 3; my $ret = (($mod > 0) ? substr( $n, 0, $mod ) : ''); my $mx = int( length($n) / 3 ); for (my $i = 0; $i < $mx; $i++ ) { if (($mod == 0) && ($i == 0)) { $ret .= substr( $n, ($mod+(3*$i)), 3 ); } else { $ret .= ',' . substr( $n, ($mod+(3*$i)), 3 ); } } return $ret; } return $n; } sub show_per_time_list() { if ($verbosity > 1) { # more output my (@per_time,$i,$ff,$tm,$sz,$sf,$nm,$dir,$dt,$csz,$min1,$min2,$len,$max,$cnt); my @arr = (); $max = scalar @fnd_files; prt("Display of the latest $verbosity files, of $max...\n"); @per_time = sort mycmp_ascend_n2 @fnd_files; $min1 = 0; $min2 = 0; $cnt = 0; for ($i = 0; $i < $max; $i++) { $ff = $per_time[$i][0]; next if ($exclude_built && is_an_excluded_file($ff)); $cnt++; last if ($cnt > $verbosity); $tm = $per_time[$i][1]; $sz = $per_time[$i][2]; $sf = substr($ff, (length($in_folder) + 1)); ($nm, $dir) = fileparse( $sf ); # $dt = get_YYYYMMDD_UTC($tm); $csz = get_nn($sz); $len = length($nm); $min1 = $len if ($len > $min1); $len = length($csz); $min2 = $len if ($len > $min2); push(@arr, [$ff,$tm,$sz]); # store entry } $max = scalar @arr; for ($i = 0; $i < $max; $i++) { $ff = $arr[$i][0]; $tm = $arr[$i][1]; $sz = $arr[$i][2]; $sf = substr($ff, (length($in_folder) + 1)); ($nm, $dir) = fileparse( $sf ); $dt = get_YYYYMMDD_hhmmss_UTC($tm); $csz = get_nn($sz); $nm .= ' ' while (length($nm) < $min1); $csz = " $csz" while (length($csz) < $min2); prt("$dt: $nm $csz, in $dir\n"); } } } sub b2ks2($) { my ($d) = @_; my $oss; my $kss; my $lg = 0; my $ks = ($d / 1024); #// get Ks my $div = 1; if( $ks < 1024 ) { $div = 1; $oss = "KB"; } elsif ( $ks < (1024*1024) ) { $div = 1024; $oss = "MB"; } elsif ( $ks < (1024*1024*1024) ) { $div = 1024 * 1024; $oss = "GB"; } else { $div = 1024 * 1204 * 1240; $oss = "TB"; } $kss = $ks / $div; $kss += 0.05; $kss *= 10; $lg = int($kss); $kss = $lg / 10; $kss .= '.0' if (!($kss =~ /\./)); ###return( ($lg / 10) . " " . $oss ); return "$kss$oss"; } # 0 1 2 # push(@local_totals, [ $inf, $loc_tsize, $loc_tcnt ]); # keep totals in THIS folder sub show_per_folder() { my $max = scalar @local_totals; my ($i,$siz,$cnt,$msize,$mcnt,$mso,$msc,$dirs,$dirc); $msize = 0; $mcnt = 0; $mso = 0; $msc = 0; for ($i = 0; $i < $max; $i++) { #$dir = $local_totals[$i][0]; $siz = $local_totals[$i][1]; $cnt = $local_totals[$i][2]; if ($siz > $msize) { $msize = $siz; $mso = $i; } if ($cnt > $mcnt) { $mcnt = $cnt; $msc = $i; } } $dirs = $local_totals[$mso][0]; $siz = $local_totals[$mso][1]; $dirc = $local_totals[$msc][0]; $cnt = $local_totals[$msc][2]; if ($mso == $msc) { prt("$max searched, [$dirs] was largest $siz, and most $cnt. ($mso)\n"); } else { prt("$max searched, largest $siz was [$dirs]($mso), most $cnt was [$dirc]($msc).\n"); } } parse_args(@ARGV); prt( "Processing $in_folder ...\n" ) if ($dbg1); process_dir( $in_folder, 0 ); $fcnt = scalar @fnd_files; $ccnt = scalar @fnd_cvs; prt( "Found $fcnt files, $ccnt in CVS/SVN folders ...\n" ); my $alfildate = show_latest_file(); for (my $i = 0; $i < $ccnt; $i++) { my $ff = $fnd_cvs[$i][0]; my $sz = $fnd_cvs[$i][2]; my $sf = substr($ff, (length($in_folder) + 1)); my $len = length($sf); if ($len > $mxlen) { $mxlen = $len; } if ($sz > $mxsiz) { $mxsiz = $sz; } } $msg = get_nn($mxsiz); $szlen = length($msg) + 1; for (my $i = 0; $i < $ccnt; $i++) { my $ff = $fnd_cvs[$i][0]; my $tm = $fnd_cvs[$i][1]; my $sz = $fnd_cvs[$i][2]; my $sf = substr($ff, (length($in_folder) + 1)); ###my ($nm, $dir, $ext) = fileparse( $sf, qr/\.[^.]*/ ); my ($nm, $dir) = fileparse( $sf ); if (defined $cvs_names{$nm}) { $cvs_names{$nm}++; } else { $cvs_names{$nm} = 1; } if ($sz > $largest) { $largest = $sz; } my $nsz = get_nn($sz); while(length($nsz) < $szlen) { $nsz = ' ' . $nsz; } $msg = $sf; while(length($msg) < $mxlen) { $msg .= ' '; } if ($tm > $latest) { $latest = $tm; } if ($tm > $cvs_latest) { $cvs_latest = $tm; $cvs_file = $ff; } prt( "$msg ". localtime($tm). " $nsz\n" ) if ($dbg2); } foreach my $key (keys %cvs_names) { my $val = $cvs_names{$key}; prt( "$key $val\n" ) if ($dbg3); } my $nsz = get_nn($largest); while(length($nsz) < $szlen) { $nsz = ' ' . $nsz; } $msg = "Latest (largest)"; ##while(length($msg) < $mxlen) { ## $msg .= ' '; ##} ##prt( "$msg ". localtime($latest). " $nsz\n" ); if ($latest) { prt( "$msg ". get_YYYYMMDD_hhmmss_UTC($latest) . " $nsz\n" ); prt( "FILES: ".get_YYYYMMDD_UTC($latest) ); } else { prt( "$msg NO LATEST CVS/SVN TIME $nsz\n" ); prt( "NO CVS/SVN FILES" ); } prt( ", FILE: $alfildate" ); if ($most_recent > 0) { prt( ", MOST RECENT: ".get_YYYYMMDD_UTC($most_recent). " $recent_file" ); } prt("\n"); show_per_folder(); $msg = ($cvs_latest ? get_YYYYMMDD_UTC($cvs_latest) : ''); prt("DIR: [$in_folder] $msg, files $total_files, bytes ".get_nn($total_bytes)." (".b2ks2($total_bytes).")"); prt(", dirs $total_dirs(".($total_all - $total_files).")\n"); if ($cvs_latest) { prt( "CVS: latest: ".get_YYYYMMDD_UTC($cvs_latest)." ($cvs_file)\n" ); } show_per_time_list(); pgm_exit(0,""); ########################## ##### subs sub show_latest_file { my $max = scalar @fnd_files; my ($i, $ff, $tm, $sz, $fn); my ($nam, $dir, $ext, $name); my $lasttime = 0; my $lastfile = ''; my $lastsize = 0; my $rmsg = ''; for ($i = 0; $i < $max; $i++) { $ff = $fnd_files[$i][0]; $tm = $fnd_files[$i][1]; $sz = $fnd_files[$i][2]; $fn = substr($ff, (length($in_folder) + 1)); if ($tm > $most_recent) { $most_recent = $tm; $recent_file = $fn; } if ($exclude_built) { ($nam,$dir,$ext) = fileparse($ff, qr/\.[^.]*/ ); next if in_excluded(lc($ext)); $name = $nam . $ext; next if ($name =~ /^temp/i); next if (lc($name) eq 'mt.dep'); next if (lc($name) eq 'buildlog.htm' ); } if ($tm > $lasttime) { $lasttime = $tm; $lastfile = $fn; $lastsize = $sz; } } if ($lasttime) { $rmsg = get_YYYYMMDD_UTC($lasttime). " $lastfile"; prt( "Latest file [$lastfile], [". get_YYYYMMDD_hhmmss_UTC($lasttime) ."], size ".get_nn($lastsize)."\n" ); } else { $rmsg = "None found!"; prt( "No latest file found!???\n" ); } return $rmsg; } sub is_in_respository_folder($) { my ($f) = shift; if ($f =~ /(\/|\\)CVS(\/|\\)/i) { return 1; } elsif ($f =~ /(\/|\\)\.svn(\/|\\)/i) { return 1; } elsif ($f =~ /(\/|\\)\.git(\/|\\)/i) { return 1; } return 0; } sub process_dir { my ($inf, $lev) = @_; prt( "$lev: Processing $inf folder ...\n" ) if ($dbg1); my @dirs = (); my ($sb,$ff); if ( opendir( DIR, $inf ) ) { my @files = readdir(DIR); closedir DIR; my $loc_tsize = 0; my $loc_tcnt = 0; my $loc_tdirs = 0; foreach my $fl (@files) { $total_all++; next if (($fl eq '.') || ($fl eq '..')); $ff = $inf . "/" . $fl; if (-d $ff) { $total_dirs++; $loc_tdirs++; # process_dir( $ff, ($lev + 1) ); # process this sub-directory if (in_excluded_dirs($fl)) { if (! defined $exclude_shown{$fl}) { prtw( "Excluding directory [$fl]\n"); $exclude_shown{$fl} = 1; } } else { #prt( "Including directory [$fl]\n"); push(@dirs,$ff); } } else { if( $sb = stat($ff) ) { $total_files++; $total_bytes += $sb->size; # local stats $loc_tsize += $sb->size; $loc_tcnt++; if ( is_in_respository_folder($ff) ) { # file is in a CVS, .git or .svn folder push(@fnd_cvs, [$ff, $sb->mtime, $sb->size, $lev] ); } else { push(@fnd_files, [$ff, $sb->mtime, $sb->size, $lev] ); } } else { prtw("WARNING: stat FAILED on [$ff]!\n"); } } } push(@local_totals, [ $inf, $loc_tsize, $loc_tcnt, $loc_tdirs ]); # keep totals in THIS folder # now process any DIRECTORIES found, NOT in @excluded_dirs... foreach $ff (@dirs) { process_dir( $ff, ($lev + 1) ); # process this sub-directory } } else { prtw( "WARNING: Can NOT open $inf ... $! ...\n" ); } } sub give_help { prt( "$0 [OPTIONS] in_folder\n" ); prt( "OPTIONS:\n" ); prt( " -? or -h - This brief help.\n" ); prt( " -d1 - show processing folders.\n" ); prt( " -d2 - show CVS/SVN file entries.\n" ); prt( " -d3 - show CVS/SVN file types.\n" ); prt( " -v[N} - Increase verbosity. That is depth of times shown. Default is 1 = just latest\n"); prt( " -xf file - Exclude this file name.\n"); prt( " -xd dir - Exclude this directory from search"); mydie("In folder must exist ...\n"); } sub check_nxt { my ($a,@v) = @_; mydir("ERROR: Argument [$a] MUST be followed by another argment to give the value! Aborting...") if (!@v); } sub parse_args { # @ARGV my (@av) = @_; my ($dn, @tv, $vb); while (@av) { my $arg = $av[0]; if (substr($arg,0,1) eq '-') { if (($arg eq '-?')||($arg eq '-h')) { give_help(); } elsif ($arg eq '-d1') { $dbg1 = 1; prt( "Show folder processing ...\n" ); } elsif ($arg eq '-d2') { $dbg2 = 1; prt( "Show CVS/SVN file entries ...\n" ); } elsif ($arg eq '-d3') { $dbg3 = 1; prt( "Show CVS/SVN file types ...\n" ); } elsif ($arg =~ /^-v(.*)/) { # verbosity $vb = $1; if (defined $vb && length($vb)) { if ($vb =~ /^\d+$/) { $verbosity = $vb; } else { mydie( "ERROR: Unknown option [$arg] -v can only be followed by a number... aborting ...\n" ); } } else { $verbosity++; } prt("Verbosity set to [$verbosity], per [$arg]\n"); } elsif ($arg =~ /^-d(\d+)/) { $dn = $1; @tv = (); push(@tv,'-d3') if ($dn >= 3); push(@tv,'-d2') if ($dn >= 2); push(@tv,'-d1') if ($dn >= 1); parse_args(@tv) if (@tv); } elsif ($arg eq '-xf') { check_nxt(@av); shift @av; $arg = $av[0]; push(@user_exclude,$arg); prt("Added [$arg] to user file excludes.\n"); } elsif ($arg eq '-xd') { check_nxt(@av); shift @av; $arg = $av[0]; push(@excluded_dirs,$arg); prt("Added [$arg] to excluded directories.\n"); } else { mydie( "ERROR: Unknown option [$arg] ... aborting ...\n" ); } } else { # bare item - assume INPUT folder $in_folder = dos_2_unix($arg); prt( "Set in folder to $in_folder ...\n" ); } shift @av; } } # eof - cvsversion.pl