3 ###############################################################################
6 # Author : Chris Koeritz #
7 # Rights : Copyright (C) 1996-$now by Author #
11 # A collection of services used for creating a report of differences #
12 # between two directories. #
14 ###############################################################################
15 # This program is free software; you can redistribute it and/or modify it #
16 # under the terms of the GNU General Public License as published by the Free #
17 # Software Foundation; either version 2 of the License or (at your option) #
18 # any later version. See: "http://www.gruntose.com/Info/GNU/GPL.html" for a #
19 # version of the License. Please send any updates to "fred@gruntose.com". #
20 ###############################################################################
22 # note: this script and the scripts that use it require the Text::Diff
23 # support from CPAN. this can be installed by using cpan and telling it
27 require "filename_helper.pl";
28 require "importenv.pl";
33 local(@arguments) = @_;
35 # print "args: @arguments\n";
37 ############################################################################
39 # constants used for header creation.
40 $long_line = "--------------\n";
41 $break_line = "\n##############\n";
43 $differing_header = "Differences seen for %1:\n";
45 ############################################################################
47 # state machine constants and initialization.
49 $STARTING = 2; # initial state.
50 $SAW_DIFF = 3; # recently saw a difference.
51 $SAW_SAME = 4; # recently saw no differences.
55 ############################################################################
57 $header_printed = 0; # did we print the header for this directory yet?
59 ############################################################################
61 if ($#arguments < 0) {
62 # complain if they don't pass a directory name.
67 # get the comparison directory from the arguments.
68 local($compare_directory) = &sanitize_name($arguments[0]);
69 if ($compare_directory eq "") {
70 # it's a bad directory name, only composed of slashes.
74 if (-l $compare_directory) {
75 # we will not operate on links, due to recursion issues.
76 ## &differ_instructions;
77 print "skipping link: $compare_directory\n";
80 if (! -d $compare_directory) {
81 # a missing directory is just not good.
82 print "skipping missing directory: $compare_directory\n";
86 # the current directory is usually used as the starting point.
87 local($source_directory) = ".";
88 if ($arguments[1] ne "") {
89 # they specified a current directory.
90 $source_directory = $arguments[1];
92 $source_directory = &sanitize_name($source_directory);
93 if (-l $source_directory) {
94 # we will not operate on links, due to recursion issues.
95 # &differ_instructions;
96 print "skipping link: $source_directory\n";
99 if (! -d $source_directory) {
100 # a missing directory is just not good.
101 print "skipping missing directory: $source_directory\n";
105 # print "src=$source_directory, dest=$compare_directory\n";
107 # keep a local copy of the names for print_header.
108 #hmmm: fix bad design.
109 local($temp_src) = $source_directory;
110 local($temp_dest) = $compare_directory;
112 # iterate over all the files in the source directory.
113 opendir CURDIR, $source_directory
114 || die("couldn't open $source_directory for reading.\n");
115 foreach $filename (readdir CURDIR) {
116 if ( ($filename eq ".") || ($filename eq "..") ) { next; }
117 $filename = $source_directory."/".$filename;
118 # make sure we compare against the base part of the name.
119 @name_components = split(/\//, $filename);
120 $basename = $name_components[$#name_components];
121 # print "doing diff of $filename against $compare_directory/$basename\n";
122 &do_diff($filename, $compare_directory."/".$basename);
126 if ($state == $SAW_SAME) {
130 # report files that exist in target directory, but not here, or vice-versa.
131 &back_compare($compare_directory, $source_directory);
132 &back_compare($source_directory, $compare_directory);
134 # only print the closure line if we printed some other stuff.
135 if ($header_printed) {
137 ### print $break_line;
143 ############################################################################
146 # this function prints out the header prior to printing out any real
147 # data. if there are no diffs, the header should never get printed.
148 print "$break_line\n";
149 local($printable_date) = &ctime(time);
150 $printable_date =~ s/\n//g;
151 print "[$printable_date]\n";
152 print "Left (<) is \"$temp_src\".\n";
153 print "Right (>) is \"$temp_dest\".\n";
158 ############################################################################
160 sub differ_instructions {
163 This program needs a directory name. The directory name is used to
164 specify a target directory where there are files which are mostly similar
165 to the files in this directory. The files in the current directory are
166 compared to those in the specified target directory and the differences
167 are sent to the standard output. Note that neither directory may be
168 a symbolic link, as that can lead to crazy recursion.
172 ############################################################################
174 sub cpdiff_instructions {
177 This program needs two directory names. The first is the source and the
178 second is a target directory where the files are mostly similar to the files
179 in the source directory. The files in source are compared to those in the
180 target directory and if a file differs, then it's copied from the source to
181 the target. Also, if the file does not exist in the target directory, it
186 ############################################################################
188 sub synchronize_instructions {
191 This program needs one directory name to be passed on the command line.
192 This directory is where the installation's executable files live. Any files
193 that are in the installation bin directory will be compared against the files
194 in the build repository (specified by an environment variable FEISTY_MEOW_DIR).
195 If files differ, they will be copied from the repository into the installation
200 ############################################################################
202 # replaces the variable marks in the text with the two substitutions.
205 local($text, $subst_1, $subst_2) = @_;
207 local($text_copy) = $text;
208 $text_copy =~ s/%1/$subst_1/;
209 $text_copy =~ s/%2/$subst_2/;
214 sub change_to_saw_diffs {
215 print $separator, $long_line;
218 sub change_to_saw_same {
221 ############################################################################
223 # checks the differences between the two files and creates appropriate output.
226 local($first, $second) = @_;
228 # turn stupid pc slashes into normal ones.
230 $second =~ s/\\/\//g;
232 @first_components = split(/\//, $first);
233 $base_filename1 = $first_components[$#first_components];
234 @second_components = split(/\//, $second);
235 $base_filename2 = $second_components[$#second_components];
237 # skip if it's a directory.
238 if (-d $first) { return; }
240 # skip the file if we don't think it's important.
241 if (! &important_filename($base_filename1)) { return; }
244 # make sure we don't bother if the file's not in the target directory.
248 local($diff_output) = diff $first, $second, { STYLE => "OldStyle" };
250 if (!length($diff_output)) {
251 # there are no differences.
254 # there were differences.
255 if (!$header_printed) { &print_header; }
257 &change_to_saw_diffs;
259 print &replace_text($differing_header, $base_filename1);
262 if (-B $first || -B $second) {
263 print "Binary files $first and $second differ.\n";
270 ############################################################################
272 # this function copies files as needed by comparing whether a file has
273 # changed or not. third parm is a flag added to cp, like -p to preserve
277 local($first, $second, $third) = @_;
279 @first_components = split(/\//, $first);
280 $base_filename1 = $first_components[$#first_components];
281 @second_components = split(/\//, $second);
282 $base_filename2 = $second_components[$#second_components];
284 # turn stupid pc slashes into normal ones.
285 $second =~ s/\\/\//g;
287 # skip if it's a directory.
288 if (-d $first) { return; }
290 # skip the file if we don't think it's important.
291 if (! &important_filename($base_filename1)) { return; }
294 # the file doesn't exist yet, so copy it.
295 # print "copying $first -> $second\n";
296 system("cp -f -v $third \"$first\" \"$second\"");
300 local($diff_output) = diff $first, $second, { STYLE => "OldStyle" };
301 if (length($diff_output)) {
302 # there were differences in the two files, so copy the source.
303 # print "copying $first -> $second\n";
304 system("cp -f -v $third \"$first\" \"$second\"");
307 #print "did nothing; $first & $second are identical\n";
310 ############################################################################
312 # back_compare checks to make sure that all of the files in the target
313 # directory are represented in the source directory.
316 local($source, $target) = @_;
317 local(@missing_list);
319 # print "backcomp: source=$source target=$target\n";
321 opendir CURDIR, $target
322 || die("couldn't open $target for reading.\n");
323 foreach $filename (readdir CURDIR) {
324 if ( ($filename eq ".") || ($filename eq "..") ) { next; }
326 $filename = $target."/".$filename;
327 # chop up the filename.
328 @dirs = split(/\//, $filename);
329 # get the basename from the last array element.
330 $basename = $dirs[$#dirs];
332 # skip the file if it seems like junk.
333 if (! &important_filename($basename)) { next; }
335 # print "backcomp: file a=$source/$basename b=$filename\n";
336 if ( (! -e "$source/$basename") && (! -d $filename) ) {
337 push(@missing_list, $basename);
342 if ($#missing_list < 0) { return; }
344 if (!$header_printed) { &print_header; }
348 These exist in \"$target\",
349 but not in \"$source\":
353 foreach $filename (@missing_list) {
358 ############################################################################
360 # this function copies files from the source directory to the target directory
361 # if there is a file of the same name whose contents differ, or if there is
362 # no file of that name in the target directory.
365 local(@arguments) = @_;
366 # print "args: @arguments\n";
368 if ($#arguments < 1) {
369 # complain if they don't pass two directory names.
370 &cpdiff_instructions;
374 # the source directory is the first parameter.
375 local($source_directory) = &sanitize_name($arguments[0]);
376 if ($source_directory eq "") {
377 # it's a bad directory name, only composed of slashes.
378 &cpdiff_instructions;
381 if (-l $source_directory) {
382 # we will not operate on links, due to recursion issues.
383 &cpdiff_instructions;
387 # get the comparison directory from the arguments.
388 local($compare_directory) = &sanitize_name($arguments[1]);
389 if ($compare_directory eq "") {
390 # it's a bad directory name here.
391 &cpdiff_instructions;
394 if (-l $compare_directory) {
395 # we will not operate on links, due to recursion issues.
396 &cpdiff_instructions;
400 # print "src=$source_directory, dest=$compare_directory\n";
402 # iterate over all the files in the source directory.
403 opendir CURDIR, $source_directory
404 || die("couldn't open $source_directory for reading.\n");
405 foreach $filename (readdir CURDIR) {
406 if ( ($filename eq ".") || ($filename eq "..") ) { next; }
407 $filename = $source_directory."/".$filename;
408 # make sure we compare against the base part of the name.
409 @name_components = split(/\//, $filename);
410 $basename = $name_components[$#name_components];
411 # print "diffing $filename against $compare_directory/$basename\n";
412 &do_cpdiff($filename, $compare_directory."/".$basename, "-p");
417 ############################################################################
419 # this version of copy_diff_dirs (see above) causes the dates of the copied
420 # files to be changed to "now".
422 #hmmm: extract the common bits used in copy_diff_dirs into useful functions.
424 sub copy_diff_dirs_using_now {
425 local(@arguments) = @_;
426 # print "args: @arguments\n";
428 if ($#arguments < 1) {
429 # complain if they don't pass two directory names.
430 &cpdiff_instructions;
434 # the source directory is the first parameter.
435 local($source_directory) = &sanitize_name($arguments[0]);
436 if ($source_directory eq "") {
437 # it's a bad directory name, only composed of slashes.
438 &cpdiff_instructions;
442 # get the comparison directory from the arguments.
443 local($compare_directory) = &sanitize_name($arguments[1]);
444 if ($compare_directory eq "") {
445 # it's a bad directory name here.
446 &cpdiff_instructions;
450 # print "src=$source_directory, dest=$compare_directory\n";
452 # iterate over all the files in the source directory.
453 opendir CURDIR, $source_directory
454 || die("couldn't open $source_directory for reading.\n");
455 foreach $filename (readdir CURDIR) {
456 if ( ($filename eq ".") || ($filename eq "..") ) { next; }
457 $filename = $source_directory."/".$filename;
458 # make sure we compare against the base part of the name.
459 @name_components = split(/\//, $filename);
460 $basename = $name_components[$#name_components];
461 # print "diffing $filename against $compare_directory/$basename\n";
462 &do_cpdiff($filename, $compare_directory."/".$basename);
467 ############################################################################
469 # makes sure all of the exes and dynamic libs are up to date in the
470 # installed executable directory.
472 sub synchronize_against_build
474 local(@arguments) = @_;
476 # print "args: @arguments\n";
478 if ($#arguments < 0) {
479 # complain if they don't pass a directory name.
480 &synchronize_instructions;
484 # clean up the directory they passed.
485 local($install_directory) = &sanitize_name($arguments[0]);
486 if ($install_directory eq "") {
487 # it's a bad directory name, only composed of slashes.
488 &synchronize_instructions;
492 # print "install=$install_directory\n";
493 # print "repos=$FEISTY_MEOW_DIR\n";
495 # iterate over all the files in the source directory.
496 opendir CURDIR, $install_directory
497 || die("couldn't open $install_directory for reading.\n");
498 $compare_directory = "$FEISTY_MEOW_DIR/dll";
499 foreach $filename (readdir CURDIR) {
500 if ( ($filename eq ".") || ($filename eq "..") ) { next; }
501 if (! ($filename =~ /\.dll$/)) { next; }
502 $filename = $install_directory."/".$filename;
503 # make sure we compare against the base part of the name.
504 @name_components = split(/\//, $filename);
505 $basename = $name_components[$#name_components];
506 if (! -e $compare_directory."/".$basename) {
509 # print "diffing $filename against $compare_directory/$basename\n";
510 &do_cpdiff($compare_directory."/".$basename, $filename);
514 # repeat for the exe directory.
515 opendir CURDIR, $install_directory
516 || die("couldn't open $install_directory for reading.\n");
517 $compare_directory = "$FEISTY_MEOW_DIR/exe";
518 foreach $filename (readdir CURDIR) {
519 if ( ($filename eq ".") || ($filename eq "..") ) { next; }
520 if (! ($filename =~ /\.exe$/)) { next; }
521 $filename = $install_directory."/".$filename;
522 # make sure we compare against the base part of the name.
523 @name_components = split(/\//, $filename);
524 $basename = $name_components[$#name_components];
525 if (! -e $compare_directory."/".$basename) {
528 # print "diffing $filename against $compare_directory/$basename\n";
529 &do_cpdiff($compare_directory."/".$basename, $filename);
534 ############################################################################