fix osname problem
[kakapo:kakapo.git] / src / Path.nqp
1 # Copyright (C) 2010, Austin Hastings. See accompanying LICENSE file, or
2 # http://www.opensource.org/licenses/artistic-license-2.0.php for license.
3
4 # Abstract representation of filesystem entries.
5 class Path;
6
7 INIT {
8         our %_Osname_class_map := Hash.new(
9                 :DEFAULT(       Path::Unix),
10                 :linux( Path::Unix),
11         );
12 }
13
14 method get_osname_map() {
15         our %_Osname_class_map;
16 }
17
18 method _init_obj(*@pos, *%named) {
19         my %map := self.get_osname_map();
20         my $osname := 'DEFAULT';
21         try {
22             my $tmp := %*VM<osname>;
23             $osname := $tmp if %map.contains: $tmp;
24
25             # if not, whatever. Keep it at DEFAULT
26             CATCH { }
27         }
28
29         my $class := %map{$osname};
30         my $obj := $class.new( |@pos, |%named );        # NB: Returns a different type than Path.
31         $obj;
32 }
33
34 class Path::Unix
35         is Path;
36
37 has     @!elements;
38 has     $!filesystem;
39 has     $!volume;
40 has     $!is_relative;
41 has     $!initialized;
42
43 INIT {
44         auto_accessors(:private);
45
46         Parrot::define_multisub( <append>, :method, :starting_with( <append> ));
47         Parrot::define_multisub( <append>, [ Path::Unix::append__String ], :method, :signatures( [ < _ string > ]));
48 }
49
50 our method absolute($bool = 1)          { $!is_relative := ! $bool; }
51
52 my method append__ANY($element, :$dynamic) {
53         die( "Can't use a ", pir::typeof__SP($element), " as part of a Path - use a String or Path instead.");
54 }
55
56 my method append__Path($element, :$dynamic = 0) {
57
58         unless $!initialized {
59                 $!initialized := $element.initialized;
60                 $!is_relative := $element.is_relative;
61                 $!volume := $element.volume;
62         }
63
64         $dynamic
65                 ?? @!elements.push: $element
66                 !! @!elements.append( $element.elements );
67
68         self;
69 }
70
71 # Scenario:  "x" -> [ 'x' ], :relative
72 # Scenario: "/x" -> [ '', 'x' ] -> ['x'] :absolute
73 # Scenario: "x/" -> [ 'x', '' ] -> [ 'x' ] :relative
74 # Scenario: "" -> [ '' ] -> [ ] :absolute (confused with /)
75
76 my method append__String($element, :$dynamic = 0) {
77         die( "Cannot use :dynamic with a String, only a Path argument" )
78                 if $dynamic;
79
80         my @parts := $element.split: self.directory_separator;
81
82         # If this $element is first one, it determines $!is_relative.
83         unless $!initialized {
84                 $!initialized := 1;
85                 if @parts[0] eq '' {
86                         @parts.shift;
87                         $!is_relative := 0;
88                 }
89                 else {
90                         $!is_relative := 1;
91                 }
92         }
93
94         # Take care of trailing /:  "foo/" -> [ 'foo', '' ]
95         my $last := @parts.pop;
96
97         @parts.push: $last
98                 unless $last eq '';
99
100         @!elements.append: @parts;
101
102         self;
103 }
104
105 our method directory_separator()        { '/'; }
106
107 our method elements() {
108         my @result := [ ];
109
110         for @!elements -> $elt {
111                 if $elt.isa: <String> {
112                         @result.push: $elt;
113                 }
114                 else {
115                         @result.append: $elt.elements;
116                 }
117         }
118
119         @result;
120 }
121
122 our method exists()                     { $!filesystem.exists(self); }
123
124 # NB: This is called by the 'get_string' vtable provided by P6object
125 method get_string() {
126         my $slash := self.directory_separator;
127
128         self.is_absolute
129                 ?? $!volume ~ $slash ~ self.elements.join: $slash
130                 !! self.elements.join: $slash;
131 }
132
133 my method _init_obj(*@parts, :$dynamic = 0, *%named) {
134         @!elements := @!elements;
135         $!filesystem := $*FileSystem;
136         $!initialized := 0;
137         $!is_relative := 1;
138         $!volume := '';
139
140         self._init_args(|%named);
141
142         for @parts -> $part {
143                 self.append($part, :dynamic($dynamic && $part.isa: 'Path'));
144         }
145
146         self;
147 }
148
149 our method is_absolute() {
150         if @!elements.elems == 0 || @!elements[0].isa('String') {
151                 ! $!is_relative;
152         }
153         else {
154                 @!elements[0].is_absolute;
155         }
156 }
157
158 our method is_relative() {
159         if @!elements.elems == 0 || @!elements[0].isa('String') {
160                 $!is_relative;
161         }
162         else {
163                 @!elements[0].is_relative;
164         }
165 }
166
167 our method relative($bool = 1)          { $!is_relative := $bool; }
168
169 ############## Stuff that is delegated to filesystem
170 #~ our method is_directory()    { self.exists && self._stat_query(2); }
171 #~ our method is_device()       { self.exists && self._stat_query(3); }
172 #~ our method is_file()         { self.exists && get_file().is_file(self._complete); }
173 #~ our method is_link()         { self.exists && get_file.is_link(self._complete); }
174 #~ our method modify_time()     { self._stat_query(6); }
175 #~ our method size()            { self._stat_query(1); }
176 #~ our method access_time()     { self._stat_query(5); }
177 #~ our method backup_time()     { self._stat_query(8); }
178 #~ our method change_time()     { self._stat_query(7); }
179 #~ our method create_time()     { self._stat_query(4); }
180 #~ my method _stat_query($index) {      # $index
181         #~ pir::stat__ISI(self._complete, $index);
182 #~ }
183 #~ our method gid()             { self._stat_query(10); }
184 #~ our method uid()             { self._stat_query(9); }
185 our method open(*%named) {
186         $!filesystem.open(self, |%named);
187 }
188
189 our method slurp(*%named) {
190         $!filesystem.slurp(self, |%named);
191 }
192
193
194
195 #~ class Path::Cwd;
196
197 #~ my method _complete() {
198         #~ '.';
199 #~ }