.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Badger::Filesystem::Virtual 3pm" .TH Badger::Filesystem::Virtual 3pm "2023-08-28" "perl v5.36.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Badger::Filesystem::Virtual \- virtual filesystem .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Badger::Filesystem::Virtual; \& \& my $fs = Badger::Filesystem::Virtual\->new( \& root => [\*(Aq/path/to/dir/one\*(Aq, \*(Aq/path/to/dir/two\*(Aq], \& ); \& my $file = $fs\->file(\*(Aq/example/file\*(Aq); \& my $dir = $fs\->dir(\*(Aq/example/directory\*(Aq); \& \& if ($file\->exists) { # under either root directory \& print $file\->text; # loaded from correct location \& } \& else { # writes under first directory \& $file\->write("hello world!\en"); \& } .Ve .SH "INTRODUCTION" .IX Header "INTRODUCTION" This module defines a subclass of Badger::Filesystem for creating virtual filesystems that are \*(L"mounted\*(R" onto one or more underlying source directories in a real file system (if you're familiar with the Template Toolkit then think of the \s-1INCLUDE_PATH\s0). If that doesn't mean much to you then the chances are that you don't need to read this documentation. Either way you should read the documentation for Badger::Filesystem first, closely followed by Badger::Filesystem::Path, Badger::Filesystem::File and Badger::Filesystem::Directory. .PP Done that now? Good, welcome back. Let us begin. .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\f(CW\*(C`Badger::Filesystem::Virtual\*(C'\fR module is a specialised subclass of the Badger::Filesystem module. In contrast to Badger::Filesystem module which gives you access to the files and directories in a \fIreal\fR filesystem, \&\f(CW\*(C`Badger::Filesystem::Virtual\*(C'\fR allows you to create a \fIvirtual\fR filesystem \&\fImounted\fR under a \fIreal\fR directory, or composed from a number of \fIreal\fR directories. .PP .Vb 1 \& use Badger::Filesystem::Virtual; \& \& # virtual file system with single root \& my $vfs1 = Badger::Filesystem::Virtual\->new( \& root => \*(Aq/path/to/virtual/root\*(Aq, \& ); \& \& # virtual file system with multiple roots \& my $vfs2 = Badger::Filesystem::Virtual\->new( \& root => [ \& \*(Aq/path/to/virtual/root/one\*(Aq, \& \*(Aq/path/to/virtual/root/two\*(Aq, \& ], \& ); .Ve .PP The module defines the exportable \f(CW\*(C`VFS\*(C'\fR symbol as an alias for \&\f(CW\*(C`Badger::Filesystem::Virtual\*(C'\fR to save on typing: .PP .Vb 1 \& use Badger::Filesystem::Virtual \*(AqVFS\*(Aq; \& \& my $vfs1 = VFS\->new( root => \*(Aq/path/to/virtual/root\*(Aq ); .Ve .PP You can also access this via the Badger::Filesystem module. .PP .Vb 1 \& use Badger::Filesystem \*(AqVFS\*(Aq; .Ve .PP \&\s-1TODO:\s0 and eventually the Badger module... .SS "Single Root Virtual Filesystem" .IX Subsection "Single Root Virtual Filesystem" A filesystem object with a single virtual root directory works in a similar way to the \f(CW\*(C`chroot\*(C'\fR command. .PP .Vb 1 \& use Badger::Filesystem::Virtual \*(AqVFS\*(Aq; \& \& my $vfs1 = VFS\->new( root => \*(Aq/my/web/site\*(Aq ); .Ve .PP Any absolute paths specified for this file system are then assumed to be relative to the virtual root. For example, we can create an object to represent a file in our virtual file system. .PP .Vb 1 \& my $home = $vfs1\->file(\*(Aqindex.html\*(Aq); .Ve .PP This file as a relative path of \f(CW\*(C`index.html\*(C'\fR. .PP .Vb 1 \& print $home\->relative; # index.html .Ve .PP The absolute path is \f(CW\*(C`/index.html\*(C'\fR. .PP .Vb 1 \& print $home\->absolute; # /index.html .Ve .PP However, the real, physical path to the file is relative to the virtual root directory. The \fBdefinitive()\fR method returns this path. .PP .Vb 1 \& print $home\->definitive; # /my/web/site/index.html .Ve .PP You can open, read, write and generally perform any kind of operation on a file or directory in a virtual file system the same way as you would for a real file system (i.e. one without a virtual \f(CW\*(C`root\*(C'\fR directory defined). Behind the scenes, the filesystem object handles the mapping of paths in the virtual file system to their physical counterparts via the definitive method. .PP .Vb 4 \& my $text = $home\->read; # read file \& $home\->write($text); # write file \& $home\->append($more_text); # append file \& # ...etc... .Ve .SS "Multiple Root Virtual File System" .IX Subsection "Multiple Root Virtual File System" Things get a little more interesting when you have a virtual filesystem with multiple root directories. .PP .Vb 1 \& use Badger::Filesystem::Virtual \*(AqVFS\*(Aq; \& \& my $vfs2 = VFS\->new( root => [ \& \*(Aq/my/root/dir/one\*(Aq, \& \*(Aq/my/root/dir/two\*(Aq \& ] ); .Ve .PP The handling of relative and absolute paths is exactly the same as for a single root virtual file system. .PP .Vb 3 \& my $home = $vfs2\->file(\*(Aqindex.html\*(Aq); \& print $home\->relative; # index.html \& print $home\->absolute; # /index.html .Ve .PP You can call any of the regular methods on Badger::Filesystem::File and Badger::Filesystem::Directory objects as you would for a normal file system, and leave it up to the \f(CW\*(C`Badger::Filesystem::Virtual\*(C'\fR module to Do The Right Thing to handle the mapping. .PP .Vb 2 \& print $home\->text; # locates file under either root dir \& print $home\->size; .Ve .PP If you look at the contents of a directory, you'll see the combined contents of that directory under any and all virtual roots that contain it. .PP .Vb 2 \& my $dir = $vfs2\->dir(\*(Aqfoo\*(Aq); \& print join "\en", $dir\->children; .Ve .PP The \fBchildren()\fR method in this example will returns all the files and sub-directories in both \&\f(CW\*(C`/my/root/dir/one/foo\*(C'\fR and \f(CW\*(C`/my/root/dir/two\*(C'\fR. .PP The \fBdefinitive_read()\fR and \fBdefinitive_write()\fR methods are used to map virtual paths onto their real counterparts whenever you read, write, or perform any other operation on an underlying file or directory. For read operations, the \fBdefinitive_read()\fR method will look for the file or directory under each of the virtual root directories until it is located or presumed not found. The \fBdefinitive_write()\fR method always maps paths to the first root directory (\s-1NOTE:\s0 we'll be providing some options to customise this at some point in the future \- be aware for now that the \fBappend()\fR method may not work correctly if you're trying to append to a file that isn't under the first root directory). .SS "Dynamic Root Directories" .IX Subsection "Dynamic Root Directories" \&\s-1TODO:\s0 we now support code refs and objects as root directories which are evaluated dynamically to generate a list of root directories. An object should have a \f(CW\*(C`path()\*(C'\fR, \f(CW\*(C`paths()\*(C'\fR or \f(CW\*(C`roots()\*(C'\fR method which returns a single path or refererence to a list of path. Any of those can be further dynamic components which will be evaluated recursively until all have been resolved or the \f(CW\*(C`max_roots\*(C'\fR limit has been reached. .SH "METHODS" .IX Header "METHODS" Badger::Filesystem::Virtual inherits all the methods of Badger::Filesystem. The following methods are added or amended. .SS "init(\e%config)" .IX Subsection "init(%config)" This custom initialisation method allows one or more \f(CW\*(C`root\*(C'\fR (or \f(CW\*(C`rootdir\*(C'\fR) directories to be specified as the base of the virtual filesystem. .SS "\fBroots()\fP" .IX Subsection "roots()" This method returns a list (in list context) or reference to a list (in scalar context) of the root directories for the virtual filesystem. Any dynamic components in the roots will be evaluated and expanded. This include subroutine references and objects implementing a \f(CW\*(C`path()\*(C'\fR, \&\f(CW\*(C`paths()\*(C'\fR or \f(CW\*(C`roots()\*(C'\fR method. Dynamic components can return a single items or reference to a list of items, any of which can be a static directory or dynamic component. .SS "definitive($path)" .IX Subsection "definitive($path)" This is aliased to the \fBdefinitive_write()\fR method. .SS "definitive_write($path)" .IX Subsection "definitive_write($path)" Maps a virtual file path to a definitive one for write operations. The path will be mapped to the first virtual root directory. .SS "definitive_read($path)" .IX Subsection "definitive_read($path)" Maps a virtual file path to a definitive one for read operations. The path will be mapped to the first virtual root directory in which the item exists. If it does not exists in any of the virtual root directories then an undefined value is returned. .SS "definitive_paths($path)" .IX Subsection "definitive_paths($path)" Returns a list (in list context) or reference to a list (in scalar context) of all the definitive paths that the file path could be mapped to. This is generating by adding the \f(CW$path\fR argument onto each of the root directories. .SS "read_directory($path)" .IX Subsection "read_directory($path)" Custom method to read a directory in a virtual filesystem. This returns a composite index of all entries in a particular directory across all roots of the virtual filesystem. .SH "OPTIONS" .IX Header "OPTIONS" .SS "root" .IX Subsection "root" The root directory or directories of the virtual filesystem. .SS "max_roots" .IX Subsection "max_roots" A limit to the maximum number of root directories allowed. This is used to prevent potential runaways when evaluating dynamic root components. See \*(L"Dynamic Root Directories\*(R" for further information. .SH "AUTHOR" .IX Header "AUTHOR" Andy Wardley .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (C) 2005\-2009 Andy Wardley. All rights reserved. .SH "SEE ALSO" .IX Header "SEE ALSO" Badger::Filesystem