Subversion Repositories DevTools

Rev

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