#!/usr/bin/perl -w # # cvsSynchCheckout version 0.1 # # Outputs a shell script (consisting of "mkdir", "cp", "rm", "cvs add" # and "cvs remove" commands), which will "import" a directory tree # into an existing cvs checkout. # # Usage: cvsSynchCheckout # # The difference between this script and "cvs import" is that no # merging is done, and that "old" files present in the cvs working # directory are removed. # # Directories called "CVS" in are ignored. # # Note: running the script modifies no files, it just prints out the # required commands. # # Known bug: Changes to the execute permissions of files are ignored. # Known bug: Spaces in filenames result in broken output # # Written by Hannes Reich (hannesATskynetDOTie), 14/10/2004. # This code is in the public domain. # use strict; use warnings; use File::Find; use File::Basename; sub process_source_file($ ); sub process_target_file($ ); die "Usage: $0 \n" unless 1 == $#ARGV; my($source_dir, $target_dir) = @ARGV; # strip trailing slashes from arguments map s&/+$&&g, ($source_dir, $target_dir); print < \&process_target_file, "no_chdir" => 1 }, ($target_dir) ); # Generate commands to bring over the contents of the source dir find({"wanted" => \&process_source_file, "no_chdir" => 1 }, ($source_dir) ); # Note: find() processes directories _before_ their contents, which is # what we need for "cvs add", while finddepth() processes directories # _after_ their contents, which is the Right Thing for "cvs remove". exit; sub process_source_file($ ) { my $source = $File::Find::name; return if $source eq $source_dir; my $target = $source; $target =~ s/^$source_dir/$target_dir/ or die "Source file name '$source' doesn't contain '$source_dir'. I don't understand this.\n"; if(-d $source and not -d $target) { print "cvs remove -f $target\n" if -e $target; # delete file with same name as the dir we want to create print "mkdir -p $target\n"; } if(-f $source) { if(-d $target) # dir with same name as the file we want to # create! { die "Error: '$target' is in CVS as a directory, so we can never check in '$source'!\n" if -d "$target/CVS"; print "rm -rf $target\n"; } # Don't bother with compares, let CVS worry about that # Don't use -a because CVS likes timestamps to be real. print "cp -f $source $target\n"; print "cvs add $target\n"; } } sub process_target_file($ ) { my $target = $File::Find::name; return if $target eq $target_dir or ($target =~ m&/CVS(/|$)&); my $source = $target; $source =~ s/^$target_dir/$source_dir/ or die "Target file name '$target' doesn't contain '$target_dir'. I don't understand this.\n"; if(not -e $source) { # No need for special directory handling here because when # this is called by finddepth(), we will already have # processed the directory contents. print "cvs remove -f $target\n"; } }