2000-08-23 04:54:08 +04:00
|
|
|
|
#!perl -w
|
|
|
|
|
|
2000-08-23 05:03:47 +04:00
|
|
|
|
# This script copies modified files from a source CVS tree to a destination
|
|
|
|
|
# tree. Modified files are detected by comparing their modification dates
|
|
|
|
|
# with the CVS Entries file.
|
2000-08-23 04:54:08 +04:00
|
|
|
|
#
|
2000-08-23 05:03:47 +04:00
|
|
|
|
# Modified files are copied in their entirety to the destination tree
|
|
|
|
|
# (no diffing is done). Files are only copied of the CVS version of the
|
|
|
|
|
# file is the same in both trees. If the destination file is modified
|
|
|
|
|
# already, it is backed up and replaced.
|
2000-08-23 04:54:08 +04:00
|
|
|
|
#
|
2000-08-23 05:03:47 +04:00
|
|
|
|
# To use this on your tree/platform, do the following:
|
2000-08-23 04:54:08 +04:00
|
|
|
|
#
|
2000-08-23 05:03:47 +04:00
|
|
|
|
# 1. Fix the !perl line, if necessary.
|
|
|
|
|
# 2. Fix $dirsep to be the directory separator on your platform.
|
|
|
|
|
# 3. Uncomment the appropriate $dst_linebreaks file specify what linebreaks
|
2000-08-26 05:23:43 +04:00
|
|
|
|
# you want for the copied files. This variable defines the *destination* linebreaks
|
|
|
|
|
# that you want your changes to be converted to.
|
|
|
|
|
# For example, if you have a linux volume
|
|
|
|
|
# mounted (via SAMBA perhaps) to your windows box where you've made changes to
|
|
|
|
|
# source files, you'd want $dst_linebreaks to be set for unix. This ensures that
|
|
|
|
|
# linebreaks are converted to the appropriate OS linebreak scheme for your *target* tree.
|
2000-08-23 05:03:47 +04:00
|
|
|
|
# 4. Set $src_tree and $dest_tree to point to the directories you want
|
|
|
|
|
# to sync up. These don't have to point to the root of the tree,
|
|
|
|
|
# but should be equivalent directories in the two trees.
|
|
|
|
|
#
|
|
|
|
|
# First version:
|
|
|
|
|
# Simon Fraser <sfraser@netscape.com>
|
2000-08-23 04:54:08 +04:00
|
|
|
|
|
|
|
|
|
use File::stat;
|
|
|
|
|
use Time::Local;
|
|
|
|
|
|
2000-08-26 05:23:43 +04:00
|
|
|
|
# change for your platform ('\' == windows, ':' == mac, '/' == unix)
|
2000-09-02 08:29:25 +04:00
|
|
|
|
$dirsep = "\\";
|
2000-08-23 04:54:08 +04:00
|
|
|
|
|
2000-08-26 05:23:43 +04:00
|
|
|
|
# Set this to the native OS of the *destination* tree
|
2000-08-23 04:54:08 +04:00
|
|
|
|
# $dst_linebreaks = pack("cc", 13); # Mac
|
2000-09-02 08:29:25 +04:00
|
|
|
|
#$dst_linebreaks = pack("cc", 13, 10); # DOS
|
|
|
|
|
$dst_linebreaks = pack("cc", 10); # UNIX
|
2000-08-23 04:54:08 +04:00
|
|
|
|
|
|
|
|
|
#change for your src and dest trees
|
2000-09-02 08:29:25 +04:00
|
|
|
|
$src_tree = "x:\\mozilla\\xpfe\\components";
|
|
|
|
|
$dest_tree = "h:\\builds\\mozilla\\xpfe\\components";
|
2000-08-23 04:54:08 +04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#//--------------------------------------------------------------------------------------------------
|
|
|
|
|
#// _copyFile. Copy file from src to dest, converting linebreaks if necessary
|
|
|
|
|
#//--------------------------------------------------------------------------------------------------
|
|
|
|
|
sub _copyFile($;$;$;$)
|
|
|
|
|
{
|
|
|
|
|
my($srcdir, $destdir, $file, $backup) = @_;
|
|
|
|
|
|
|
|
|
|
my($srcfile) = $srcdir.$dirsep.$file;
|
|
|
|
|
my($dstfile) = $destdir.$dirsep.$file;
|
|
|
|
|
|
|
|
|
|
if ($backup)
|
|
|
|
|
{
|
|
|
|
|
my($counter) = 0;
|
|
|
|
|
|
|
|
|
|
while (-f $dstfile."-".$counter)
|
|
|
|
|
{
|
|
|
|
|
$counter ++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rename($dstfile, $dstfile."-".$counter) or die "Failed to rename file\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print "Copying $file over to dest\n";
|
|
|
|
|
|
|
|
|
|
my($newdest) = $dstfile."_temp";
|
|
|
|
|
|
|
|
|
|
open(SRCFILE, "< $srcfile") or die "Can't open source file $srcfile\n";
|
|
|
|
|
open(NEWDEST, "> $newdest") or die "Can't open dest file $newdest\n";
|
|
|
|
|
|
|
|
|
|
while (<SRCFILE>)
|
|
|
|
|
{
|
|
|
|
|
chomp($_);
|
|
|
|
|
print NEWDEST $_.$dst_linebreaks;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
close(SRCFILE);
|
|
|
|
|
close(NEWDEST);
|
|
|
|
|
|
|
|
|
|
if (!$backup) {
|
|
|
|
|
unlink($dstfile) or die "Failed to remove $dstfile\n";
|
|
|
|
|
}
|
|
|
|
|
rename($newdest, $dstfile) or die "Failed to rename $newdest\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#//--------------------------------------------------------------------------------------------------
|
|
|
|
|
#// _readCVSInfo. Suck in the CVS info from the Entries file
|
|
|
|
|
#//--------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
sub _readCVSInfo($)
|
|
|
|
|
{
|
|
|
|
|
my($cvsDir) = @_;
|
|
|
|
|
|
|
|
|
|
my($entries_file_name) = $cvsDir.$dirsep."CVS".$dirsep."Entries";
|
|
|
|
|
|
|
|
|
|
# print "Reading $entries_file_name\n";
|
|
|
|
|
open(ENTRIES, $entries_file_name) || die "Could not open file $entries_file_name";
|
|
|
|
|
|
|
|
|
|
my(%cvs_entries);
|
|
|
|
|
|
|
|
|
|
# Read in the path if available
|
|
|
|
|
while (defined ($line = <ENTRIES>))
|
|
|
|
|
{
|
|
|
|
|
chomp($line);
|
2000-08-23 05:03:47 +04:00
|
|
|
|
|
2000-08-23 04:54:08 +04:00
|
|
|
|
#parse out the line. Format is:
|
|
|
|
|
# files: /filename/version/date/options/tag
|
|
|
|
|
# dirs: D/dirname////
|
|
|
|
|
# dir? D
|
2000-08-23 05:03:47 +04:00
|
|
|
|
# because we might be reading an entries file from another platform, with
|
|
|
|
|
# different linebreaks, be anal about cleaning up $line.
|
2000-08-23 04:54:08 +04:00
|
|
|
|
|
2000-08-23 05:03:47 +04:00
|
|
|
|
if ($line =~ /^?\/(.+)\/(.+)\/(.+)\/(.*)\/(.*)?$/)
|
2000-08-23 04:54:08 +04:00
|
|
|
|
{
|
|
|
|
|
my($filename) = $1;
|
|
|
|
|
my($version) = $2;
|
|
|
|
|
my($date) = $3;
|
|
|
|
|
my($options) = $4;
|
|
|
|
|
my($tag) = $5;
|
|
|
|
|
|
|
|
|
|
my(%cvs_file) = (
|
|
|
|
|
"version" => $version,
|
|
|
|
|
"date" => $date,
|
|
|
|
|
"options" => $options,
|
|
|
|
|
"tag" => $tag
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
# print $filename." ".$version." ".$date." ".$options." ".$tag."\n";
|
|
|
|
|
$cvs_entries{$filename} = \%cvs_file;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
close ENTRIES;
|
|
|
|
|
|
|
|
|
|
return %cvs_entries;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#//--------------------------------------------------------------------------------------------------
|
|
|
|
|
#// _fileIsModified. compare mod date with CVS entries to see if a file is modified
|
|
|
|
|
#//--------------------------------------------------------------------------------------------------
|
|
|
|
|
sub _fileIsModified($;$;$)
|
|
|
|
|
{
|
|
|
|
|
my($entries, $dir, $file) = @_;
|
|
|
|
|
|
|
|
|
|
my($abs_file) = $dir.$dirsep.$file;
|
|
|
|
|
|
|
|
|
|
if (exists($entries->{$file}))
|
|
|
|
|
{
|
|
|
|
|
my($date) = $entries->{$file}->{"date"};
|
|
|
|
|
|
|
|
|
|
# stat the file to get its date
|
|
|
|
|
my($file_data) = stat($abs_file) || die "Could not stat $file\n";
|
|
|
|
|
my($mod_string) = scalar(gmtime($file_data->mtime));
|
|
|
|
|
|
|
|
|
|
return ($mod_string ne $date);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#//--------------------------------------------------------------------------------------------------
|
|
|
|
|
#// _processFile. args: entries hash, dir, filename
|
|
|
|
|
#//--------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
sub _processFile($;$;$;$;$)
|
|
|
|
|
{
|
|
|
|
|
my($src_entries, $dest_entries, $srcdir, $destdir, $file) = @_;
|
|
|
|
|
|
|
|
|
|
my($abs_file) = $srcdir.$dirsep.$file;
|
|
|
|
|
|
|
|
|
|
if (exists($src_entries->{$file}))
|
|
|
|
|
{
|
|
|
|
|
my($file_entry) = $src_entries->{$file};
|
|
|
|
|
my($version) = $file_entry->{"version"};
|
|
|
|
|
|
|
|
|
|
if (_fileIsModified($src_entries, $srcdir, $file))
|
|
|
|
|
{
|
|
|
|
|
my($rel_file) = $abs_file;
|
|
|
|
|
$rel_file =~ s/^$src_tree//;
|
|
|
|
|
|
|
|
|
|
# print "<22><>File $rel_file is modified\n";
|
|
|
|
|
|
|
|
|
|
# check CVS version in dest
|
|
|
|
|
my($dest_entry) = $dest_entries->{$file};
|
|
|
|
|
if ($dest_entry)
|
|
|
|
|
{
|
|
|
|
|
my($dest_version) = $dest_entry->{"version"};
|
|
|
|
|
my($versions_match) = ($version == $dest_version);
|
|
|
|
|
my($dest_modified) = _fileIsModified($dest_entries, $destdir, $file);
|
|
|
|
|
|
|
|
|
|
if ($versions_match)
|
|
|
|
|
{
|
|
|
|
|
# ok, we can copy the file over now, backing up dest if it is modified
|
|
|
|
|
_copyFile($srcdir, $destdir, $file, $dest_modified);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
print "File $rel_file is version $version in the src tree, but $dest_version in dest. This file will not be copied.\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
print "No CVS entry found in destination tree for $rel_file\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
print "No entry for file $file\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#//--------------------------------------------------------------------------------------------------
|
|
|
|
|
#// _traverseDir. Traverse one dir, recurse for each found dir.
|
|
|
|
|
#//--------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
sub _traverseDir($;$)
|
|
|
|
|
{
|
|
|
|
|
my($srcdir, $destdir) = @_;
|
|
|
|
|
|
|
|
|
|
opendir(DIR, $srcdir) or die "Cannot open dir $srcdir\n";
|
|
|
|
|
my @files = readdir(DIR);
|
|
|
|
|
closedir DIR;
|
|
|
|
|
|
|
|
|
|
# suck in the CVS info for this dir, if there is a CVS dir
|
2000-09-02 08:29:25 +04:00
|
|
|
|
unless (-e $srcdir.$dirsep."CVS".$dirsep."Entries" && -e $destdir.$dirsep."CVS".$dirsep."Entries") {
|
2000-08-23 04:54:08 +04:00
|
|
|
|
print "$srcdir is not a CVS directory in both source and dest\n";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print " Doing $srcdir\n";
|
|
|
|
|
|
|
|
|
|
my(%src_entries) = _readCVSInfo($srcdir);
|
|
|
|
|
my(%dest_entries) = _readCVSInfo($destdir);
|
|
|
|
|
|
|
|
|
|
my $file;
|
|
|
|
|
foreach $file (@files)
|
|
|
|
|
{
|
|
|
|
|
my $filepath = $srcdir.$dirsep.$file;
|
|
|
|
|
|
|
|
|
|
if (-d $filepath)
|
|
|
|
|
{
|
|
|
|
|
if ($file ne "CVS") # ignore 'CVS' dirs
|
|
|
|
|
{
|
|
|
|
|
# print "Going into $filepath\n";
|
|
|
|
|
_traverseDir($filepath, $destdir.$dirsep.$file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
# process this file
|
|
|
|
|
_processFile(\%src_entries, \%dest_entries, $srcdir, $destdir, $file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#//--------------------------------------------------------------------------------------------------
|
|
|
|
|
#// MigrateChanges
|
|
|
|
|
#//--------------------------------------------------------------------------------------------------
|
|
|
|
|
sub MigrateChanges($;$)
|
|
|
|
|
{
|
|
|
|
|
my($srcdir, $destdir) = @_;
|
|
|
|
|
|
|
|
|
|
# Check that src and dest exist
|
|
|
|
|
if (! -d $srcdir) {
|
|
|
|
|
die "Source directory $srcdir does not exist\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! -d $destdir) {
|
|
|
|
|
die "Dest directory $destdir does not exist\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print "---------------------------------------------------------\n";
|
|
|
|
|
print "Migrating changes from\n $srcdir\nto\n $destdir\n";
|
|
|
|
|
print "---------------------------------------------------------\n";
|
|
|
|
|
_traverseDir($srcdir, $destdir);
|
|
|
|
|
print "---------------------------------------------------------\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MigrateChanges($src_tree, $dest_tree);
|
|
|
|
|
|