Subversion Repositories DevTools

Rev

Rev 391 | 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
#
422
# Inputs          : Source file path
325 dpurdie 423
#                   $here       - Optional current directory
424
#                                 $Cwd will be used if non provided
227 dpurdie 425
#
426
# Returns         : Cleaned abs path
427
#
428
sub AbsPath
429
{
325 dpurdie 430
    my ($dpath, $here) = @_;
227 dpurdie 431
    my @result;
432
 
433
    #
434
    #   If we have a relative path then prepend the current directory
435
    #   An absolute path is:
436
    #           /aaa/aa/aa
437
    #       or  c:/aaa/aa/aa
438
    #
325 dpurdie 439
    $here = $Cwd unless ( defined $here );
440
    $dpath = $here . '/' . $dpath
227 dpurdie 441
        unless ( $dpath =~ m~^/|\w:/~  );
442
    $dpath =~ s~//~/~g;
443
 
444
    #
445
    #   Walk the bits and remove ".." directories
446
    #       Done by pushing non-.. elements and poping last entry for .. elements.
447
    #   Have a leading "/" which is good.
448
    #
449
    foreach ( split ( '/', $dpath ) )
450
    {
451
        next if ( $_ eq '.' );
452
        unless ( $_ eq '..' )
453
        {
454
            push @result, $_;
455
        }
456
        else
457
        {
458
            Error ("Bad Pathname: $dpath")
459
                if ( $#result <= 0 );
460
            pop @result;
461
        }
462
    }
463
 
464
    #
465
    #   Create a nice directory name again.
466
    #
467
    return join ( '/', @result );
468
}
469
 
470
#-------------------------------------------------------------------------------
471
# Function        : FullPath
472
#
473
# Description     : Return the absolute path to the file - with driver letter
474
#                   Add the current directory if the path is absolute
475
#                   Clean up xxx/.. constructs
476
#
477
#                   If an absolute path is provided then it will simply be
478
#                   cleaned up.
479
#
480
# Inputs          : Source file path
325 dpurdie 481
#                   $here       - Optional current directory
482
#                                 $Cwd will be used if non provided
227 dpurdie 483
#
484
# Returns         : Cleaned abs path
485
#
486
sub FullPath
487
{
488
    my $path = AbsPath (@_ );
229 dpurdie 489
    $path = $CwdDrive . $path unless ( $path =~ m~^\w:~  );
227 dpurdie 490
    return $path;
491
}
492
 
493
#-------------------------------------------------------------------------------
257 dpurdie 494
# Function        : TruePath
495
#
496
# Description     : Returns a case correct pathname
497
#                   Really only applicable to windows, under unix it returns
498
#                   its input path.
499
#
500
#                   Maintains a cache to speed up processing
501
#
502
# Inputs          : Confused path (Absolute with a driver letter)
503
#
504
# Returns         : Case Correct Path : Windows
505
#                   Input Path : Non Windows
506
#
507
my %TruePathCache;
508
my %DirRead;
509
sub TruePath
510
{
511
    my ($path) = @_;
512
    $path =~ tr~\\/~/~s;
513
 
514
    #
515
    #   On Unix systems the path is case sensitive to start with
516
    #   Can't get it wrong - can't do anything.
517
    #
518
    return $path if ( $isUnix );
519
 
520
    #
521
    #   If the path does not exist at all then return the user input
522
    #   Assume that the user will handle this later
523
    #
524
    unless ( -e $path )
525
    {
526
        Warning ("TruePath given invalid path: $path");
527
        return $path;
528
    }
529
 
530
    #
531
    #   Look in the cache - have we seen this before
532
    #
533
    if ( exists $TruePathCache{lc($path)} )
534
    {
535
        Verbose( "TruePath Cache Hit: $path");
536
        return $TruePathCache{lc($path)};
537
    }
538
 
539
    #
540
    #   Split the directory into components
541
    #
542
    my $TrueComponent = '';
543
    my @components = split ('/', $path );
544
    foreach my $elem ( @components )
545
    {
546
        Debug ("Process: $elem in $TrueComponent");
547
        my $tag;
548
        #
549
        #   Handle driver letter
550
        #
551
        if ( $elem =~ m~^[a-zA-Z]:$~ )
552
        {
553
            $elem = uc($elem);
554
            $TrueComponent = $elem;
555
 
556
            $tag = lc($TrueComponent);
557
            $TruePathCache{$tag} = $elem;
558
            Debug ("     Add: $elem");
559
            next;
560
        }
561
 
562
        #
563
        #   Ensure that we have read in containing directory
564
        #   Note: Append / to ensure we read root directories correctly
565
        #
566
        $TrueComponent .= '/';
567
        unless ( $DirRead{ $TrueComponent }  )
568
        {
569
            Debug ("Reading: $TrueComponent");
285 dpurdie 570
            opendir (my $tp, $TrueComponent ) or Error ("Cannot open $TrueComponent");
571
            my @dirlist = readdir $tp;
572
            closedir $tp;
257 dpurdie 573
            $DirRead {$TrueComponent } = 1;
574
 
575
            #
576
            #   Add cache entries for each path in the directory
577
            #
578
            foreach my $dir ( @dirlist )
579
            {
580
                next if ( $dir eq '.' );
581
                next if ( $dir eq '..' );
582
                my $fullpath = $TrueComponent . $dir;
583
                Debug ("     Add: $fullpath");
584
                $TruePathCache{lc($fullpath)} = $fullpath;
585
            }
586
        }
587
 
588
        #
589
        #   Now that we have populated the cache with data from the directory
590
        #   we can expect to find our desired entry in the cache.
591
        #
592
        $tag = lc($TrueComponent . $elem );
593
        if ( exists $TruePathCache{ $tag } )
594
        {
595
            $TrueComponent = $TruePathCache{ $tag };
596
        }
597
        else
598
        {
599
            DebugDumpData ("Cache", \%TruePathCache);
600
            Error ("TruePath Internal error. File may have been deleted: $tag");
601
        }
602
        Debug ("Have: $TrueComponent");
603
    }
604
 
605
    Verbose ("TruePath: $TrueComponent");
606
    return $TrueComponent;
607
}
608
 
609
#-------------------------------------------------------------------------------
227 dpurdie 610
# Function        : CleanPath
611
#
612
# Description     : Cleanup a path
613
#                   Remove xxx/.. constructs
614
#
615
# Note            : Will not perform error detection on badly formed
616
#                   absolute paths.
617
#
618
# Inputs          : Source file path
619
#
620
# Returns         : Clean absolute or relative path
621
#
622
#
623
sub CleanPath
624
{
625
    my ($dpath) = @_;
626
    my @result;
627
    Debug("CleanPath: Source: $dpath");
628
 
629
    #
630
    #   Cleanup the the user input. Remove double delimiters and ensure there
631
    #   is no trailing delemiter
632
    #
245 dpurdie 633
    $dpath =~ s~/+~/~g;
227 dpurdie 634
    $dpath =~ s~/$~~g;
635
 
636
    #
637
    #   Walk the bits and remove "xxx/.." directories
638
    #
639
    foreach ( split ( '/', $dpath ) )
640
    {
641
        if ( $_ ne '..' || $#result < 0 )
642
        {
643
            push @result, $_;
644
        }
645
        else
646
        {
647
            if ( $#result >= 0 )
648
            {
283 dpurdie 649
                my $last_dir = pop @result;
650
                push (@result, $last_dir, $_)
651
                    if ($last_dir eq '..' || $last_dir eq '');
227 dpurdie 652
            }
653
        }
654
    }
655
 
656
    my $result = join ( '/', @result );
657
    Debug("CleanPath: Result: $result");
658
    return $result;
659
}
660
 
661
#-------------------------------------------------------------------------------
662
# Function        : StripDrive
663
#
664
# Description     : Strip any leading drive speification
665
#
666
# Inputs          : $fname          - Path to process
667
#
668
# Returns         : Path, with drive letter stripped
669
#                   Will do nothing on Unix systems
670
#
671
sub StripDrive
672
{
673
    my( $fname ) = @_;                          # Full name
674
 
675
    $fname =~ s/^[A-Za-z]://g                  # leading drive spec
676
        if ( ! $isUnix );
677
    return $fname;
678
}
679
 
680
#-------------------------------------------------------------------------------
681
# Function        : StripDir
682
#
683
# Description     : Strip directory (returns file, including extension)
684
#
685
# Inputs          : $fname          - Path to process
686
#
687
# Returns         : filename + extension
688
#
689
sub StripDir
690
{
691
    my( $fname ) = @_;                          # Full name
692
    my( $idx );
693
 
694
    if (($idx = rindex($fname, "/")) == -1) {
695
        if (($idx = rindex($fname, "\\")) == -1) {
696
            return $fname;                      # No path ...
697
        }
698
    }
699
    return substr($fname, $idx+1, 512);
700
}
701
 
702
#-------------------------------------------------------------------------------
703
# Function        : StripExt
704
#
705
# Description     : Strip extension (return basename, plus any dir)
706
#
707
# Inputs          : $fname          - Path to process
708
#
709
# Returns         : basename, plus any dir
710
#                   Simply removes one extension
711
#
712
sub StripExt
713
{
714
    my( $fname ) = @_;
715
 
716
    $fname =~ s/(\S+)(\.\S+)/$1/;               # strip out trailing '.<ext>'
717
    return ($fname);
718
}
719
 
720
#-------------------------------------------------------------------------------
721
# Function        : StripFile
722
#
723
# Description     : Strip filename (returns extension)
724
#
725
# Inputs          : $fname          - Path to process
726
#
727
# Returns         : extension
728
#                   Will return an empty string if the input does not have an
729
#                   extension.
730
#
731
sub StripFile
732
{
733
    my( $fname ) = @_;
734
 
735
    $fname =~ s/(\S+)(\.\S+)/$2/;               # Strip out items before '.<ext>'
736
    return ("")                                 # No extension
737
        if ("$fname" eq "@_");
738
    return ($fname);
739
}
740
 
741
#-------------------------------------------------------------------------------
742
# Function        : StripFileExt
743
#
744
# Description     : Strip filename and ext (returns dir)
745
#
746
# Inputs          : $fname          - Path to process
747
#
748
# Returns         : Directory of a file path
749
#
750
 
751
 
752
#   StripFileExt( path ) ---
753
#       Strip filename and ext (returns dir)
754
#..
755
 
756
sub StripFileExt
757
{
758
    my( $fname ) = @_;                          # Full name
759
    my( $idx );
760
    my $dir;
761
 
762
    if (($idx = rindex($fname, "/")) == -1) {
763
        if (($idx = rindex($fname, "\\")) == -1) {
764
            return "";                          # No path ...
765
        }
766
    }
767
 
768
    return substr($fname, 0, $idx);
769
}
770
 
771
#-------------------------------------------------------------------------------
772
# Function        : StripDirExt
773
#
774
# Description     : Strip the directory and extension from a file
775
#                   Returning the base file. Optionally replace the extension
776
#                   with a user value
777
#
778
# Inputs          : Full path name
779
#                   Optional extension to be replaced
780
#
781
# Returns         :
782
#
783
sub StripDirExt
784
{
785
    my ($fname, $ext ) = (@_, '');
786
    $fname =~ s~.*[/\\]~~;                      # Strip directory
787
    $fname =~ s/\.[^.]+$/$ext/;
788
    return $fname;
789
}
790
 
791
 
792
#-------------------------------------------------------------------------------
793
# Function        : CleanDirName
794
#
795
# Description     : Clean up a directory path string
796
#                       1) Remove multiple //
797
#                       2) Remove multiple /./
798
#                       2) Remove leading ./
799
#                       3) Remove trailing /
800
#                       4) Remove /xxxx/../
801
#
802
# Inputs          : A dirty directory path
803
#
804
# Returns         : A clean directory path
805
#
806
sub CleanDirName
807
{
808
    my ( $dir ) = @_;
809
    $dir =~ s~//~/~g;                   # Kill multiple //
810
    $dir =~ s~/\./~/~g;                 # Kill multiple /./
811
    $dir =~ s~^\./~~;                   # Kill leading ./
812
    $dir = '.' unless ( $dir );         # Ensure we have a path
813
 
814
    #
815
    #   Remove /xxxxx/../ bits
816
    #
817
    unless ( $dir =~ m~^\.\./~  )
818
    {
819
        while ( $dir =~ s~
820
                        (^|/)               # Allow for stings that may not start with a /
821
                        [^/]+/\.\.          # xxxxx/.., where xxxx is anything other than a /
822
                        (/|$)               # Allow for strings ending with /..
823
                        ~$1~x               # Replace with the start character
824
              )
825
        {
826
            last if ( $dir =~ m~^\.\./~ );  # Too far. Stop now !
827
        }
828
    }
829
 
830
    $dir =~ s~/$~~;                     # No trailing /
831
    $dir =~ s~/\.$~~;                   # No trailing /.
832
    return $dir;
833
}
834
 
835
#-------------------------------------------------------------------------------
836
# Function        : DisplayPath
837
#
838
# Description     : Cleanup a path for display purposes
839
#                   Useful under windows to provide paths with \ that can be
840
#                   cut and pasted.
841
#
842
#                   If cygwin is located in the environment, then this function
843
#                   will not convert / to \.
844
#
845
# Inputs          : A path to modify
846
#
847
# Returns         : Modified path
848
#
849
sub DisplayPath
850
{
851
    my ($path) = @_;
852
    if ( ! $isUnix && ! $isCygWin )
853
    {
854
        $path =~ s~/~\\~g;
855
    }
856
    return $path;
857
}
858
 
361 dpurdie 859
#-------------------------------------------------------------------------------
860
# Function        : RmDirTree
861
#
862
# Description     : Delete a directory tree
863
#                   Really delete it. Allow for users to remove directory
864
#                   without search permissions under unix.
865
#
866
#                   Can also delete a file
867
#
2438 dpurdie 868
#                   This function has a bit of history
869
#                   I've tried the Perl rmtree(), but there were situations
870
#                   where the OS(WIN32) says the directory exists after its been
871
#                   deleted. Also the Jats-Win32 version of chmod would issue
872
#                   messages if it couldn't find the dir/file.
873
#
874
#                   The solution is to use JATS' own JatsFileUtil utility
875
#                   This appears to do the right thing
876
#
361 dpurdie 877
# Inputs          : $path                   - Path to directory
878
#
879
# Returns         : 1                       - Still there
880
#
881
sub RmDirTree
882
{
883
    my ($path) = @_;
884
    if ( -e $path )
885
    {
2438 dpurdie 886
        #  Need to know if its a file or a directory
887
        #
888
        my $mode = ( -d $path ) ? 'T' : 'r';
889
 
890
        #
891
        #   Use JATS's own utility to do the hardwork
892
        #   Used as it address a number of issues
893
        #
894
        #   Merge in verbosity
895
        #
896
        system ("$ENV{GBE_BIN}/JatsFileUtil", $mode . $::ScmVerbose, '', $path );
897
 
898
        #
899
        #   Shouldn't happen but ...
900
        #   If the path still exists try another (one this has known problems)
901
        #
902
        if ( -e $path )
903
        {
904
            Verbose3 ("RmDirTree: Directory still exists. Change permissions: $path");
905
            system ("$ENV{GBE_BIN}/chmod", '-R', 'u+wrx', $path);
906
            rmtree( $path );
907
        }
361 dpurdie 908
    }
909
    return ( -e $path );
910
}
911
 
227 dpurdie 912
1;
913
 
914