Merge pull request #228 from DOCGroup/jwillemsen-patch-1
[MPC.git] / modules / DirectoryManager.pm
blobbdc231512bd6da7322809ba02de37380614a03fd
1 package DirectoryManager;
3 # ************************************************************
4 # Description : This module provides directory related methods
5 # Author : Chad Elliott
6 # Create Date : 5/13/2004
7 # ************************************************************
9 # ************************************************************
10 # Pragmas
11 # ************************************************************
13 use strict;
14 use File::Spec;
15 use File::Basename;
17 # ************************************************************
18 # Data Section
19 # ************************************************************
21 my $onVMS = ($^O eq 'VMS');
22 my $case_insensitive = File::Spec->case_tolerant();
23 my $cwd = Cwd::getcwd();
24 if ($^O eq 'cygwin' && $cwd !~ /[A-Za-z]:/) {
25 my $cyg = `cygpath -w $cwd`;
26 if (defined $cyg) {
27 $cyg =~ s/\\/\//g;
28 chop($cwd = $cyg);
30 $case_insensitive = 1;
32 elsif ($^O eq 'msys' && $cwd !~ /[A-Za-z]:/) {
33 my $mp = Win32::GetCwd();
34 if (defined $mp) {
35 $mp =~ s/\\/\//g;
36 $cwd = $mp;
39 elsif ($onVMS) {
40 $cwd = VMS::Filespec::unixify($cwd);
41 $cwd =~ s!/$!!g;
43 my $start = $cwd;
45 # ************************************************************
46 # Subroutine Section
47 # ************************************************************
49 sub cd {
50 my($self, $dir) = @_;
51 my $status = chdir($dir);
53 if ($status && $dir ne '.') {
54 ## First strip out any /./ or ./ or /.
55 $dir =~ s/\/\.\//\//g;
56 $dir =~ s/^\.\///;
57 $dir =~ s/\/\.$//;
59 ## If the new directory contains a relative directory
60 ## then we just get the real working directory
61 if (index($dir, '..') >= 0) {
62 $cwd = Cwd::getcwd();
63 if ($^O eq 'cygwin' && $cwd !~ /[A-Za-z]:/) {
64 ## We're using Cygwin perl, use cygpath to get the windows path
65 ## and then fix up the slashes.
66 my $cyg = `cygpath -w $cwd`;
67 if (defined $cyg) {
68 $cyg =~ s/\\/\//g;
69 chop($cwd = $cyg);
72 elsif ($^O eq 'msys' && $cwd !~ /[A-Za-z]:/) {
73 ## We're using Mingw32 perl, use Win32::GetCwd() to get the windows
74 ## path and then fix up the slashes.
75 my $mp = Win32::GetCwd();
76 if (defined $mp) {
77 $mp =~ s/\\/\//g;
78 $cwd = $mp;
81 elsif ($onVMS) {
82 ## On VMS, we need to get the UNIX style path and remove the
83 ## trailing slash.
84 $cwd = VMS::Filespec::unixify($cwd);
85 $cwd =~ s!/$!!g;
88 else {
89 if ($dir =~ /^(\/|[a-z]:)/i) {
90 ## It was a full path, just store it.
91 $cwd = $dir;
93 else {
94 ## This portion was relative, add it onto the current working
95 ## directory.
96 $cwd .= "/$dir";
100 return $status;
104 sub abs_path {
105 my($self, $path) = @_;
107 ## When needing a full path, it's usually because the build system requires
108 ## it. If that's the case, it is unlikely to understand cygwin or mingw32
109 ## paths. For these, we will return the full path for Win32 specifically.
110 return Win32::GetFullPathName($path) if ($^O eq 'cygwin' || $^O eq 'msys');
112 ## For all others, we will just use Cwd::abs_path
113 return Cwd::abs_path($path);
117 sub getcwd {
118 #my $self = shift;
119 return $cwd;
123 sub getstartdir {
124 #my $self = shift;
125 return $start;
129 sub mpc_basename {
130 #my $self = $_[0];
131 #my $file = $_[1];
132 return substr($_[1], rindex($_[1], '/') + 1);
136 sub mpc_dirname {
137 my($self, $dir) = @_;
139 ## The dirname() on VMS doesn't work as we expect it to.
140 if ($onVMS) {
141 ## If the directory contains multiple parts, we need to get the
142 ## dirname in a UNIX style format and then remove the slash from the
143 ## end.
144 if (index($dir, '/') >= 0) {
145 $dir = VMS::Filespec::unixify(dirname($dir));
146 $dir =~ s!/$!!g;
147 return $dir;
149 else {
150 ## There's no directory portion, so just return '.'
151 return '.';
154 else {
155 ## Get the directory portion of the original directory or file path.
156 $dir = dirname($dir);
158 ## If the result is just a drive specification, we need to append a
159 ## slash to the end of the path so that cygwin perl can use this
160 ## return value within a chdir() call.
161 $dir .= '/' if ($dir =~ /^[a-z]:$/i);
163 return $dir;
168 sub mpc_glob {
169 my($self, $pattern) = @_;
171 ## glob() provided by OpenVMS does not understand [] within
172 ## the pattern. So, we implement our own through recursive calls
173 ## to mpc_glob().
174 if ($onVMS && $pattern =~ /(.*)\[([^\]]+)\](.*)/) {
175 my @files;
176 my($pre, $mid, $post) = ($1, $2, $3);
177 for(my $i = 0; $i < length($mid); $i++) {
178 StringProcessor::merge(\@files,
179 [$self->mpc_glob($pre . substr($mid, $i, 1)
180 . $post)]);
182 return @files;
185 ## Otherwise, we just return the globbed pattern.
186 return glob($pattern);
190 sub onVMS {
191 return $onVMS;
195 sub path_is_relative {
196 ## To determine if the path is relative, we just determine if it is not
197 ## an absolute path.
198 #my($self, $path) = @_;
199 return (index($_[1], '/') != 0 && $_[1] !~ /^[A-Z]:[\/\\]/i && $_[1] !~ /^\$\(\w+\)/);
202 sub path_to_relative {
203 my($self, $check, $path) = @_;
205 ## See if it's already relative. If it is, there's nothing to do.
206 if ($path !~ s/^.[\/]+// && !$self->path_is_relative($path)) {
207 ## See how many times we have to chop off a directory until we find that
208 ## the provided path contains part of the current working directory.
209 my $dircount = 0;
210 while($check ne '.' && index($path, $check) != 0) {
211 $dircount++;
212 $check = $self->mpc_dirname($check);
215 ## If we didn't go all the way back up the current working directory, we
216 ## can create a relative path from it based on the number of directories
217 ## we removed above.
218 if ($check ne '.') {
219 $path = ('../' x $dircount) . substr($path, length($check) + 1);
223 return $path;
226 # ************************************************************
227 # Virtual Methods To Be Overridden
228 # ************************************************************
230 sub translate_directory {
231 my($self, $dir) = @_;
233 ## Remove the current working directory from $dir (if it is contained)
234 my $cwd = $self->getcwd();
235 $cwd =~ s/\//\\/g if ($self->convert_slashes());
236 if (index($dir, $cwd) == 0) {
237 my $cwdl = length($cwd);
238 return '.' if (length($dir) == $cwdl);
239 $dir = substr($dir, $cwdl + 1);
242 ## Translate .. to $dd
243 if (index($dir, '..') >= 0) {
244 my $dd = 'dotdot';
245 $dir =~ s/^\.\.([\/\\])/$dd$1/;
246 $dir =~ s/([\/\\])\.\.$/$1$dd/;
247 $dir =~ s/([\/\\])\.\.(?=[\/\\])/$1$dd$2/g;
248 $dir =~ s/^\.\.$/$dd/;
251 return $dir;
255 sub convert_slashes {
256 #my $self = shift;
257 return 0;
261 sub case_insensitive {
262 #my $self = shift;
263 return $case_insensitive;