Subversion Repositories DevTools

Rev

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