File Coverage

blib/lib/YATT/Lite/VFS.pm
Criterion Covered Total %
statement 295 332 88.8
branch 102 144 70.8
condition 45 67 67.1
subroutine 60 69 86.9
pod 2 53 3.7
total 504 665 75.7


line stmt bran cond sub pod time code
1             package YATT::Lite::VFS;
2 18     18   8897 use strict;
  18         42  
  18         528  
3 18     18   86 use warnings qw(FATAL all NONFATAL misc);
  18         35  
  18         604  
4 18     18   92 use mro 'c3';
  18         35  
  18         126  
5 18     18   512 use Exporter qw(import);
  18         43  
  18         454  
6 18     18   86 use Scalar::Util qw(weaken);
  18         36  
  18         812  
7 18     18   92 use Carp;
  18         42  
  18         928  
8 18     18   124 use constant DEBUG_VFS => $ENV{DEBUG_YATT_VFS};
  18         39  
  18         1017  
9 18     18   105 use constant DEBUG_REBUILD => $ENV{DEBUG_YATT_REBUILD};
  18         38  
  18         879  
10 18     18   100 use constant DEBUG_MRO => $ENV{DEBUG_YATT_MRO};
  18         1120  
  18         2073  
11              
12             require File::Spec;
13             require File::Basename;
14              
15             #========================================
16             # VFS 層. vfs_file (Template) のダミー実装を含む。
17             #========================================
18             {
19             sub MY () {__PACKAGE__}
20             use YATT::Lite::Types
21 18         274 ([Item => -fields => [qw(cf_name cf_public cf_type)]
22             , -constants => [[can_generate_code => 0]]
23             , [Folder => -fields => [qw(Item cf_path cf_parent cf_base
24             cf_entns)]
25             , -eval => q{use YATT::Lite::Util qw(cached_in);}
26             , [File => -fields => [qw(partlist cf_string cf_overlay cf_imported
27             dependency
28             )]
29             , -alias => 'vfs_file']
30             , [Dir => -fields => [qw(cf_encoding)]
31 18     18   5777 , -alias => 'vfs_dir']]]);
  18         47  
32              
33       0 0   sub YATT::Lite::VFS::Item::after_create {}
34             sub YATT::Lite::VFS::Folder::configure_parent {
35 250     250 0 532 my MY $self = shift;
36             # 循環参照対策
37             # XXX: Item に移すべきかもしれない。そうすれば、 Widget->parent が引ける。
38 250         1536 weaken($self->{cf_parent} = shift);
39             }
40              
41 18     18   652 package YATT::Lite::VFS; BEGIN {$INC{"YATT/Lite/VFS.pm"} = 1}
42             sub VFS () {__PACKAGE__}
43 18     18   120 use parent qw(YATT::Lite::Object);
  18         38  
  18         79  
44 18         94 use YATT::Lite::MFields qw/cf_ext_private cf_ext_public cf_cache cf_no_auto_create
45             cf_facade cf_base
46             cf_import
47             cf_entns
48             cf_always_refresh_deps
49             cf_no_mro_c3
50             on_memory
51             root extdict
52             cf_mark
53             n_creates
54 18     18   1348 cf_entns2vfs_item/;
  18         43  
55 18     18   148 use YATT::Lite::Util qw(lexpand rootname terse_dump extname);
  18         49  
  18         24019  
56 0     0 0 0 sub default_ext_public {'yatt'}
57 0     0 0 0 sub default_ext_private {'ytmpl'}
58             sub new {
59 84     84 1 6541 my ($class, $spec) = splice @_, 0, 2;
60 84         472 (my VFS $vfs, my @task) = $class->SUPER::just_new(@_);
61 84   33     582 foreach my $desc ([1, ($vfs->{cf_ext_public}
      33        
62             ||= $vfs->default_ext_public)]
63             , [0, ($vfs->{cf_ext_private}
64             ||= $vfs->default_ext_private)]) {
65 168         416 my ($value, @ext) = @$desc;
66 168         588 $vfs->{extdict}{$_} = $value for @ext;
67             }
68              
69 84 50       285 if ($spec) {
70 84         386 my Folder $root = $vfs->root_create
71             (linsert($spec, 2, $vfs->cf_delegate(qw(entns))));
72             # Mark [data => ..] vfs as on_memory
73 84 100 66     542 $vfs->{on_memory} = 1 if $spec->[0] eq 'data' or not $root->{cf_path};
74             }
75              
76 84         206 $$_[0]->($vfs, $$_[1]) for @task;
77 84         317 $vfs->after_new;
78 84         631 $vfs;
79             }
80             sub after_new {
81 84     84 1 161 my MY $self = shift;
82 84 50       252 confess __PACKAGE__ . ": facade is empty!" unless $self->{cf_facade};
83 84         294 weaken($self->{cf_facade});
84              
85 84 50       246 $self->refresh_import if $self->{cf_import};
86             }
87             sub error {
88 29     29 0 53 my MY $self = shift;
89 29         200 $self->{cf_facade}->error(@_);
90             }
91             #========================================
92              
93             sub find_neighbor_file {
94 4     4 0 9 (my VFS $vfs, my ($path)) = @_;
95             my VFS $other_vfs = $vfs->{cf_facade}->find_neighbor_vfs
96 4         141 (File::Basename::dirname($path));
97 4         119 $other_vfs->find_file(File::Basename::basename($path));
98             }
99             sub find_neighbor_type {
100 5     5 0 11 (my VFS $vfs, my ($kind, $path)) = @_;
101 5 100 33     77 $kind //= -d $path ? 'dir' : 'file';
102 5 100       15 if ($kind eq 'file') {
    50          
103 4         13 $vfs->find_neighbor_file($path);
104             } elsif ($kind eq 'dir') {
105 1         10 $vfs->{cf_facade}->find_neighbor($path);
106             } else {
107 0         0 croak "Unknown vfs type=$kind path=$path";
108             }
109             }
110              
111             sub refresh_import {
112 0     0 0 0 (my VFS $vfs) = @_;
113 0         0 my Folder $root = $vfs->{root};
114              
115             my @files = grep {
116 0 0       0 -f $_ && defined $vfs->{extdict}{extname($_)}
117             } map {
118 0         0 my $fn = "$root->{cf_path}/$_";
119 0         0 1 while $fn =~ s,/[^/\.]+/\.\./,/,g;
120 0         0 glob($fn);
121 0         0 } lexpand($vfs->{cf_import});
122              
123 0         0 if (DEBUG_VFS) {
124             printf STDERR "# vfs-import to %s from %s (actually: %s)\n"
125             , $root->{cf_path}, terse_dump($vfs->{cf_import}), terse_dump(\@files);
126             }
127              
128 0         0 foreach my $fn (@files) {
129 0         0 my Folder $file = $vfs->find_neighbor_file($fn);
130              
131             # Skip if it exists.
132 0 0       0 next if $root->lookup_1($vfs, $file->{cf_name});
133              
134             #
135             $root->{Item}{$file->{cf_name}}
136 0         0 = $vfs->create(file => $file->{cf_path}, parent => $root
137             , imported => 1
138             );
139             }
140             }
141              
142             #========================================
143             sub find_file {
144 381     381 0 941 (my VFS $vfs, my $filename) = @_;
145             # XXX: 拡張子をどうしたい?
146 381 50       2409 my ($name) = $filename =~ m{^(\w+)}
147             or croak "Can't extract part name from filename '$filename'";
148 381         1621 $vfs->{root}->lookup($vfs, $name);
149             }
150             sub list_items {
151 1     1 0 2 (my VFS $vfs) = @_;
152 1         4 $vfs->{root}->list_items($vfs);
153             }
154             sub resolve_path_from {
155 5     5 0 11 (my VFS $vfs, my Folder $from, my $fn) = @_;
156 5         16 my Folder $folder = $from->dirobj;
157 5 50       14 my $dirname = $folder->dirname
158             or return undef;
159 5         9 my $abs = do {
160 5 50       27 if ($fn =~ /^@/) {
    100          
161 0         0 croak "Not (yet) supported path type '$fn' in $folder->{cf_path}";
162             } elsif ($fn =~ s!^((?:\.\./)+)!!) {
163             # leading upward relpath is treated specially.
164 2         8 my $up = length($1) / 3;
165 2         30 my @dirs = File::Spec->splitdir($dirname);
166 2         29 File::Spec->catfile(@dirs[0.. $#dirs - $up], $fn);
167             } else {
168 3         54 File::Spec->rel2abs($fn, $dirname);
169             }
170             };
171 5         22 $abs;
172             }
173              
174             #========================================
175             sub find_part {
176 46     46 0 8607 my VFS $vfs = shift;
177 46         156 $vfs->{root}->lookup($vfs, @_);
178             }
179             sub find_part_from {
180 159     159 0 451 (my VFS $vfs, my $from) = splice @_, 0, 2;
181 159         688 my Item $item = $from->lookup($vfs, @_);
182 159 100 100     1667 if ($item and $item->isa($vfs->Folder)) {
183 23         195 (my Folder $folder = $item)->{Item}{''}
184             } else {
185 136         1193 $item;
186             }
187             }
188              
189             sub find_part_from_entns {
190 0     0 0 0 (my VFS $vfs, my $entns) = splice @_, 0, 2;
191 0 0       0 my Folder $folder = $vfs->{cf_entns2vfs_item}{$entns}
192             or croak "Unknown entns $entns!";
193 0         0 $vfs->find_part_from($folder, @_);
194             }
195              
196             # To limit call of refresh atmost 1, use this.
197             sub reset_refresh_mark {
198 197     197 0 415 (my VFS $vfs) = shift;
199 197 50       851 $vfs->{cf_mark} = @_ ? shift : {};
200             }
201              
202             sub YATT::Lite::VFS::Folder::lookup {
203 630   100 630 0 2927 $_[0]->lookup_1(@_[1..$#_])
204             // $_[0]->lookup_base(@_[1..$#_])
205             }
206              
207 0     0 0 0 sub YATT::Lite::VFS::Dir::dirobj { $_[0] }
208             sub YATT::Lite::VFS::File::dirobj {
209 5     5 0 9 (my vfs_file $file) = @_;
210 5         11 $file->{cf_parent};
211             }
212              
213             sub YATT::Lite::VFS::Dir::dirname {
214 5     5 0 8 (my vfs_dir $dir) = @_;
215 5         14 $dir->{cf_path};
216             }
217             sub YATT::Lite::VFS::File::dirname {
218 0     0 0 0 (my vfs_file $file) = @_;
219 0 0       0 if (my $parent = $file->{cf_parent}) {
    0          
220 0         0 $parent->dirname;
221             } elsif (my $path = $file->{cf_path}) {
222 0         0 File::Basename::dirname(File::Spec->rel2abs($path));
223             } else {
224 0         0 undef;
225             }
226             }
227              
228 18     18   167 use Scalar::Util qw(refaddr);
  18         37  
  18         46237  
229             sub YATT::Lite::VFS::File::fake_filename {
230 223     223 0 554 (my vfs_file $file) = @_;
231 223   66     1355 $file->{cf_path} // $file->{cf_name};
232             }
233              
234             sub YATT::Lite::VFS::File::lookup_1 {
235 240     240 0 656 (my vfs_file $file, my VFS $vfs, my $name) = splice @_, 0, 3;
236 240 100       716 unless (@_) {
237             # ファイルの中には、深さ 1 の name しか無いはずだから。
238             # mtime, refresh
239 225 100       1008 $file->refresh($vfs) unless $vfs->{cf_mark}{refaddr($file)}++;
240 225         523 my Item $item = $file->{Item}{$name};
241 225 100       934 return $item if $item;
242             }
243 81         383 undef;
244             }
245             sub YATT::Lite::VFS::Dir::lookup_1 {
246 511     511 0 1528 (my vfs_dir $dir, my VFS $vfs, my $name) = splice @_, 0, 3;
247 511 100 100     3263 if (my Item $item = $dir->cached_in
248             ($dir->{Item} //= {}, $name, $vfs, $vfs->{cf_mark})) {
249 450 100 100     3131 if ((not ref $item or not UNIVERSAL::isa($item, Item))
      100        
250             and not $vfs->{cf_no_auto_create}) {
251             # Special case (mostly for test)
252             # data vfs can contain vfs spec (string, array, hash).
253 143         555 $item = $dir->{Item}{$name} = $vfs->create
254             (data => $item, parent => $dir, name => $name);
255             }
256 448 100       3090 return $item unless @_;
257 40 100 66     194 if (not $vfs->{cf_no_mro_c3} and $dir->{cf_entns}) {
258 16         53 $item = $item->lookup_1($vfs, @_);
259             } else {
260 24         68 $item = $item->lookup($vfs, @_);
261             }
262 40 100       291 return $item if $item;
263             }
264 62         286 undef;
265             }
266             sub YATT::Lite::VFS::Folder::lookup_base {
267 71     71 0 216 (my Folder $item, my VFS $vfs, my $name) = splice @_, 0, 3;
268 71 100 66     386 if (not $vfs->{cf_no_mro_c3} and $item->{cf_entns}) {
269 50         103 my @super_ns = @{mro::get_linear_isa($item->{cf_entns})};
  50         391  
270 50 100       133 foreach my $super (map {my $o = $vfs->{cf_entns2vfs_item}{$_}; $o ? $o : ()}
  350         628  
  350         764  
271             @super_ns) {
272 105 100       284 my $ans = $super->lookup_1($vfs, $name, @_) or next;
273 33         192 return $ans;
274             }
275             } else {
276 21         47 my @super = $item->list_base;
277 21         42 foreach my $super (@super) {
278 20 100       47 my $ans = $super->lookup($vfs, $name, @_) or next;
279 17         83 return $ans;
280             }
281             }
282 21         182 undef;
283             }
284             sub YATT::Lite::VFS::Folder::list_base {
285 681   100 681 0 1120 my Folder $folder = shift; @{$folder->{cf_base} ||= []}
  681         1075  
  681         2940  
286             }
287             sub YATT::Lite::VFS::File::list_base {
288 671     671 0 1206 my vfs_file $file = shift;
289              
290             # $dir/$file.yatt inherits its own base decl,
291 671         1150 my (@local, @otherdir);
292 671         2160 foreach my Folder $super ($file->YATT::Lite::VFS::Folder::list_base) {
293 28 100 100     131 if ($super->{cf_parent} and $file->{cf_parent} == $super->{cf_parent}) {
294 9         22 push @local, $super;
295             } else {
296 19         39 push @otherdir, $super;
297             }
298             }
299              
300 671         1599 push @local, grep {$_} $file->{cf_parent}, $file->{cf_overlay};
  1342         2602  
301              
302 671 100 66     4240 if ($file->{cf_entns} and mro::get_mro($file->{cf_entns}) eq 'c3') {
303             print STDERR "use c3 for $file->{cf_entns}"
304             , "\n ".terse_dump([local => map {
305             my Folder $f = $_;
306             mro::get_linear_isa($f->{cf_entns})
307             } @local])
308             , "\n ".terse_dump([other => map {
309 660         1016 my Folder $f = $_;
310             mro::get_linear_isa($f->{cf_entns})
311             } @otherdir])
312             , "\n" if DEBUG_MRO;
313 660         2837 return (@local, @otherdir);
314             } else {
315 11         18 print STDERR "use dfs for $file->{cf_entns}\n" if DEBUG_MRO;
316 11         30 return (@otherdir, @local);
317             }
318             }
319             sub YATT::Lite::VFS::File::list_items {
320 0     0 0 0 die "NIMPL";
321             }
322             sub YATT::Lite::VFS::Dir::list_items {
323 1     1 0 2 (my vfs_dir $in, my VFS $vfs) = @_;
324 1 50       4 croak "BUG: vfs is undef!" unless defined $vfs;
325 1 50       4 return unless defined $in->{cf_path};
326 1         1 my %dup;
327             my @exts = map {
328 2 50 33     12 if (defined $_ and not $dup{$_}++) {
329 2         6 $_
330 0         0 } else { () }
331 1         3 } ($vfs->{cf_ext_public}, $vfs->{cf_ext_private});
332 1         2 my %dup2;
333             map {
334 1         125 my $name = substr($_, length($in->{cf_path})+1);
  2         9  
335 2         9 $name =~ s/\.\w+$//;
336 2 50       23 $dup2{$name}++ ? () : $name;
337             } glob("$in->{cf_path}/[a-z]*.{".join(",", @exts)."}");
338             }
339             #----------------------------------------
340             sub YATT::Lite::VFS::Dir::load {
341 120     120 0 284 (my vfs_dir $in, my VFS $vfs, my $partName) = @_;
342 120 100       364 return unless defined $in->{cf_path};
343 113         329 my $vfsname = "$in->{cf_path}/$partName";
344 113         344 my @opt = (name => $partName, parent => $in);
345 113         181 my ($kind, $path, @other) = do {
346 113 100       356 if (my $fn = $vfs->find_ext($vfsname, $vfs->{cf_ext_public})) {
    100          
    100          
347 80         360 (file => $fn, public => 1);
348             } elsif ($fn = $vfs->find_ext($vfsname, $vfs->{cf_ext_private})) {
349             # dir の場合、 new_tmplpkg では?
350 8 50       81 my $kind = -d $fn ? 'dir' : 'file';
351 8         31 ($kind => $fn);
352             } elsif (-d $vfsname) {
353 1         5 return $vfs->{cf_facade}->find_neighbor($vfsname);
354             } else {
355 24         135 return undef;
356             }
357             };
358 88         347 $vfs->create($kind, $path, @opt, @other);
359             }
360             sub find_ext {
361 146     146 0 352 (my VFS $vfs, my ($vfsname, $spec)) = @_;
362 146 50       471 foreach my $ext (!defined $spec ? () : ref $spec ? @$spec : $spec) {
    50          
363 146         411 my $fn = "$vfsname.$ext";
364 146 100       3559 return $fn if -e $fn;
365             }
366             }
367             #========================================
368             # 実験用、ダミーのパーサー
369             sub YATT::Lite::VFS::File::reset {
370 7     7 0 19 (my File $file) = @_;
371 7         29 undef $file->{partlist};
372 7         214 undef $file->{Item};
373 7         26 undef $file->{cf_string};
374 7         18 undef $file->{cf_base};
375 7         26 $file->{dependency} = +{};
376             }
377       2 0   sub YATT::Lite::VFS::Dir::refresh {}
378             sub YATT::Lite::VFS::File::refresh {
379 22     22 0 43 (my vfs_file $file, my VFS $vfs) = @_;
380 22 50 66     68 return unless $$file{cf_path} || $$file{cf_string};
381             # XXX: mtime!
382 22         35 my @part = do {
383 22         81 local $/; split /^!\s*(\w+)\s+(\S+)[^\n]*?\n/m, do {
  22         58  
384 22 100       46 if ($$file{cf_path}) {
385             open my $fh, '<', $$file{cf_path}
386 19 50       495 or die "Can't open '$$file{cf_path}': $!";
387             scalar <$fh>
388 19         481 } else {
389 3         19 $$file{cf_string};
390             }
391             };
392             };
393 22         92 $file->add_widget('', shift @part);
394 22         89 while (my ($kind, $name, $part) = splice @part, 0, 3) {
395 19 100 66     115 if (defined $kind and my $sub = $file->can("declare_$kind")) {
396 4         10 $sub->($file, $name, $vfs, $part);
397             } else {
398 15         45 $file->can("add_$kind")->($file, $name, $part);
399             }
400             }
401             }
402              
403             sub YATT::Lite::VFS::File::add_dependency {
404 29     29 0 81 (my File $file, my $wpath, my File $other) = @_;
405 29         195 Scalar::Util::weaken($file->{dependency}{$wpath} = $other);
406             }
407             sub YATT::Lite::VFS::File::list_dependency {
408 55     55 0 104 (my File $file, my $detail) = @_;
409             defined (my $deps = $file->{dependency})
410 55 100       164 or return;
411 34 50       71 if ($detail) {
412 0 0       0 wantarray ? map([$_ => $deps->{$_}], keys %$deps) : $deps;
413             } else {
414 34         131 values %$deps;
415             }
416             }
417             sub refresh_deps_for {
418 55     55 0 123 (my MY $self, my File $file) = @_;
419 55         90 print STDERR "refresh deps for: ", $file->{cf_path}, "\n" if DEBUG_REBUILD;
420 55         122 foreach my $dep ($file->list_dependency) {
421 34 50       162 unless ($self->{cf_mark}{refaddr($dep)}++) {
422 34         58 print STDERR " refreshing: ", $dep->{cf_path}, "\n" if DEBUG_REBUILD;
423 34         98 $dep->refresh($self);
424             }
425             }
426             }
427              
428             #========================================
429             sub add_to {
430 19     19 0 61 (my VFS $vfs, my ($path, $data)) = @_;
431 19 50       69 my @path = ref $path ? @$path : $path;
432 19         39 my $lastName = pop @path;
433 19         55 my Folder $folder = $vfs->{root};
434 19         60 while (@path) {
435 0         0 my $name = shift @path;
436 0   0     0 $folder = $folder->{Item}{$name} ||= $vfs->create
437             (data => {}, name => $name, parent => $folder);
438             }
439             # XXX: path を足すと、memory 動作の時に困る
440 19         71 $folder->{Item}{$lastName} = $vfs->create
441             (data => $data, name => $lastName, parent => $folder);
442             }
443             #========================================
444 37     37 0 75 sub root {(my VFS $vfs) = @_; $vfs->{root}}
  37         102  
445              
446             # special hook for root creation.
447             sub root_create {
448 84     84 0 367 (my VFS $vfs, my ($kind, $primary, %rest)) = @_;
449 84   66     305 $rest{entns} //= $vfs->{cf_entns};
450 84         400 $vfs->{root} = $vfs->create($kind, $primary, %rest);
451             }
452             sub create {
453 344     344 0 2131 (my VFS $vfs, my ($kind, $primary, %rest)) = @_;
454             # XXX: $vfs は className の時も有る。
455 344 100       1913 if (my $sub = $vfs->can("create_$kind")) {
456 261         1286 $vfs->fixup_created(\@_, $sub->($vfs, $primary, %rest, type => $kind));
457             } else {
458 83   33     390 $vfs->{cf_cache}{$primary} ||= do {
459             # XXX: Really??
460 83   66     296 $rest{entns} //= $vfs->{cf_entns};
461 83         875 $vfs->fixup_created
462             (\@_, $vfs->can("vfs_$kind")->()->new(%rest, path => $primary
463             , type => $kind
464             ));
465             };
466             }
467             }
468             sub terse_dump2 {
469 0     0 0 0 require Data::Dumper;
470             join ", ", map {
471 0         0 Data::Dumper->new([$_])->Maxdepth(2)->Terse(1)->Indent(0)->Dump;
  0         0  
472             } @_;
473             }
474             sub fixup_created {
475 344     344 0 856 (my VFS $vfs, my $info, my Folder $folder) = @_;
476             printf STDERR "# VFS::create(%s) => %s(0x%x)\n"
477 344         545 , terse_dump2(@{$info}[1..$#$info])
478             , ref $folder, ($folder+0) if DEBUG_VFS;
479             # create の直後、 after_create より前に、mark を打つ。そうしないと、 delegate で困る。
480 344 100       1020 if (ref $vfs) {
481 342         725 $vfs->{n_creates}++;
482 342         1583 $vfs->{cf_mark}{refaddr($folder)}++;
483             }
484              
485 344 100 100     1662 if (my $path = $folder->{cf_path} and not defined $folder->{cf_name}) {
486 67         270 $path =~ s/\.\w+$//;
487 67         328 $path =~ s!.*/!!;
488 67         181 $folder->{cf_name} = $path;
489             }
490              
491 344 100       1089 if (my Folder $parent = $folder->{cf_parent}) {
492 250 100       771 if (defined $parent->{cf_entns}) {
493             $folder->{cf_entns} = join '::'
494 230         860 , $parent->{cf_entns}, $folder->{cf_name};
495             # XXX: base 指定だけで済むべきだが、Factory を呼んでないので出来ないorz...
496             YATT::Lite::MFields->add_isa_to
497 230         1657 ($folder->{cf_entns}, $parent->{cf_entns});
498             }
499             }
500 344 100       1014 if ($folder->{cf_entns}) {
501 299 50       863 if (not $vfs->{cf_no_mro_c3}) {
502 299         1514 mro::set_mro($folder->{cf_entns}, 'c3');
503             }
504 299 50       1192 if (defined (my Folder $old = $vfs->{cf_entns2vfs_item}{$folder->{cf_entns}})) {
505 0 0       0 if ($old != $folder) {
506 0         0 croak "EntNS confliction for $folder->{cf_entns}! old=$old->{cf_path} vs new=$folder->{cf_path}";
507             }
508             }
509 299         780 $vfs->{cf_entns2vfs_item}{$folder->{cf_entns}} = $folder;
510             }
511 344         1407 $folder->after_create($vfs);
512 341         2483 $folder;
513             }
514              
515             # XXX: <=> find_part_from_entns
516             sub find_template_from_package {
517 3     3 0 10 (my MY $self, my $pkg) = @_;
518 3         17 $self->{cf_entns2vfs_item}{$pkg};
519             }
520              
521             sub create_data {
522 189     189 0 588 (my VFS $vfs, my ($primary)) = splice @_, 0, 2;
523 189 100       478 if (ref $primary) {
524             # 直接 Folder slot にデータを。
525 28         230 my vfs_dir $item = $vfs->vfs_dir->new(@_);
526 28         81 $item->{Item} = $primary;
527 28         97 $item;
528             } else {
529 161         1375 $vfs->vfs_file->new(public => 1, @_, string => $primary);
530             }
531             }
532              
533             #
534             # This converts all descriptors in Folder->base into real item objects.
535             #
536             sub YATT::Lite::VFS::Folder::vivify_base_descs {
537 92     92 0 199 (my Folder $folder, my VFS $vfs) = @_;
538 92         170 foreach my Folder $desc (@{$folder->{cf_base}}) {
  92         288  
539 38 50       122 if (ref $desc eq 'ARRAY') {
540             #
541             # This $desc structure *may* come from Factory->_list_base_spec_in
542             #
543 38 100       96 if ($desc->[0] eq 'dir') {
544             # To create YATT::Lite with .htyattconfig.xhf, Factory should be involved.
545 34         179 $desc = $vfs->{cf_facade}->find_neighbor($desc->[1]);
546             } else {
547 4         18 $desc = $vfs->create(@$desc);
548             }
549             }
550             # parent がある == parent から指されている。なので、 weaken する必要が有る。
551 38 50       137 weaken($desc) if $desc->{cf_parent};
552             }
553             }
554             sub YATT::Lite::VFS::Dir::after_create {
555 92     92 0 219 (my vfs_dir $dir, my VFS $vfs) = @_;
556 92         428 $dir->YATT::Lite::VFS::Folder::vivify_base_descs($vfs);
557             # $dir->refresh($vfs);
558 92         177 $dir;
559             }
560             # file 系は create 時に必ず refresh. refresh は decl のみ parse.
561             sub YATT::Lite::VFS::File::after_create {
562 252     252 0 563 (my vfs_file $file, my VFS $vfs) = @_;
563 252         854 $file->refresh_overlay($vfs);
564 252         981 $file->refresh($vfs);
565             }
566             sub YATT::Lite::VFS::File::refresh_overlay {
567 252     252 0 527 (my vfs_file $file, my VFS $vfs) = @_;
568 252 50       757 return if $file->{cf_overlay};
569 252 100       754 return unless $file->{cf_path};
570 91         317 my $rootname = rootname($file->{cf_path});
571 91         435 my @found = grep {-d $$_[-1]} ([1, $rootname]
  182         4489  
572             , [0, "$rootname.$vfs->{cf_ext_private}"]);
573 91 50       517 if (@found > 1) {
    100          
574             $vfs->error(q|Don't use %1$s and %1$s.%2$s at once|
575 0         0 , $rootname, $vfs->{cf_ext_private});
576             } elsif (not @found) {
577 90         233 return;
578             }
579 1         3 $file->{cf_overlay} = do {
580 1         3 my ($public, $path) = @{$found[0]};
  1         4  
581 1 50       3 if ($public) {
582 1         6 $vfs->{cf_facade}->find_neighbor($path);
583             } else {
584             $vfs->create
585 0         0 (dir => $path, parent => $file->{cf_parent});
586             }
587             };
588             }
589             #----------------------------------------
590             sub YATT::Lite::VFS::File::declare_base {
591 4     4 0 12 (my vfs_file $file, my ($spec), my VFS $vfs, my $part) = @_;
592 4         11 my ($kind, $path) = split /=/, $spec, 2;
593             # XXX: 物理 path だと困るよね? findINC 的な処理が欲しい
594             # XXX: 帰属ディレクトリより強くするため、先頭に。でも、不満。
595 4         8 unshift @{$file->{cf_base}}, $vfs->create($kind => $path);
  4         14  
596 4         15 weaken($file->{cf_base}[0]);
597 4         20 $file->{Item}{''} .= $part;
598             }
599             sub YATT::Lite::VFS::File::add_widget {
600 37     37 0 76 (my vfs_file $file, my ($name, $part)) = @_;
601 37         55 push @{$file->{partlist}}, $file->{Item}{$name} = $part;
  37         168  
602             }
603              
604             sub linsert {
605 84     84 0 171 my @ls = @{shift()};
  84         256  
606 84         261 splice @ls, shift, 0, @_;
607 84 50       539 wantarray ? @ls : \@ls;
608             }
609             }
610              
611 18     18   183 use YATT::Lite::Breakpoint;
  18         46  
  18         1679  
612             YATT::Lite::Breakpoint::break_load_vfs();
613              
614             1;