Badger

 view release on metacpan or  search on metacpan

lib/Badger/Filesystem.pm  view on Meta::CPAN

        qr/$sep$/;
    };
    $path .= $self->{ separator } unless $path =~ $slash;
    return $path;
}


#-----------------------------------------------------------------------
# absolute and relative path tests and transmogrifiers
#-----------------------------------------------------------------------

sub is_absolute {
    my $self = shift;
#    $self->debug("args: ", $self->dump_data(\@_));
    $self->spec->file_name_is_absolute(
        $self->join_directory(@_)
    ) ? 1 : 0;
}

sub is_relative {
    shift->is_absolute(@_) ? 0 : 1;
}

sub absolute {
    my $self = shift;
    my $path = $self->join_directory(shift);
    my $spec = $self->spec;
    return $path if $spec->file_name_is_absolute($path);
    $spec->catdir(shift || $self->cwd, $path);
}

sub relative {
    my $self = shift;
    $self->spec->abs2rel($self->join_directory(shift), shift || $self->cwd);
}


#-----------------------------------------------------------------------
# file/directory test methods
#-----------------------------------------------------------------------

sub path_exists {
    shift->stat_path(@_);
}

sub file_exists {
    my $self  = shift;
    my $stats = $self->stat_path(shift) || return; 
    return -f _ ? $stats : 0;       # relies on cached stat
}

sub directory_exists {
    my $self = shift;
    my $stats = $self->stat_path(shift) || return; 
    return -d _ ? $stats : 0;       # relies on cached stat
}

sub stat_path {
    my $self  = shift;
    my $path  = $self->definitive_read(shift) || return; 
    my @stats = (stat($path), -r _, -w _, -x _, -o _, $path);

    return $self->error_msg( bad_stat => $self->{ path } )
        unless @stats;

    return wantarray
        ?  @stats
        : \@stats;
}

sub chmod_path {
    my $self = shift;
    my $path = $self->definitive_write(shift);
    chmod(shift, $path);
}


#-----------------------------------------------------------------------
# file manipulation methods
#-----------------------------------------------------------------------

sub create_file {
    my ($self, $path) = @_;
    unless (-e $self->definitive_write($path)) {
        $self->write_file($path); # calls definitive_write again
    }
    return 1;
}

sub touch_file {
    my ($self, $path) = @_;
    my $definitive = $self->definitive_write($path);
    if (-e $definitive) {
        my $now = time();
        utime $now, $now, $definitive;
    }
    else {
        $self->write_file($path); # calls definitive_write again
    }
}

sub delete_file {
    my $self = shift;
    my $path = $self->definitive_write(shift);
    unlink($path)
        || return $self->error_msg( delete_failed => file => $path => $! );
}

sub open_file {
    my $self = shift;
    my $name = shift;
    my $mode = $_[0] || 'r';            # leave it in @_ for IO::File
    my $opts = @_ && ref $_[-1] eq HASH ? pop(@_) : { };
    my $path = $mode eq 'r' 
        ? $self->definitive_read($name)
        : $self->definitive_write($name);
    return $self->error_msg( no_path => $name )
        unless defined $path && length $path;

    require IO::File;
    $self->debug("about to open file $path (", join(', ', @_), ")\n") if $DEBUG;

lib/Badger/Filesystem.pm  view on Meta::CPAN


    $fs->cwd;                               # /foo/bar  (for example)
    $fs->relative('/foo/bar/wam/bam');      # wam/bam
    $fs->relative('/baz/wam/bam', '/baz');  # wam/bam

Again note that last example where 

=head2 definitive($path)

Converts an absolute or relative path to a definitive one.  In most cases,
a definitive path is identical to an absolute one.

    $fs->definitive('/foo/bar');            # /foo/bar

However, if you're using a L<virtual filesystem|Badger::Filesystem::Virtual>
with a virtual root directory, then a I<definitive> path I<will> include the
virtual root directory, whereas a an I<absolute> path will I<not>.

    my $vfs = Badger::Filesystem::Virtual->new( root => '/my/vfs' );
    $vfs->absolute('/foo/bar');              # /foo/bar
    $vfs->definitive('/foo/bar');            # /my/vfs/foo/bar

The C<Badger::Filesystem> module uses definitive paths when performing any
operations on the file system (e.g. opening and reading files and
directories). You can think of absolute paths as being like conceptual URIs
(identifiers) and definitive paths as being like concrete URLs (locators). In
practice, they'll both have the same value unless unless you're using a
virtual file system.

In the C<Badger::Filesystem> base class, the C<definitive()> method is
mapped directly to the L<definitive_write()> method.  This has no real
effect in this module, but provides the relevant hooks that allow the 
L<Badger::Filesystem::Virtual> subclass to work properly.

=head2 definitive_read($path)

Converts an absolute or relative path to a definitive one for a read
operation.  See L<definitive()>.

=head2 definitive_write($path)

Converts an absolute or relative path to a definitive one for a write 
operation.  See L<definitive()>.

=head1 PATH TEST METHODS

=head2 path_exists($path)

Returns true if the path exists, false if not.

=head2 file_exists($path)

Returns true if the path exists and is a file, false if not.

=head2 dir_exists($path) / directory_exists($path)

Returns true if the path exists and is a directory, false if not.

=head2 stat_path($path)

Performs a C<stat()> on the filesystem path.  It returns a list (in list 
context) or a reference to a list (in scalar context) containing 17 items.
The first 13 are those returned by Perl's inbuilt C<stat()> function.  The
next 3 items are flags indicating if the file is readable, writeable and/or
executable.  The final item is a flag indicating if the file is owned by the
current user (i.e. owner of the current process.

A summary of the fields is shown below. See C<perldoc -f stat> and the
L<stat()|Badger::Filesystem::Path/stat()> method in
L<Badger::Filesystem::Path> for further details.

    Field   Description
    --------------------------------------------------------
      0     device number of filesystem
      1     inode number
      2     file mode  (type and permissions)
      3     number of (hard) links to the file
      4     numeric user ID of file’s owner
      5     numeric group ID of file’s owner
      6     the device identifier (special files only)
      7     total size of file, in bytes
      8     last access time in seconds since the epoch
      9     last modify time in seconds since the epoch
     10     inode change time in seconds since the epoch (*)
     11     preferred block size for file system I/O
     12     actual number of blocks allocated
     13     file is readable by current process
     14     file is writeable by current process
     15     file is executable by current process
     16     file is owned by current process

=head2 chmod_path($path)

Changes the file permissions on a path.

    $fs->chmod_path('/path/to/file', 0755);

=head1 FILE MANIPULATION METHODS

=head2 create_file($path)

Creates an empty file if it doesn't already exist.  Returns a true value
if the file is created and a false value if it already exists.  Errors are
thrown as exceptions.

    $fs->create_file('/path/to/file');

=head2 touch_file($path) / touch($path)

Creates a file if it doesn't exists, or updates the timestamp if it does.

    $fs->touch_file('/path/to/file');

=head2 delete_file($path)

Deletes a file.

    $fs->delete_file('/path/to/file');      # Careful with that axe, Eugene!

=head2 open_file($path, $mode, $perms)

Opens a file for reading (by default) or writing/appending (by passing
C<$mode> and optionally C<$perms>). Accepts the same parameters as for the
L<IO::File::open()|IO::File> method and returns an L<IO::File> object.

    my $fh = $fs->open_file('/path/to/file');
    my $fh = $fs->open_file('/path/to/file', 'w');      
    my $fh = $fs->open_file('/path/to/file', 'w', 0644);



( run in 1.763 second using v1.01-cache-2.11-cpan-d8267643d1d )