Changeset 37034 for main


Ignore:
Timestamp:
2022-12-17T11:57:05+13:00 (17 months ago)
Author:
davidb
Message:

Introduction of new (internal) general purpose recursive file/dir copy. In a later phase, the existing public subroutines will be changed over to using it

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone2/perllib/FileUtils.pm

    r32204 r37034  
    167167
    168168
     169## @function readdirFullpath()
     170#
     171# For the given input directory, return full-path versions of the
     172# files and directories it contains
     173#
     174# returned data is in the form of the tuple (status, fullpath-listing)
     175#
     176
     177sub readdirFullpath
     178{
     179    my ($src_dir_fullpath,$options) = @_;
     180
     181    my $ret_val = 1; # assume things will work out!
     182    my $fullpath_files_and_dirs = [];
     183
     184    my $exclude_filter_re = undef;
     185    my $include_filter_re = undef;
     186    if (defined $options) {
     187    $exclude_filter_re = $options->{'exclude_filter_re'};
     188    $include_filter_re = $options->{'include_filter_re'};
     189    }
     190   
     191    # get the contents of this directory
     192    if (!opendir(INDIR, $src_dir_fullpath))
     193    {
     194    print STDERR "FileUtils::readdirFullpath() could not open directory $src_dir_fullpath\n";
     195    $ret_val = 0;   
     196    }
     197    else
     198    {
     199    my @next_files_and_dirs = readdir(INDIR);
     200    closedir (INDIR);
     201
     202    foreach my $f_or_d (@next_files_and_dirs)
     203    {
     204        next if $f_or_d =~ /^\.\.?$/;
     205        next if (defined $exclude_filter_re && ($f_or_d =~ m/$exclude_filter_re/));
     206       
     207        if ((!defined $include_filter_re) || ($f_or_d =~ m/$include_filter_re/)) {
     208        my $ff_or_dd = &filenameConcatenate($src_dir_fullpath, $f_or_d);
     209        push(@$fullpath_files_and_dirs,$ff_or_dd);
     210        }
     211    }
     212
     213    }
     214
     215    return ($ret_val,$fullpath_files_and_dirs);
     216}
     217
     218
     219           
     220## @function _copyFilesRecursiveGeneral()
     221#
     222# internal support routine for recursively copying or hard-linking files
     223#
     224sub _copyFilesRecursiveGeneral
     225{
     226    my ($srcfiles_ref,$dest,$depth,$options) = @_;
     227
     228    # a few sanity checks
     229    my $num_src_files = scalar (@$srcfiles_ref);
     230   
     231    if ($num_src_files == 0)
     232    {
     233    print STDERR "FileUtils::copyFilesRecursive() no destination directory given\n";
     234    return 0;
     235    }
     236    elsif (-f $dest)
     237    {
     238    print STDERR "FileUtils::copyFilesRecursive() destination must be a directory\n";
     239    return 0;
     240    }
     241
     242    if ($depth == 0) {
     243    # Test for the special (top-level) case where:
     244    #   there is only one src file
     245    #   it is a directory
     246    #   and dest as a directory does not exits
     247    #
     248    # => This is a case similar to something like cp -r abc/ def/
     249    #    where we *don't* want abc ending up inside def
     250   
     251   
     252    if ($num_src_files == 1) {
     253       
     254        my $src_first_fullpath = $srcfiles_ref->[0];
     255
     256        if (-d $src_first_fullpath) {
     257        my $src_dir_fullpath = $src_first_fullpath;
     258
     259        if (! -e $dest) {
     260            # Do slight of hand, and replace the supplied single src_dir_fullpath with the contents of
     261            # that directory
     262
     263            my ($readdir_status, $fullpath_subfiles_and_subdirs) = &readdirFullpath($src_dir_fullpath,$options);
     264           
     265            if (!$readdir_status) {
     266            return 0;
     267            }
     268            else
     269            {
     270            $srcfiles_ref = $fullpath_subfiles_and_subdirs;   
     271            }
     272        }
     273        }
     274    }
     275    }
     276
     277
     278    # create destination directory if it doesn't exist already
     279    if (! -d $dest)
     280    {
     281    my $store_umask = umask(0002);
     282    my $mkdir_status = mkdir($dest, 0777);
     283   
     284    if (!$mkdir_status) {
     285        print STDERR "$!\n";
     286        print STDERR "FileUtils::_copyFilesRecursiveGeneral() failed to create directory $dest\n";
     287        umask($store_umask);
     288       
     289        return 0;
     290    }
     291    umask($store_umask);
     292    }
     293
     294   
     295    # copy the files
     296    foreach my $file (@$srcfiles_ref)
     297    {
     298    if (! -e $file)
     299    {
     300        print STDERR "FileUtils::_copyFilesRecursiveGeneral() $file does not exist\n";
     301        # wrap up in strict option check
     302        return 0;
     303    }
     304    elsif (-d $file)
     305    {
     306        my $src_dir_fullpath = $file; # know by this point that $file is actually a sub-directory
     307
     308        # make the new directory
     309        my ($src_dirname_tail) = $src_dir_fullpath =~ /([^\\\/]*)$/;
     310
     311        my $next_dest = &filenameConcatenate($dest, $src_dirname_tail);
     312        my $store_umask = umask(0002);
     313        mkdir ($next_dest, 0777);
     314        umask($store_umask);
     315
     316        my ($readdir_status, $fullpath_src_subfiles_and_subdirs) = &readdirFullpath($src_dir_fullpath,$options);
     317
     318        if (!$readdir_status) {
     319        return 0;
     320        }
     321        else {
     322
     323        foreach my $fullpath_subf_or_subd (@$fullpath_src_subfiles_and_subdirs)
     324        {
     325            # Recursively copy all the files/dirs in this directory:
     326            #   In the general version need the source argument to be a reference to an array
     327            my $ret_val = &_copyFilesRecursiveGeneral([$fullpath_subf_or_subd],$next_dest, $depth+1, $options);
     328
     329            if ($ret_val == 0) {
     330            # Error condition encountered
     331            return 0;
     332            }
     333        }
     334        }
     335       
     336#       # get the contents of this directory
     337#       if (!opendir(INDIR, $src_dir_fullpath))
     338#       {
     339#       print STDERR "FileUtils::_copyFilesRecursiveGeneral() could not open directory $src_dir_fullpath\n";
     340#       }
     341#       else
     342#       {
     343#       my @next_files_and_dirs = readdir(INDIR);
     344#       closedir (INDIR);
     345#       foreach my $f_or_d (@next_files_and_dirs)
     346#       {
     347#           next if $f_or_d =~ /^\.\.?$/;
     348#           # recursively copy all the files/dirs in this directory
     349#           my $ff_or_dd = &filenameConcatenate($src_dir_fullpath, $f_or_d);
     350#           # In the general version need the source argument to be a reference to an array
     351#           my $ret_val = &_copyFilesRecursiveGeneral($next_dest, [ $ff_or_dd ], $options);
     352#
     353#           if ($ret_val == 0) {
     354#           # Error condition encountered
     355#           return 0;
     356#           }
     357#       }
     358#       }
     359       
     360    }
     361    else
     362    {
     363        &copyFiles($file, $dest);
     364    }
     365    }
     366
     367    return 1;
     368}
     369## _copyFilesRecursiveGeneral()
     370
     371
     372
    169373## @function copyFilesRecursive()
    170374#
Note: See TracChangeset for help on using the changeset viewer.