Subversion Repositories DevTools

Rev

Rev 4309 | Rev 4421 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
########################################################################
2
# Copyright ( C ) 2005 ERG Limited, All rights reserved
3
#
4
# Module name   : jats.sh
5
# Module type   : Perl Package
6
# Compiler(s)   : n/a
7
# Environment(s): jats
8
#
9
# Description   : This package contains functions to manipulate file paths
10
#                 directories and names.
11
#
12
#                    Getcwd                     - Get current directory
13
#                    Realpath                   - Get real path
14
#                    Realfile                   - Get real path ?
15
#                    RelPath                    - Convert to relative path
16
#                    AbsPath                    - Convert to Abs path
17
#                    FullPath                   - Convert to Abs path with driver letter
257 dpurdie 18
#                    TruePath                   - Case Corrected pathname
227 dpurdie 19
#                    CleanPath                  - Clean up a path
20
#                    StripDrive                 - Remove drive letter
21
#                    StripDir                   - Return file + extension
22
#                    StripExt                   - Return dir + file
23
#                    StripFile                  - Returns extension
24
#                    StripFileExt               - Returns directory
25
#                    StripDirExt                - Returns filename ( with optional ext)
26
#                    CleanDirName               - Clean up a path
261 dpurdie 27
#                    TouchFile                  - Touch a file
28
#                    FileIsNewer                - Test if newer
227 dpurdie 29
#                    DisplayPath                - Genate a Path that can be displayed
261 dpurdie 30
#                    FileCreate                 - Create a simple text file
31
#                    FileAppend                 - Append to a simple text file
379 dpurdie 32
#                    RmDirTree                  - Remove a directory tree
227 dpurdie 33
#
34
#
35
#......................................................................#
36
 
255 dpurdie 37
use 5.006_001;
227 dpurdie 38
use strict;
39
use warnings;
40
 
41
################################################################################
42
#   Global variables used by functions in this package
43
#   For historical reasons many of these variabeles are global
44
#
45
 
46
package FileUtils;
283 dpurdie 47
use base qw(Exporter);
361 dpurdie 48
use File::Path;
4309 dpurdie 49
use File::Spec::Functions;
283 dpurdie 50
 
227 dpurdie 51
use JatsError;
52
use Cwd;
283 dpurdie 53
our (@EXPORT, @EXPORT_OK, %EXPORT_TAGS, $VERSION);
227 dpurdie 54
 
55
$VERSION = 1.00;
56
 
57
# Symbols to autoexport (:DEFAULT tag)
58
@EXPORT = qw(   InitFileUtils
59
                Getcwd
60
                Realpath
61
                RelPath
62
                AbsPath
63
                FullPath
64
                CleanPath
65
                StripDrive
66
                StripDir
67
                StripExt
68
                StripFile
69
                StripFileExt
70
                StripDirExt
71
                CleanDirName
72
                TouchFile
73
                FileIsNewer
74
                DisplayPath
257 dpurdie 75
                TruePath
261 dpurdie 76
                FileCreate
77
                FileAppend
361 dpurdie 78
                RmDirTree
4309 dpurdie 79
                catfile
80
                catdir
227 dpurdie 81
 
82
                $ScmPathSep
261 dpurdie 83
                $ScmDirSep
227 dpurdie 84
                $Cwd
85
                $CwdDrive
86
                $ScmHost
87
            );
88
#
89
# exported package globals go here
90
#
91
our $ScmPathSep;                # Windows/Unix path seperator
261 dpurdie 92
our $ScmDirSep;                 # Windows/Unix dir sep
227 dpurdie 93
our $Cwd       ;                # Current directory ( no drive letter )
247 dpurdie 94
our $CwdFull   ;                # Current directory ( with drive letter )
227 dpurdie 95
our $CwdDrive  ;                # Current drive
96
our $ScmHost   ;                # Host Type. Unix, WIN
97
 
98
#
99
#   Internal variables
100
#
101
my  $isCygWin;                 # Running under CygWin
102
my  $isUnix;                   # Is Unix
103
 
104
#-------------------------------------------------------------------------------
105
# Function        : BEGIN
106
#
107
# Description     : Determine some values very early
108
#
109
#
110
BEGIN
111
{
112
    $ScmHost = "Unix";                                # UNIX, default
113
 
114
    Debug( "PerlHost:  $^O" );
115
    $ScmHost = "DOS"      if ($^O eq "win95");        # DOS Perl dependent
116
    $ScmHost = "WIN"      if ($^O eq "MSWin32");      # ActivePerl
117
    $ScmHost = "WIN"      if ($^O eq "cygwin");       # Cygwin
118
 
119
    $isUnix = 1 if ( $ScmHost eq "Unix"  );
255 dpurdie 120
    $isCygWin = 1 if ( $ENV{'SHELL'} || $ENV{'CYGWIN'} );
227 dpurdie 121
 
122
    $ScmPathSep = $isUnix ? ':' : ';';     # Unix / Windows
261 dpurdie 123
    $ScmDirSep = $isUnix ? '/' : '\\';     # Unix / Windows
227 dpurdie 124
}
125
 
126
#-------------------------------------------------------------------------------
127
# Function        : InitFileUtils
128
#
129
# Description     : Initialise this package
130
#                   This function should be called once the user has determined
131
#                   settled on a working directory
132
#
133
#                   The function may be called multiple times
134
#                   to allow various globals to be reset - when the user has
135
#                   changed directory
136
#
137
# Inputs          : Nothing
138
#
139
# Returns         : Nothing
140
#
141
sub InitFileUtils
142
{
143
    #
144
    #   Setup current directory and drive
145
    #
146
 
247 dpurdie 147
    $CwdFull = Getcwd();                    # Current working dir
227 dpurdie 148
 
149
    $CwdDrive = '';
247 dpurdie 150
    $CwdDrive = substr( $CwdFull, 0, 2 )    # Saved Drive letter
227 dpurdie 151
        if ( ! $isUnix );
152
 
247 dpurdie 153
    $Cwd = StripDrive( $CwdFull );          # With drive spec striped
227 dpurdie 154
 
155
    Debug ("InitFileUtils: ScmHost     : $ScmHost");
247 dpurdie 156
    Debug ("InitFileUtils: CwdFull     : $CwdFull");
227 dpurdie 157
    Debug ("InitFileUtils: Cwd         : $Cwd");
158
    Debug ("InitFileUtils: CwdDrive    : $CwdDrive");
159
    Debug ("InitFileUtils: ScmPathSep  : $ScmPathSep");
160
}
161
 
162
 
163
#-------------------------------------------------------------------------------
164
# Function        : Getcwd
165
#
166
# Description     : Retrieve current working directory
167
#
168
# Inputs          : None
169
#
170
# Returns         : The current working directory
171
#
172
# Notes           : Don't use 'pwd' program as it gets symbolic links wrong
173
#
174
sub Getcwd
175
{
176
    my $cwd = getcwd();
177
    return $cwd;
178
}
179
 
180
#-------------------------------------------------------------------------------
261 dpurdie 181
# Function        : TouchFile 
227 dpurdie 182
#
183
# Description     : touch a file
184
#                   Real use is to touch a marker file
185
#
186
# Inputs          : path        - path to the file
187
#
188
# Returns         : TRUE if an error occured in creating the file
189
#
190
sub TouchFile
191
{
192
    my ($path, $text) = @_;
193
    my $result = 0;
283 dpurdie 194
    my $tfh;
195
 
227 dpurdie 196
    Verbose ("Touching file: $path" );
197
    if ( ! -f $path )
198
    {
283 dpurdie 199
        open ($tfh, ">>", $path) || ($result = 1);
200
        close $tfh;
227 dpurdie 201
    }
202
    else
203
    {
204
 
205
        #
206
        #   Modify the file
207
        #
208
        #   Need to physically modify the file
209
        #   Need to change the 'change time' on the file. Simply setting the
210
        #   last-mod and last-access is not enough to get past WIN32
211
        #   OR 'utime()' does not work as expected
212
        #
213
        #   Read in the first character of the file, rewind and write it
214
        #   out again.
215
        #
216
        my $data;
283 dpurdie 217
        open ($tfh , "+<", $path ) || return 1;
218
        if ( read ( $tfh, $data, 1 ) )
219
        {
220
            seek  ( $tfh, 0, 0 );
221
            print $tfh $data;
227 dpurdie 222
        }
223
        else
224
        {
225
            #
226
            #   File must have been of zero length
227
            #   Delete the file and create it
228
            #
283 dpurdie 229
            close ($tfh);
227 dpurdie 230
            unlink ( $path );
283 dpurdie 231
            open ($tfh, ">>", $path) || ($result = 1);
227 dpurdie 232
        }
283 dpurdie 233
        close ($tfh);
227 dpurdie 234
    }
235
    return $result;
236
}
237
 
238
#-------------------------------------------------------------------------------
261 dpurdie 239
# Function        : FileCreate
240
#                   FileAppend
241
#                   _FileWrite
242
#
243
# Description     : Simple Text File Creation function
244
#                   Suited to the creation of small, simple text files.
245
#
246
# Inputs          : Name of the file
247
#                   Remainder are:
248
#                       Lines of data to output to the file
249
#                       Or a reference to an array of lines
250
#                       Or a mixture
251
#                   All lines will be terminated with a "\n"
252
#
253
# Returns         : Nothing
254
#
255
sub FileCreate
256
{
257
    _FileWrite ( '>', @_ );
258
}
259
 
260
sub FileAppend
261
{
262
    _FileWrite ( '>>', @_ );
263
}
264
 
265
sub _FileWrite
266
{
267
    my $mode = shift @_;
268
    my $name = shift @_;
283 dpurdie 269
    my $fh;
261 dpurdie 270
 
271
    Error ("FileCreate: No file specified") unless ( $name );
272
    Error ("FileCreate: Path is directory") if ( -d $name );
273
 
283 dpurdie 274
    open  ($fh, $mode, $name ) || Error( "Cannot create file: $name", "Reason: $!" );
261 dpurdie 275
 
276
    foreach my $entry ( @_ ) {
277
        if ( ref ($entry ) eq 'ARRAY'  ) {
283 dpurdie 278
            print $fh $_ . "\n" foreach  ( @$entry );
261 dpurdie 279
        } else {
283 dpurdie 280
            print $fh $entry . "\n"
261 dpurdie 281
        }
282
    }
283 dpurdie 283
    close $fh;
261 dpurdie 284
}
285
 
286
#-------------------------------------------------------------------------------
227 dpurdie 287
# Function        : FileIsNewer
288
#
289
# Description     : Test two files to see if the files are newer
290
#
291
# Inputs          : file1
292
#                   file2
293
#
294
# Returns         : Returns true if file1 is newer than file2 or file2 does not
295
#                   exist.
296
#
297
#                   If file 1 does not exist then it will return false
298
#
299
sub FileIsNewer
300
{
301
    my ($file1, $file2) = @_;
302
 
303
    my $f1_timestamp = (stat($file1))[9] || 0;
304
    my $f2_timestamp = (stat($file2))[9] || 0;
305
    my $result = $f1_timestamp > $f2_timestamp ? 1 : 0;
306
 
307
    Verbose2 ("FileIsNewer: TS: $f1_timestamp, File: $file1");
308
    Verbose2 ("FileIsNewer: TS: $f2_timestamp, File: $file2");
309
    Verbose2 ("FileIsNewer: $result" );
310
 
311
    return $result;
312
}
313
 
314
#-------------------------------------------------------------------------------
315
# Function        : Realpath
316
#
317
# Description     : Returns the 'real path'
318
#
319
# Inputs          : $path       - Path to process
320
#
321
# Returns         : The real path
322
#
323
sub Realpath
324
{
325
    my( $path ) = @_;
326
    my( $real, $cwd );
327
 
328
    $cwd = Getcwd();
329
    if (!chdir( $path )) {
330
        $real = "";
331
    } else {
332
        $real = Getcwd();
333
        Error ("FATAL: Realpath($path) could not restore directory ($cwd)." )
334
            unless (chdir( $cwd ));
335
    }
336
    Debug( "Realpath:   = $real ($path)" );
337
    return $real;
338
}
339
 
340
#-------------------------------------------------------------------------------
341
# Function        : Realfile
342
#
343
# Description     : Returns the 'real path'
344
#
345
# Inputs          : $path       - Path to process
346
#
347
# Returns         : The real path
348
#
349
#sub Realfile
350
#{
351
#    my( $path ) = @_;
352
#    my( $real, $cwd );
353
#
354
#    $cwd = Getcwd();
355
#    if (!chdir( $path )) {
356
#        $real = "";
357
#    } else {
358
#        $real = Getcwd();
359
#        Error ("FATAL: Realpath($path) could not restore directory ($cwd)." )
360
#            unless (chdir( $cwd ));
361
#    }
362
#    Debug( "Realpath:   = $real ($path)" );
363
#    return $real;
364
#}
365
 
366
#-------------------------------------------------------------------------------
367
# Function        : RelPath
368
#
369
# Description     : Return the relative path to the current working directory
370
#                   as provided in $Cwd
371
#
285 dpurdie 372
# Inputs          : $base       - Base directory to convert
373
#                   $here       - Optional current directory
374
#                                 $Cwd will be used if non provided
227 dpurdie 375
#
376
# Returns         : Relative path from the current directory to the base directory
377
#
378
sub RelPath
379
{
285 dpurdie 380
    my ($base, $here) = @_;
227 dpurdie 381
 
285 dpurdie 382
    $here = $Cwd unless ( defined $here );
227 dpurdie 383
    my @base = split ('/', $base );
285 dpurdie 384
    my @here = split ('/', $here );
227 dpurdie 385
    my $result;
386
 
4265 dpurdie 387
    Debug("RelPath: Here  : $here");
227 dpurdie 388
    Debug("RelPath: Source: $base");
389
 
390
    return $base unless ( $base =~ m~^/~ );
391
 
392
    #
393
    #   Remove common bits from the head of both lists
394
    #
395
    while ( $#base >= 0 && $#here >= 0 && $base[0] eq $here[0] )
396
    {
397
        shift @base;
398
        shift @here;
399
    }
400
 
401
    #
402
    #   Need to go up some directories from here and then down into base
403
    #
404
    $result = '../' x ($#here + 1);
405
    $result .= join ( '/', @base);
406
    $result = '.' unless ( $result );
407
    $result =~ s~/$~~;
408
 
409
    Debug("RelPath: Result: $result");
410
    return $result;
411
}
412
 
413
#-------------------------------------------------------------------------------
414
# Function        : AbsPath
415
#
416
# Description     : Return the absolute path to the file
417
#                   Add the current directory if the path is absolute
418
#                   Clean up xxx/.. constructs
419
#
420
#                   If an absolute path is provided then it will simply be
421
#                   cleaned up.
422
#
423
# Assumption      : Absolute paths start with a "/" and do not have a drive letter
424
#
2450 dpurdie 425
# Inputs          : $dpath      - Source file path
325 dpurdie 426
#                   $here       - Optional current directory
427
#                                 $Cwd will be used if non provided
2450 dpurdie 428
#                   $mode       - Defined: No error
429
#                                 Used during error reporting
227 dpurdie 430
#
431
# Returns         : Cleaned abs path
432
#
433
sub AbsPath
434
{
2450 dpurdie 435
    my ($dpath, $here, $mode) = @_;
227 dpurdie 436
    my @result;
437
 
438
    #
439
    #   If we have a relative path then prepend the current directory
440
    #   An absolute path is:
441
    #           /aaa/aa/aa
442
    #       or  c:/aaa/aa/aa
443
    #
325 dpurdie 444
    $here = $Cwd unless ( defined $here );
3859 dpurdie 445
    $here =~ s~^\w:~~;
325 dpurdie 446
    $dpath = $here . '/' . $dpath
3832 dpurdie 447
        unless ( $dpath =~ m~^/|\w:[/\\]~  );
227 dpurdie 448
    $dpath =~ s~//~/~g;
449
 
450
    #
451
    #   Walk the bits and remove ".." directories
452
    #       Done by pushing non-.. elements and poping last entry for .. elements.
453
    #   Have a leading "/" which is good.
454
    #
455
    foreach ( split ( '/', $dpath ) )
456
    {
457
        next if ( $_ eq '.' );
458
        unless ( $_ eq '..' )
459
        {
460
            push @result, $_;
461
        }
462
        else
463
        {
2450 dpurdie 464
            if ( $#result <= 0 )
465
            {
466
                Error ("Bad Pathname: $dpath") unless ( $mode );
467
                return $dpath;
468
            }
469
            else
470
            {
471
                pop @result;
472
            }
227 dpurdie 473
        }
474
    }
475
 
476
    #
477
    #   Create a nice directory name again.
478
    #
479
    return join ( '/', @result );
480
}
481
 
482
#-------------------------------------------------------------------------------
483
# Function        : FullPath
484
#
485
# Description     : Return the absolute path to the file - with driver letter
486
#                   Add the current directory if the path is absolute
487
#                   Clean up xxx/.. constructs
488
#
489
#                   If an absolute path is provided then it will simply be
490
#                   cleaned up.
491
#
492
# Inputs          : Source file path
325 dpurdie 493
#                   $here       - Optional current directory
494
#                                 $Cwd will be used if non provided
227 dpurdie 495
#
496
# Returns         : Cleaned abs path
497
#
498
sub FullPath
499
{
500
    my $path = AbsPath (@_ );
229 dpurdie 501
    $path = $CwdDrive . $path unless ( $path =~ m~^\w:~  );
227 dpurdie 502
    return $path;
503
}
504
 
505
#-------------------------------------------------------------------------------
257 dpurdie 506
# Function        : TruePath
507
#
508
# Description     : Returns a case correct pathname
509
#                   Really only applicable to windows, under unix it returns
510
#                   its input path.
511
#
512
#                   Maintains a cache to speed up processing
513
#
514
# Inputs          : Confused path (Absolute with a driver letter)
515
#
516
# Returns         : Case Correct Path : Windows
517
#                   Input Path : Non Windows
518
#
519
my %TruePathCache;
520
my %DirRead;
521
sub TruePath
522
{
523
    my ($path) = @_;
524
    $path =~ tr~\\/~/~s;
525
 
526
    #
527
    #   On Unix systems the path is case sensitive to start with
528
    #   Can't get it wrong - can't do anything.
529
    #
530
    return $path if ( $isUnix );
531
 
532
    #
533
    #   If the path does not exist at all then return the user input
534
    #   Assume that the user will handle this later
535
    #
536
    unless ( -e $path )
537
    {
538
        Warning ("TruePath given invalid path: $path");
539
        return $path;
540
    }
541
 
542
    #
543
    #   Look in the cache - have we seen this before
544
    #
545
    if ( exists $TruePathCache{lc($path)} )
546
    {
547
        Verbose( "TruePath Cache Hit: $path");
548
        return $TruePathCache{lc($path)};
549
    }
550
 
551
    #
552
    #   Split the directory into components
553
    #
554
    my $TrueComponent = '';
555
    my @components = split ('/', $path );
556
    foreach my $elem ( @components )
557
    {
558
        Debug ("Process: $elem in $TrueComponent");
559
        my $tag;
560
        #
561
        #   Handle driver letter
562
        #
563
        if ( $elem =~ m~^[a-zA-Z]:$~ )
564
        {
565
            $elem = uc($elem);
566
            $TrueComponent = $elem;
567
 
568
            $tag = lc($TrueComponent);
569
            $TruePathCache{$tag} = $elem;
570
            Debug ("     Add: $elem");
571
            next;
572
        }
573
 
574
        #
575
        #   Ensure that we have read in containing directory
576
        #   Note: Append / to ensure we read root directories correctly
577
        #
578
        $TrueComponent .= '/';
579
        unless ( $DirRead{ $TrueComponent }  )
580
        {
581
            Debug ("Reading: $TrueComponent");
285 dpurdie 582
            opendir (my $tp, $TrueComponent ) or Error ("Cannot open $TrueComponent");
583
            my @dirlist = readdir $tp;
584
            closedir $tp;
257 dpurdie 585
            $DirRead {$TrueComponent } = 1;
586
 
587
            #
588
            #   Add cache entries for each path in the directory
589
            #
590
            foreach my $dir ( @dirlist )
591
            {
592
                next if ( $dir eq '.' );
593
                next if ( $dir eq '..' );
594
                my $fullpath = $TrueComponent . $dir;
595
                Debug ("     Add: $fullpath");
596
                $TruePathCache{lc($fullpath)} = $fullpath;
597
            }
598
        }
599
 
600
        #
601
        #   Now that we have populated the cache with data from the directory
602
        #   we can expect to find our desired entry in the cache.
603
        #
604
        $tag = lc($TrueComponent . $elem );
605
        if ( exists $TruePathCache{ $tag } )
606
        {
607
            $TrueComponent = $TruePathCache{ $tag };
608
        }
609
        else
610
        {
611
            DebugDumpData ("Cache", \%TruePathCache);
612
            Error ("TruePath Internal error. File may have been deleted: $tag");
613
        }
614
        Debug ("Have: $TrueComponent");
615
    }
616
 
617
    Verbose ("TruePath: $TrueComponent");
618
    return $TrueComponent;
619
}
620
 
621
#-------------------------------------------------------------------------------
227 dpurdie 622
# Function        : CleanPath
623
#
624
# Description     : Cleanup a path
625
#                   Remove xxx/.. constructs
626
#
627
# Note            : Will not perform error detection on badly formed
628
#                   absolute paths.
629
#
630
# Inputs          : Source file path
631
#
632
# Returns         : Clean absolute or relative path
633
#
634
#
635
sub CleanPath
636
{
637
    my ($dpath) = @_;
638
    my @result;
639
    Debug("CleanPath: Source: $dpath");
640
 
641
    #
642
    #   Cleanup the the user input. Remove double delimiters and ensure there
643
    #   is no trailing delemiter
644
    #
245 dpurdie 645
    $dpath =~ s~/+~/~g;
227 dpurdie 646
    $dpath =~ s~/$~~g;
647
 
648
    #
649
    #   Walk the bits and remove "xxx/.." directories
650
    #
651
    foreach ( split ( '/', $dpath ) )
652
    {
653
        if ( $_ ne '..' || $#result < 0 )
654
        {
655
            push @result, $_;
656
        }
657
        else
658
        {
659
            if ( $#result >= 0 )
660
            {
283 dpurdie 661
                my $last_dir = pop @result;
662
                push (@result, $last_dir, $_)
663
                    if ($last_dir eq '..' || $last_dir eq '');
227 dpurdie 664
            }
665
        }
666
    }
667
 
668
    my $result = join ( '/', @result );
669
    Debug("CleanPath: Result: $result");
670
    return $result;
671
}
672
 
673
#-------------------------------------------------------------------------------
674
# Function        : StripDrive
675
#
676
# Description     : Strip any leading drive speification
677
#
678
# Inputs          : $fname          - Path to process
679
#
680
# Returns         : Path, with drive letter stripped
681
#                   Will do nothing on Unix systems
682
#
683
sub StripDrive
684
{
685
    my( $fname ) = @_;                          # Full name
686
 
687
    $fname =~ s/^[A-Za-z]://g                  # leading drive spec
688
        if ( ! $isUnix );
689
    return $fname;
690
}
691
 
692
#-------------------------------------------------------------------------------
693
# Function        : StripDir
694
#
695
# Description     : Strip directory (returns file, including extension)
696
#
697
# Inputs          : $fname          - Path to process
698
#
699
# Returns         : filename + extension
700
#
701
sub StripDir
702
{
703
    my( $fname ) = @_;                          # Full name
704
    my( $idx );
705
 
706
    if (($idx = rindex($fname, "/")) == -1) {
707
        if (($idx = rindex($fname, "\\")) == -1) {
708
            return $fname;                      # No path ...
709
        }
710
    }
711
    return substr($fname, $idx+1, 512);
712
}
713
 
714
#-------------------------------------------------------------------------------
715
# Function        : StripExt
716
#
717
# Description     : Strip extension (return basename, plus any dir)
718
#
719
# Inputs          : $fname          - Path to process
720
#
721
# Returns         : basename, plus any dir
722
#                   Simply removes one extension
723
#
724
sub StripExt
725
{
726
    my( $fname ) = @_;
727
 
728
    $fname =~ s/(\S+)(\.\S+)/$1/;               # strip out trailing '.<ext>'
729
    return ($fname);
730
}
731
 
732
#-------------------------------------------------------------------------------
733
# Function        : StripFile
734
#
735
# Description     : Strip filename (returns extension)
736
#
737
# Inputs          : $fname          - Path to process
738
#
739
# Returns         : extension
740
#                   Will return an empty string if the input does not have an
741
#                   extension.
742
#
743
sub StripFile
744
{
745
    my( $fname ) = @_;
746
 
747
    $fname =~ s/(\S+)(\.\S+)/$2/;               # Strip out items before '.<ext>'
748
    return ("")                                 # No extension
749
        if ("$fname" eq "@_");
750
    return ($fname);
751
}
752
 
753
#-------------------------------------------------------------------------------
754
# Function        : StripFileExt
755
#
756
# Description     : Strip filename and ext (returns dir)
757
#
758
# Inputs          : $fname          - Path to process
759
#
760
# Returns         : Directory of a file path
761
#
762
 
763
 
764
#   StripFileExt( path ) ---
765
#       Strip filename and ext (returns dir)
766
#..
767
 
768
sub StripFileExt
769
{
770
    my( $fname ) = @_;                          # Full name
771
    my( $idx );
772
    my $dir;
773
 
774
    if (($idx = rindex($fname, "/")) == -1) {
775
        if (($idx = rindex($fname, "\\")) == -1) {
776
            return "";                          # No path ...
777
        }
778
    }
779
 
780
    return substr($fname, 0, $idx);
781
}
782
 
783
#-------------------------------------------------------------------------------
784
# Function        : StripDirExt
785
#
786
# Description     : Strip the directory and extension from a file
787
#                   Returning the base file. Optionally replace the extension
788
#                   with a user value
789
#
790
# Inputs          : Full path name
791
#                   Optional extension to be replaced
792
#
793
# Returns         :
794
#
795
sub StripDirExt
796
{
797
    my ($fname, $ext ) = (@_, '');
798
    $fname =~ s~.*[/\\]~~;                      # Strip directory
799
    $fname =~ s/\.[^.]+$/$ext/;
800
    return $fname;
801
}
802
 
803
 
804
#-------------------------------------------------------------------------------
805
# Function        : CleanDirName
806
#
807
# Description     : Clean up a directory path string
808
#                       1) Remove multiple //
809
#                       2) Remove multiple /./
810
#                       2) Remove leading ./
811
#                       3) Remove trailing /
812
#                       4) Remove /xxxx/../
813
#
814
# Inputs          : A dirty directory path
815
#
816
# Returns         : A clean directory path
817
#
818
sub CleanDirName
819
{
820
    my ( $dir ) = @_;
821
    $dir =~ s~//~/~g;                   # Kill multiple //
822
    $dir =~ s~/\./~/~g;                 # Kill multiple /./
823
    $dir =~ s~^\./~~;                   # Kill leading ./
824
    $dir = '.' unless ( $dir );         # Ensure we have a path
825
 
826
    #
827
    #   Remove /xxxxx/../ bits
828
    #
829
    unless ( $dir =~ m~^\.\./~  )
830
    {
831
        while ( $dir =~ s~
832
                        (^|/)               # Allow for stings that may not start with a /
833
                        [^/]+/\.\.          # xxxxx/.., where xxxx is anything other than a /
834
                        (/|$)               # Allow for strings ending with /..
835
                        ~$1~x               # Replace with the start character
836
              )
837
        {
838
            last if ( $dir =~ m~^\.\./~ );  # Too far. Stop now !
839
        }
840
    }
841
 
842
    $dir =~ s~/$~~;                     # No trailing /
843
    $dir =~ s~/\.$~~;                   # No trailing /.
844
    return $dir;
845
}
846
 
847
#-------------------------------------------------------------------------------
848
# Function        : DisplayPath
849
#
850
# Description     : Cleanup a path for display purposes
851
#                   Useful under windows to provide paths with \ that can be
852
#                   cut and pasted.
853
#
854
#                   If cygwin is located in the environment, then this function
855
#                   will not convert / to \.
856
#
857
# Inputs          : A path to modify
858
#
859
# Returns         : Modified path
860
#
861
sub DisplayPath
862
{
863
    my ($path) = @_;
864
    if ( ! $isUnix && ! $isCygWin )
865
    {
866
        $path =~ s~/~\\~g;
867
    }
868
    return $path;
869
}
870
 
361 dpurdie 871
#-------------------------------------------------------------------------------
872
# Function        : RmDirTree
873
#
874
# Description     : Delete a directory tree
875
#                   Really delete it. Allow for users to remove directory
876
#                   without search permissions under unix.
877
#
878
#                   Can also delete a file
879
#
2439 dpurdie 880
#                   This function has a bit of history
881
#                   I've tried the Perl rmtree(), but there were situations
882
#                   where the OS(WIN32) says the directory exists after its been
883
#                   deleted. Also the Jats-Win32 version of chmod would issue
884
#                   messages if it couldn't find the dir/file.
885
#
886
#                   The solution is to use JATS' own JatsFileUtil utility
887
#                   This appears to do the right thing
888
#
361 dpurdie 889
# Inputs          : $path                   - Path to directory
4344 dpurdie 890
#                                             May be empty, in which case nothing is done
361 dpurdie 891
#
892
# Returns         : 1                       - Still there
893
#
894
sub RmDirTree
895
{
896
    my ($path) = @_;
4344 dpurdie 897
    return 0 unless $path;
361 dpurdie 898
    if ( -e $path )
899
    {
2439 dpurdie 900
        #  Need to know if its a file or a directory
901
        #
902
        my $mode = ( -d $path ) ? 'T' : 'r';
903
 
904
        #
905
        #   Use JATS's own utility to do the hardwork
906
        #   Used as it address a number of issues
907
        #
908
        #   Merge in verbosity
909
        #
910
        system ("$ENV{GBE_BIN}/JatsFileUtil", $mode . $::ScmVerbose, '', $path );
911
 
912
        #
913
        #   Shouldn't happen but ...
914
        #   If the path still exists try another (one this has known problems)
915
        #
916
        if ( -e $path )
917
        {
918
            Verbose3 ("RmDirTree: Directory still exists. Change permissions: $path");
919
            system ("$ENV{GBE_BIN}/chmod", '-R', 'u+wrx', $path);
920
            rmtree( $path );
921
        }
361 dpurdie 922
    }
923
    return ( -e $path );
924
}
925
 
227 dpurdie 926
1;
927
 
928