#!/perl -w # NAME: cleandiff02.pl # AIM: To remove some things from an input diff file ... # 1 - remove Only in blah blah ... # 2 - remove diff of .dsw, .dsp, .sln, .vcproj files ... # and write results to an output file # 01/02/2015 - Add -i input.txt, similar to -@input.txt # 02/12/2013 - Add -x *.html;*.sip list of wild card excludes # 22/09/2013 - Add a -KO to add ALL 'Only in ...' lines # 05/09/2013 - Modify -ko options to NOT show .git folder items, and order the list # 11/02/2013 - Default output changed to tempclean.diff # 28/03/2012 - Add .vcxproj to excluded list # 23/03/2012 - Add -u to convert paths to unix path speparator # 05/01/2012 - Added special -x _cmake_, and excluded file '.gitignore' # 10/12/2011 - If VERB, output a changed file list # 17/11/2011 - Add -o , to set the OUTPUT of the cleaned diff # 29/06/2011 - Add -x , to exclude a specific 'file' from the diff # 26/05/2011 - Improve UI use strict; use warnings; use File::Basename; # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] ) use Cwd; my $perl_dir = 'C:\GTools\perl'; unshift(@INC, $perl_dir); require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl'!\n"; # log file stuff our ($LF); my $pgmname = $0; if ($pgmname =~ /(\\|\/)/) { my @tmpsp = split(/(\\|\/)/,$pgmname); $pgmname = $tmpsp[-1]; } my $outfile = $perl_dir."\\temp.$pgmname.txt"; open_log($outfile); my $VERS = "1.0.5 2013-09-22"; # features my $load_log = 0; # load log file at end my $keep_only_in = 0; my $KEEP_ONLY_IN = 0; my $keep_bin_files = 0; my $unix_pat_sep = 0; my $include_msvc = 0; # program variables my $in_file = ''; my $out_file = $perl_dir.'\tempclean.diff'; my @user_xcludes = (); my @xclude_dirs = (); my $verbosity = 0; my $in_input_file = 0; my $show_copy_list = 0; my $output_file = ''; my $add_skipped_lines = 0; my $common_destination = ''; # from $fil2 my $common_source = ''; # from $fil1 my @changed_files = (); my @excluded_files = (); my @new_files = (); # that is '@@ -0,0 +n,n @@' COUNT LINE my @excluded_new_files = (); # likewise NEW, but excluded my @cmake_xcludes = qw( CMakeLists.txt *.cmake ); sub VERB1() { return ($verbosity >= 1); } sub VERB2() { return ($verbosity >= 2); } sub VERB5() { return ($verbosity >= 5); } sub VERB9() { return ($verbosity >= 9); } sub get_common_dir($$) { my ($file,$rdir) = @_; my $len1 = length($file); return 0 if ($len1 == 0); my $dir2 = ${$rdir}; my $len2 = length($dir2); my ($name,$dir1) = fileparse($file); return 0 if ($dir1 =~ /^\.(\\|\/)$/); $len1 = length($dir1); if ($len2 == 0) { ${$rdir} = $dir1; # set first common directory return 1; } # else keep only the COMMON part of $dir2 given in $dir1 my $len = ($len2 < $len1) ? $len2 : $len1; # get shortest my ($i,$ch1,$ch2); for ($i = 0; $i < $len; $i++) { $ch1 = substr($dir1,$i,1); $ch2 = substr($dir2,$i,1); last if ($ch1 ne $ch2); } if ($i < $len2) { $dir2 = substr($dir2,0,$i); ${$rdir} = $dir2; } return 1; } sub get_common_dst($) { my $fil = shift; get_common_dir($fil,\$common_destination); } sub get_common_src($) { my $fil = shift; get_common_dir($fil,\$common_source); } my $dbg_mww = 0; sub match_with_wild($$) { my ($fil1,$fil2) = @_; my $len1 = length($fil1); my $len2 = length($fil2); prt("match_with_wild: [$fil1] [$fil2] ") if ($dbg_mww); my ($i,$j,$c1,$c2); $i = 0; $j = 0; if (($len1 > 0) && ($len2 > 0)) { while (($i < $len1)&&($j < $len2)) { $c1 = substr($fil1,$i,1); $c2 = substr($fil2,$j,1); if (($c1 eq $c2)||($c1 eq '?')||($c2 eq '?')) { $i++; $j++; prt("$c1= ") if ($dbg_mww); } elsif ($c2 eq '*') { $i++; # any $c1 matches asterick if (($j + 1) < $len2) { # but if more, maybe time to step past '*' $c2 = substr($fil2,($j+1),1); if ($c1 eq $c2) { $j += 2; } } prt("$c1* ") if ($dbg_mww); } elsif ($c1 eq '*') { $j++; # any $c2 matches asterick if (($i + 1) < $len1) { # but if more, maybe time to step past '*' $c1 = substr($fil1,($i+1),1); if ($c1 eq $c2) { $i += 2; } } prt("$c2* ") if ($dbg_mww); } else { prt(" = 0 - [$c1] ne [$c2]\n") if ($dbg_mww); return 0; } } if (($i == $len1)&&($j == $len2)) { prt(" = 1 - both ran out of chars\n") if ($dbg_mww); return 1; # both ran out of chars } elsif (($i == $len1)&&($c2 eq '*')&&(($j + 1) == $len2)){ prt(" = 1 - first ran out and last is second $c2\n") if ($dbg_mww); return 1; # first ran out, and second is last '*' } elsif (($j == $len2)&&($c1 eq '*')&&(($i + 1) == $len1)){ prt(" = 1 - second ran out and last of first is $c1\n") if ($dbg_mww); return 1; # second ran out, and second is last '*' } prt(" = 0 - failed - no case\n") if ($dbg_mww); } elsif ($len1 > 0) { # 2nd is nul if ($fil1 eq '*') { prt(" = 1 - asterix matches nul\n") if ($dbg_mww); return 1; # nul matches asterix } prt(" = 0 - len1 > 0, but [$fil1]\n") if ($dbg_mww); } elsif ($len2 > 0) { # 1st is nul if ($fil2 eq '*') { prt(" = 1 - nul match asterix\n") if ($dbg_mww); return 1; # nul matches asterix } prt(" = 0 - len2 > 0, but [$fil1]\n") if ($dbg_mww); } else { prt(" = 0 - no case\n") if ($dbg_mww); } return 0; } sub matches_wild($$) { my ($fil,$wild) = @_; my ($n1,$d1,$e1) = fileparse( $fil, qr/\.[^.]*/ ); my ($n2,$d2,$e2) = fileparse( $wild, qr/\.[^.]*/ ); my $lcn1 = lc($n1); my $lcn2 = lc($n2); # strip . from extension $e1 =~ s/^\.//; $e2 =~ s/^\.//; my $lce1 = lc($e1); my $lce2 = lc($e2); prt("[v9] matches_wild: [$n1] [$n2] and [$e1] [$e2]\n") if (VERB9()); return 1 if (($lcn1 eq $lcn2)&&($lce1 eq $lce2)); return 2 if (($lcn1 eq $lcn2)&&($lce2 eq '*')); return 3 if (($lcn2 eq '*')&&($lce1 eq $lce2)); return 4 if (match_with_wild($lcn1,$lcn2) && match_with_wild($lce1,$lce2)); return 0; } sub has_wild($) { my $txt = shift; my $len = length($txt); my ($i,$c); for ($i = 0; $i < $len; $i++) { $c = substr($txt,$i,1); if (($c eq '?')||($c eq '*')) { return 1; } } return 0; } sub in_user_excludes($) { my ($fil) = shift; my ($nam,$dir) = fileparse($fil); my ($item); my $hw = has_wild($fil); foreach $item (@user_xcludes) { return 1 if ($nam eq $item); if ($hw || has_wild($item)) { return 2 if (matches_wild($item,$nam)); } } return 0; } sub in_dir_excludes($) { my ($tx) = @_; my ($dir); foreach $dir (@xclude_dirs) { if ($tx =~ /(\\|\/)$dir(\\|\/)/) { return 1; } } return 0; } # debug my $dbg_01 = 0; # show every line my @warnings = (); sub prtw($) { my $txt = shift; $txt =~ s/\n$//; prt("$txt\n"); push(@warnings,$txt); } sub show_warnings($) { my ($dbg) = shift; if (@warnings) { prt( "\nGot ".scalar @warnings." WARNINGS ...\n" ); foreach my $line (@warnings) { prt("$line\n" ); } prt("\n"); } elsif ($dbg) { #prt("\nNo warnings issued.\n\n"); } } sub pgm_exit($$) { my ($val,$msg) = @_; show_warnings($val); prt( "$msg" ) if (length($msg)); close_log($outfile,$load_log); exit($val); } sub is_msvc_file($) { my ($tx) = @_; my $val = 0; # exclude MSVC make files $val++; return $val if ($tx =~ /\.dsp$/i); # 1 $val++; return $val if ($tx =~ /\.dsw$/i); $val++; return $val if ($tx =~ /\.sln$/i); $val++; return $val if ($tx =~ /\.vcproj$/i); $val++; return $val if ($tx =~ /\.vcxproj$/i); $val++; return $val if ($tx =~ /\.vcxproj.user$/i); $val++; return $val if ($tx =~ /\.vcxproj.filters$/i); # 6 return 0; } my $repo_dirs = 3; sub is_excluded_file($) { my ($tx) = @_; my $val = 0; # exclude SVN, CVS, git directory items $val++; return $val if ($tx =~ /(\\|\/)\.svn(\\|\/)/); $val++; return $val if ($tx =~ /(\\|\/)CVS(\\|\/)/); $val++; return $val if ($tx =~ /(\\|\/)\.git(\\|\/)/); # exclude MSVC make files, if NOT specifically INCLUDED -m return 0 if ($include_msvc && is_msvc_file($tx)); $val++; return $val if ($tx =~ /\.dsp$/i); # 1 $val++; return $val if ($tx =~ /\.dsw$/i); $val++; return $val if ($tx =~ /\.sln$/i); $val++; return $val if ($tx =~ /\.vcproj$/i); $val++; return $val if ($tx =~ /\.vcxproj$/i); $val++; return $val if ($tx =~ /\.vcxproj.user$/i); $val++; return $val if ($tx =~ /\.vcxproj.filters$/i); # 6 # user file exclude $val++; return $val if (in_user_excludes($tx)); # user directory exclude $val++; return $val if (in_dir_excludes($tx)); $val++; return $val if ($tx =~ /\.gitignore$/); return 0; } sub is_repo_dir($) { my $tx = shift; return 1 if ($tx =~ /(\\|\/)\.git(\\|\/|:)/); # Only in lines can be 'fgcom\.git:...' return 1 if ($tx =~ /(\\|\/)\.svn(\\|\/)/); return 1 if ($tx =~ /(\\|\/)CVS(\\|\/)/); return 0; } sub get_diff_files($$$) { my ($lin,$rfil1,$rfil2) = @_; #my @arr = split(/s+/,$lin); my @arr = space_split($lin); if (scalar @arr < 2) { pgm_exit(1,"ERROR: Line [$lin] did NOT split correctly!\n"); } my ($fil,$cnt); $cnt = 0; foreach $fil (@arr) { next if ($fil =~ /^-/); if ($cnt == 0) { ${$rfil1} = $fil; $cnt++; } elsif ($cnt == 1) { ${$rfil2} = $fil; $cnt++; } } return $cnt; } # get_counts($lcnts,\$off1,\$len1,\$off2,\$len2); # Normally @@ -57,10 +57,16 # Also must resolve @@ -1 +1 @@ and @@ -0,0 +1 @@ # UGH and '-1 +0,0', '-1,2 +1', '-1 +0,0' sub get_counts($$$$$) { my ($lcnts,$roff1,$rlen1,$roff2,$rlen2) = @_; ${$roff1} = -9999; ${$rlen1} = -9999; ${$roff2} = -9999; ${$rlen2} = -9999; my ($cnt,$old,$new,$msg,$i); my @arr = split(/\s+/,$lcnts); $cnt = scalar @arr; if ($cnt != 2) { $msg = "WARNING: CNTS [$lcnts] did NOT split in 2 on space! Got $cnt?"; for ($i = 0; $i < $cnt; $i++) { $msg .= " $arr[$i]"; } prtw("$msg\n"); return 1; } $old = $arr[0]; $new = $arr[1]; if ( !($old =~ /^-/) || !($new =~ /^\+/)) { prtw("WARNING: CNTS [$lcnts] did NOT resolve with - or + [$old] [$new]!\n"); return 2; } $old = substr($old,1); @arr = split(",",$old); $cnt = scalar @arr; if ($cnt == 1) { ${$roff1} = $arr[0]; ${$rlen1} = $arr[0]; } elsif ($cnt == 2) { ${$roff1} = $arr[0]; ${$rlen1} = $arr[1]; } else { prtw("WARNING: CNTS [$lcnts] OLD did NOT resolve [$old] [$new]!\n"); return 3; } $new = substr($new,1); @arr = split(",",$new); $cnt = scalar @arr; if ($cnt == 1) { ${$roff2} = $arr[0]; ${$rlen2} = $arr[0]; } elsif ($cnt == 2) { ${$roff2} = $arr[0]; ${$rlen2} = $arr[1]; } else { prtw("WARNING: CNTS [$lcnts] OLD did NOT resolve [$old] [$new]!\n"); return 4; } return 0; } sub process_file($) { my ($fil) = @_; my (@lines, $line, $lncnt, $i, $txt, $lnnum); my @nlines = (); my @only = (); my @bins = (); my @skipped = (); my %dupes = (); my $newlns = 0; my ($res,$proj,$fil1,$fil2,$sline,$cnt); my ($name,$dir); my ($tmp,$lcnts,$extra,$off1,$len1,$off2,$len2); my ($poff1,$plen1,$poff2,$plen2); $proj = ''; $off1 = $len1 = $off2 = $len2 = 0; $fil1 = ''; $fil2 = ''; if (open INF, "<$fil") { @lines = ; close INF; $lncnt = scalar @lines; prt( "Process $lncnt lines from $fil ...\n" ); $lnnum = 0; for ($i = 0; $i < $lncnt; $i++) { $line = $lines[$i]; chomp $line; $lnnum = $i + 1; prt("$lnnum: [$line]\n") if ($dbg_01); if ($line =~ /^diff\s+.+/) { #if ( $line =~ /^diff\s+(.+)\s+(.+)$/ ) { $sline = $line; $sline =~ s/^diff\s+//; $fil1 = ''; $fil2 = ''; $cnt = get_diff_files($sline,\$fil1,\$fil2); if (($cnt != 2)||(length($fil1)==0)) { prtw("WARNING: get_diff_files:1: FAILED on [$sline] $cnt f1=[$fil1] f2=[$fil2]\n"); } get_common_dst($fil1); get_common_src($fil2); #$res = is_excluded_file($line); $res = is_excluded_file($fil1); push(@excluded_files,[$fil1,$fil2,$res]) if ($res); prt("[v5]$lnnum: $line [$fil1] ($res) 1\n") if (VERB5()); if (length($fil1) && !defined $dupes{$fil1}) { ($name,$dir) = fileparse($fil1); # 0 1 2 3 4 push(@changed_files,[$name,$fil1,$fil2,$res,0]); $dupes{$fil1} = 1; } if ($res) { $i++; # stay here, eating lines, until next NOT excluded item push(@skipped,$line); for (; $i < $lncnt; $i++) { $line = $lines[$i]; chomp $line; $lnnum = $i + 1; if ($line =~ /^diff\s+.+/) { #if ( $line =~ /^diff\s+(.+)\s+(.+)$/ ) { $sline = $line; $sline =~ s/^diff\s+//; $fil1 = ''; $fil2 = ''; $cnt = get_diff_files($sline,\$fil1,\$fil2); if (($cnt != 2)||(length($fil1)==0)) { prtw("WARNING: get_diff_files:2: FAILED on [$sline] $cnt f1=[$fil1] f2=[$fil2]\n"); } get_common_dst($fil1); get_common_src($fil2); #$res = is_excluded_file($line); $res = is_excluded_file($fil1); push(@excluded_files,[$fil1,$fil2,$res]) if ($res); prt("[v5]$lnnum: $line [$fil1] ($res) 2\n") if (VERB5()); if (length($fil1) && !defined $dupes{$fil1}) { ($name,$dir) = fileparse($fil1); # 0 1 2 3 4 push(@changed_files,[$name,$fil1,$fil2,$res,0]); $dupes{$fil1} = 1; } last if ( !$res ); push(@skipped,$line); } elsif ($line =~ /^Only\s+in\s+/) { if ($KEEP_ONLY_IN) { push(@only,$line); # -KO keep ALL 'Only in... lines } elsif ($keep_only_in) { #$res = is_excluded_file($line); #push(@only,$line) if ($res <= $repo_dirs); # EXCLUDE \.git\, \.svn\, etc... lines push(@only,$line) if (!is_repo_dir($line)); # EXCLUDE \.git\, \.svn\, etc... lines } next; } elsif ($line =~ /^\s*Binary\s+files\s+/) { if ($keep_bin_files) { $res = is_excluded_file($line); push(@bins,$line) if ($res <= $repo_dirs); # EXCLUDE \.git\, \.svn\, etc... lines } next; } elsif ($line =~ /^\@\@\s+(.+)\s+\@\@\s*(.*)$/) { $tmp = $1; $extra = $2; # git puts this after the numbers - is actually the next line!!! $lcnts = $tmp; $poff1 = $off1; $plen1 = $len1; $poff2 = $off2; $plen2 = $len2; get_counts($lcnts,\$off1,\$len1,\$off2,\$len2); push(@excluded_new_files,$fil1) if (($off1 == 0)&&($len1 == 0)); } else { push(@skipped,$line); } } last if ($i == $lncnt); } } elsif ($line =~ /^Only\s+in\s+/) { if ($KEEP_ONLY_IN) { push(@only,$line); # -KO keep ALL 'Only in... lines } elsif ($keep_only_in) { #$res = is_excluded_file($line); #push(@only,$line) if ($res <= $repo_dirs); # EXCLUDE \.git\, \.svn\, etc... lines push(@only,$line) if (!is_repo_dir($line)); # EXCLUDE \.git\, \.svn\, etc... lines } next; } elsif ($line =~ /^\s*Binary\s+files\s+/) { if ($keep_bin_files) { $res = is_excluded_file($line); push(@bins,$line) if ($res <= $repo_dirs); # EXCLUDE \.git\, \.svn\, etc... lines } next; } elsif ($line =~ /^\@\@\s+(.+)\s+\@\@\s*(.*)$/) { $tmp = $1; $extra = $2; # git puts this after the numbers - is actually the next line!!! $lcnts = $tmp; $poff1 = $off1; $plen1 = $len1; $poff2 = $off2; $plen2 = $len2; get_counts($lcnts,\$off1,\$len1,\$off2,\$len2); push(@new_files,$fil1) if (($off1 == 0)&&($len1 == 0)); } elsif ($line =~ /^=================(=+)\s(\w+)/) { $proj = $2; if ($keep_only_in || $KEEP_ONLY_IN) { push(@only,$line); } } push(@nlines,$line); $newlns++; } if ($keep_only_in || $KEEP_ONLY_IN) { $cnt = scalar @only; if ($cnt) { push(@nlines, "##################################################"); push(@nlines, "### following $cnt lines added due to -ko option ###"); push(@nlines, "##################################################"); push(@nlines, sort(@only)); push(@nlines, "##################################################"); } } if ($keep_bin_files) { push(@nlines, @bins); } if ($add_skipped_lines) { $cnt = scalar @skipped; if ($cnt) { push(@nlines, "##################################################"); push(@nlines, "### following $cnt lines added due to -a option ###"); push(@nlines, "##################################################"); push(@nlines, @skipped); push(@nlines, "##################################################"); } } } else { prt( "ERROR: Unable to OPEN/READ file $fil ... check name, location...\n" ); } return \@nlines; # return the array reference } sub write_out_lines($$) { my ($rnls,$out) = @_; my $cnt = scalar @{$rnls}; my ($txt); if ($cnt) { $txt = join("\n",@{$rnls}); $txt .= "\n"; write2file($txt,$out); prt("Written $cnt lines to [$out]...\n" ); } else { $txt = "Appears no differences after cleaning\n"; write2file($txt,$out); prt("Blank diffs written to $out\n"); } } sub show_changed_files() { my ($i,$name,$fil1,$fil2,$res,$cnt); my ($msg,$txt,$rescnt,$dst,$src,$ra,$rea,$cres,$added,$removed); my @newlist = (); my ($com_dst,$com_src,$len); my ($ncnt,$nxcnt,$tnew,$dfil,$inew,$outlen,$newcnt,$newxcnt); # my %dupes = (); $outlen = length($output_file); $newcnt = 0; $newxcnt = 0; # if (VERB1()) { # $rea = \@excluded_files; # $cnt = scalar @{$rea}; # #prt("Excluded $cnt files from clean diff.\n") if (VERB9()); # $rescnt = 0; # for ($i = 0; $i < $cnt; $i++) { # $fil1 = ${$rea}[$i][0]; # old - destination # $fil2 = ${$rea}[$i][1]; # new - source # $res = ${$rea}[$i][2]; # reason # if (!defined $dupes{$fil1}) { # $dupes{$fil1} = 1; # $rescnt++; # #$cres = sprintf("%3d:%02d",$rescnt,$res); # #prt("$cres: [$fil1]\n") if (VERB9()); # } # } # } $cnt = scalar @changed_files; $ncnt = scalar @new_files; $nxcnt = scalar @excluded_new_files; $tnew = $ncnt + $nxcnt; $msg = "Original diff contained $cnt changed ($tnew new) files..."; $msg .= " use -v1 to view" if (!VERB1()); prt("$msg\n"); $ra = \@changed_files; # establish the NEW flag # 0 1 2 3 4 # push(@changed_files,[$name,$fil1,$fil2,$res,0]); for ($i = 0; $i < $cnt; $i++) { $fil1 = ${$ra}[$i][1]; # destination $res = ${$ra}[$i][3]; if ($res) { $inew = is_in_array($fil1,@excluded_new_files); } else { $inew = is_in_array($fil1,@new_files); } ${$ra}[$i][4] = $inew; } if ($cnt) { if ($show_copy_list) { $msg = ''; $txt = ''; $rescnt = 0; $dst = ''; $src = ''; $ra = \@changed_files; if (length($common_destination) && length($common_source)) { @newlist = (); $com_dst = $common_destination; $com_src = $common_source; $com_dst =~ s/\\/\\\\/g; $com_src =~ s/\\/\\\\/g; for ($i = 0; $i < $cnt; $i++) { $name = ${$ra}[$i][0]; $fil1 = ${$ra}[$i][1]; # destination $fil2 = ${$ra}[$i][2]; # source $res = ${$ra}[$i][3]; $inew = ${$ra}[$i][4]; $fil1 =~ s/$com_dst//; $fil2 =~ s/$com_src//; push(@newlist,[$name,$fil1,$fil2,$res,$inew]); } $src = "\%SRC\%"; $dst = "\%DST\%"; $ra = \@newlist; $txt .= "\@setlocal\n"; $txt .= "\@set SRC=$common_source\n"; $txt .= "\@set DST=$common_destination\n"; } for ($i = 0; $i < $cnt; $i++) { $name = ${$ra}[$i][0]; $fil1 = ${$ra}[$i][1]; $fil2 = ${$ra}[$i][2]; $res = ${$ra}[$i][3]; $inew = ${$ra}[$i][4]; if ($res) { $rescnt++; } else { if ($inew) { $msg = "copy $src$fil2 $dst$fil1"; prt("$msg\n") if (VERB9() || !$outlen); $txt .= "$msg\n"; } else { $newcnt++; # well actually NOT NEW == OVERWRITE } } } if ($newcnt) { $msg = "\@echo NOTE: Have $newcnt files which will OVERWRITE existing!"; prt("$msg\n"); $txt .= "$msg\n"; $txt .= "\@echo The diff of these files should be reviewed BEFORE doing a COPY!\n"; $txt .= "\@pause\n"; for ($i = 0; $i < $cnt; $i++) { $name = ${$ra}[$i][0]; $fil1 = ${$ra}[$i][1]; $fil2 = ${$ra}[$i][2]; $res = ${$ra}[$i][3]; $inew = ${$ra}[$i][4]; if (!$res && !$inew) { $msg = "copy $src$fil2 $dst$fil1"; prt("$msg\n") if (VERB9() || !$outlen); $txt .= "$msg\n"; } } } if ($rescnt) { $msg = "\@echo NOTE: Have $rescnt files EXCLUDED from diff review file!"; prt("$msg\n"); $txt .= "$msg\n"; $txt .= "\@echo The diff of these files should be reviewed BEFORE doing a COPY!\n"; $txt .= "\@pause\n"; for ($i = 0; $i < $cnt; $i++) { $name = ${$ra}[$i][0]; $fil1 = ${$ra}[$i][1]; $fil2 = ${$ra}[$i][2]; $res = ${$ra}[$i][3]; if ($res) { $msg = "\@echo copy $src$fil2 $dst$fil1"; prt("$msg\n") if (VERB9() || !$outlen); $txt .= "$msg\n"; } } } if (length($output_file)) { write2file($txt,$output_file); prt("Copy list written to $output_file\n"); } } elsif (VERB1()) { $rescnt = 0; $added = 0; $removed = 0; $len = length($common_destination); for ($i = 0; $i < $cnt; $i++) { #$name = $changed_files[$i][0]; #$fil1 = $changed_files[$i][1]; #$fil2 = $changed_files[$i][2]; $res = $changed_files[$i][3]; if ($res) { $removed++; } else { $added++; } } $msg = "Total $removed files removed from cleaned diff..."; $msg .= " use -v5 to view." if (!VERB5()); prt("$msg\n"); for ($i = 0; $i < $cnt; $i++) { $name = $changed_files[$i][0]; $fil1 = $changed_files[$i][1]; $fil2 = $changed_files[$i][2]; $res = $changed_files[$i][3]; $inew = $changed_files[$i][4]; if ($res) { $rescnt++; $cres = sprintf("%3d",$rescnt); $dfil = substr($fil1,$len); $msg = "$cres:REMOVED: [$dfil]"; #prt(" $fil1 ($res)\n"); $msg .= " NEW" if ($inew); prt("$msg\n") if (VERB5()); } } $msg = "Total $added files included in cleaned diff..."; $msg .= " use -v2 to view." if (!VERB2()); prt("$msg\n"); $added = 0; for ($i = 0; $i < $cnt; $i++) { $name = $changed_files[$i][0]; $fil1 = $changed_files[$i][1]; $fil2 = $changed_files[$i][2]; $res = $changed_files[$i][3]; $inew = $changed_files[$i][4]; if (!$res) { $rescnt++; $added++; $cres = sprintf("%3d:%3d",$added,$rescnt); $dfil = substr($fil1,$len); $msg = "$cres: [$dfil]"; #prt(" $fil1 ($res)\n"); $msg .= " NEW" if ($inew); prt("$msg\n") if (VERB2());; } } } } else { if (length($output_file)) { $txt = "Appears no list after cleaning\n"; write2file($txt,$output_file); prt("Blank list written to $output_file\n"); } } if (VERB5()) { prt("Common dst [$common_destination]\n"); prt("Common src [$common_source]\n"); } } # ======================================= # MAIN parse_args(@ARGV); my $ref_lines = process_file($in_file); write_out_lines($ref_lines,$out_file); show_changed_files(); pgm_exit(0,""); # ======================================= sub load_input_file($$) { my ($arg,$file) = @_; if (open INF, "<$file") { my @lines = ; close INF; my @carr = (); my ($line,@arr,$tmp,$i); my $lncnt = scalar @lines; for ($i = 0; $i < $lncnt; $i++) { $line = $lines[$i]; $line = trim_all($line); next if (length($line) == 0); next if ($line =~ /^#/); while (($line =~ /\\$/)&&(($i+1) < $lncnt)) { $i++; $line =~ s/\\$//; $line .= trim_all($lines[$i]); } #@arr = split(/\s/,$line); @arr = space_split($line); foreach $tmp (@arr) { $tmp = local_strip_both_quotes($tmp); push(@carr,$tmp); } } $in_input_file++; parse_args(@carr); $in_input_file--; } else { pgm_exit(1,"ERROR: Unable to 'open' file [$file]!\n") } } sub need_arg { my ($arg,@av) = @_; pgm_exit(1,"ERROR: Arg [$arg] must be followed by a 2nd argument!\n") if (!@av); } sub local_strip_both_quotes($) { my $txt = shift; if ($txt =~ /^'(.+)'$/) { return $1; } if ($txt =~ /^"(.+)"$/) { return $1; } return '' if ($txt eq '""'); return '' if ($txt eq "''"); #prt("Stripping [$txt] FAILED\n"); return $txt; } sub parse_args { my (@av) = @_; my ($arg,$ch,$sarg,@arr,$tmp); while (@av) { $arg = $av[0]; $ch = substr($arg,0,1); if ($arg =~ /\?/) { give_help(); pgm_exit(0,"Help exit\n"); } elsif (($ch eq '-')||($ch eq '/')) { $sarg = substr($arg,1); $sarg = substr($sarg,1) while ($sarg =~ /^-/); #$val = substr($arg,1); if ($sarg =~ /^a/) { $add_skipped_lines = 1; prt("Adding skipped lines to end of review file\n") if (VERB2()); } elsif ($sarg =~ /^h/) { give_help(); pgm_exit(0,"Help exit\n"); } elsif ($sarg =~ /^c/) { $sarg = substr($sarg,1); $show_copy_list = 1; if (length($sarg)) { $output_file = $sarg; prt("Output copy list to $output_file.\n") if (VERB2()); } else { prt("Output a copy list.\n") if (VERB2()); } # } elsif ($sarg =~ /^i/) { # if ($sarg =~ /^in:(.+)$/) { # $in_file = substr($sarg,3); # } else { # need_arg(@av); # shift @av; # $sarg = $av[0]; # $in_file = $sarg; # } # prt( "Set input file to [$in_file] ...\n" ) if (VERB2()); } elsif ($sarg =~ /^o/) { if ($sarg =~ /^out:(.+)$/) { $out_file = substr($sarg,4); } else { need_arg(@av); shift @av; $sarg = $av[0]; $out_file = $sarg; } prt( "Set output file to [$out_file] ...\n" ) if (VERB2()); } elsif ($sarg eq 'ko') { $keep_only_in = 1; prt( "Set to keep 'Only in ' lines, except in repo folder...\n" ) if (VERB2()); } elsif ($sarg eq 'KO') { $KEEP_ONLY_IN = 1; prt( "Set to keep ALL 'Only in ' lines...\n" ) if (VERB2()); } elsif ($sarg eq 'kb') { $keep_bin_files = 1; prt("Set to keep 'Binary files ' lines...\n") if (VERB2()); } elsif ($sarg eq 'll') { $load_log = 1; prt( "Set to load log at end...\n" ) if (VERB2()); } elsif ($sarg eq 'm') { $include_msvc = 1; prt( "Set to include MSVC files.\n" ) if (VERB2()); } elsif ($sarg =~ /^x/) { need_arg(@av); shift @av; $sarg = $av[0]; if ($sarg eq '_cmake_') { push(@user_xcludes, @cmake_xcludes); prt("Added [$sarg] excludes.\n") if (VERB2()); } else { @arr = split(";",$sarg); foreach $sarg (@arr) { push(@user_xcludes,$sarg); prt("Added [$sarg] to user file excludes.\n") if (VERB2()); } } } elsif ($sarg =~ /^d/) { need_arg(@av); shift @av; $sarg = $av[0]; push(@xclude_dirs,$sarg); prt("Added [$sarg] to user directory excludes.\n") if (VERB2()); } elsif ($sarg =~ /^v/) { if ($sarg =~ /^v(\d+)$/) { $verbosity = $1; } else { while ($sarg =~ /^v/) { $verbosity++; $sarg = substr($sarg,1); } } prt("Set verbosity to [$verbosity]\n") if (VERB2()); } elsif ($sarg =~ /^\@/) { $sarg = substr($sarg,1); prt("Loading from input file [$sarg]\n") if (VERB2()); load_input_file($arg,$sarg); } elsif ($sarg =~ /^i/) { need_arg(@av); shift @av; $sarg = $av[0]; prt("Loading from input file [$sarg]\n") if (VERB2()); load_input_file($arg,$sarg); } elsif ($sarg =~ /^o/) { need_arg(@av); shift @av; $sarg = $av[0]; $out_file = $sarg; prt("Set the output file to [$out_file].\n") if (VERB2()); # } elsif ($sarg =~ /^u/) { # $unix_pat_sep = 1; # prt("Set the unix path separator.\n"); } else { prt( "ERROR: Unknown argument [$arg]!\n" ); give_help(); pgm_exit(1,"Error exit\n"); } } else { # assume a bare argument in the INPUT file $in_file = $arg; prt( "Set input file to [$in_file] ...\n" ) if (VERB2()); } shift @av; } if ($in_input_file == 0) { if (length($in_file) == 0) { prt( "ERROR: NO input file found in command! Aborting...\n" ); pgm_exit(1,"No file exit\n"); } elsif ( ! -f $in_file) { prt( "ERROR: Unable to locate [$in_file] file! Aborting...\n" ); pgm_exit(1,"No file exit\n"); } } } # # 23/03/2012 - Add -u to convert paths to unix path speparator sub give_help { prt( "Brief HELP for $pgmname script ... version $VERS\n" ); prt( "$pgmname [options] -\@input input_diff\n" ); prt( "options:\n" ); prt( " -a = Add skipped lines to END of diff review file.\n"); prt( " -c[output] = Write a copy changed list. To [output], if given.\n"); prt( " -i = Load commands from input file, space, line sepearted items.\n"); prt( " -ko = Keep 'Only in ...' lines, except in .git folder, and add to end.\n" ); prt( " -KO = Keep ALL 'Only in ...' lines, and add to end.\n" ); prt( " -ll = Load log at end.\n" ); prt( " -m = Included all MSVC files, normally excluded.\n"); prt( " -v[n] = Bump or set verbosity. Def=$verbosity.\n"); prt( " -x = Exclude this file from the cleaned diff.\n"); prt( " This can be a ';' separated list, and can include wild cards, like *.html\n"); prt( " -x _cmake_ = Special exclude of CMake file changes.\n"); prt( " -d = Exclude files with this folder from the cleaned diff.\n"); prt( " -o = Set the OUTPUT cleaned diff file.\n"); # prt( " -u = Use unix path separator.\n"); prt( "Defaults: in:[$in_file], out:[$out_file]\n" ); prt( "Will exit if error found in command!\n" ); } # eof - cleandiff02.pl