Module-Generic

 view release on metacpan or  search on metacpan

lib/Module/Generic/File.pm  view on Meta::CPAN

    }
    elsif( !$self->is_directory )
    {
        return( $self->error( "children() can only be called on a directory." ) );
    }
    $self->open || return( $self->pass_error );
    my @files = $self->read( exclude_invisible => 1, as_object => 1 );
    return( $self->pass_error ) if( !scalar( @files ) && $self->error );
    require Module::Generic::Array;
    my $all = Module::Generic::Array->new( \@files );
    $self->close;
    return( $all );
}

sub chmod
{
    my $self = shift( @_ );
    my $this = shift( @_ );
    return( $self->error( "No mode was provided for file \"", $self->filename, "\"." ) ) if( !defined( $this ) || !CORE::length( $this ) );
    my $mode;
    if( $this =~ /^\d+$/ )
    {
        $mode = CORE::substr( $this, 0, 1 ) eq '0' ? oct( $this ) : $this;
    }
    elsif( $this =~ /^[augo]+[=+-][rwx]+/ )
    {
        # Credits: David Golden for this nifty code borrowed from Path::Tiny
        $mode = $self->finfo->reset->mode;
        foreach my $def ( CORE::split( /,[[:blank:]\h]*/, $this ) )
        {
            if( /^(?<who>[augo]+)(?<what>[=+-])(?<perms>[rwx]+)$/ )
            {
                my $ref = { %+ };
                $ref->{who} =~ s/a/ugo/g;
                foreach my $w ( CORE::split( //, $ref->{who} ) )
                {
                    my $p = 0;
                    $p |= $MODE_BITS->{ "${w}$_" } for( CORE::split( //, $ref->{perms} ) );
                    if ( $ref->{what} eq '=' )
                    {
                        $mode = ( $mode & ~$MODE_BITS->{ "${w}m" } ) | $p;
                    }
                    else
                    {
                        $mode = $ref->{what} eq '+' ? ( $mode | $p ) : ( $mode & ~$p );
                    }
                }
            }
            else
            {
                warn( "Relative mode definition \"$def\" is malformed." ) if( warnings::enabled( 'Module::Generic' ) );
            }
        }
    }
    my $file = $self->filename;
    CORE::chmod( $mode, $file ) || return( $self->error( sprintf( "An error occurred while changing mode for file \"$file\" to %o: $!", $mode ) ) );
    $self->finfo->reset;
    return( $self );
}

sub chown
{
    my $self = shift( @_ );
    my( $uid, $gid ) = @_;
    my $f = $self->filename;
    my $what = $self->is_dir ? 'directory' : 'file';
    # try-catch
    local $@;
    my $rv;
    eval
    {
        $rv = CORE::chown( $uid, $gid, "$f" );
    };
    if( $@ )
    {
        return( $self->error( "Unable to chown ${what} $f: $@" ) );
    }
    return( $rv );
}

sub cleanup { return( shift->_set_get_boolean( 'auto_remove', @_ ) ); }

sub close
{
    my $self = shift( @_ );
    my $io = $self->opened || return( $self );
    if( $self->is_file )
    {
        my $fd = $io->fileno;
        $io->close;
        # We use the file as the universal key, just like flock locks the file on its inode
        my $repo_key = $self->filepath;
        my $repo = Module::Generic::Global->new( 'fd_locks' => CORE::ref( $self ), key => "$repo_key" ) ||
            return( $self->pass_error( Module::Generic::Global->error ) );
        # Clear any lock state
        $repo->remove;
        # Clear instance lock state
        $self->locked(0);
    }
    $self->opened( undef );
    return( $self );
}

sub code
{
    my $self = shift( @_ );
    if( @_ )
    {
        return( $self->_set_get_number( 'code', @_ ) );
    }
    else
    {
        $self->finfo->reset;
        my $code = $self->_set_get_number( 'code' );
        if( $self->exists )
        {
            if( $self->is_dir )
            {
                if( !$self->finfo->can_exec )
                {
                    $code = 403; # Forbidden
                }
            }
            else
            {
                if( !$self->changed )
                {
                    $code = 304; # Not modified
                }
                elsif( !$self->finfo->can_read )
                {
                    $code = 403; # Forbidden
                }
                elsif( $self->is_empty )
                {
                    if( $code == 201 )

lib/Module/Generic/File.pm  view on Meta::CPAN


If an error occurred, undef will be returned an an exception will be set.

=head2 can_exec

This is an alias for L<Module::Generic::Finfo/can_exec>

=head2 can_read

Returns true if the file or directory are readable. False otherwise.

If an error occurred, undef will be returned an an exception will be set.

=head2 can_write

Returns true if the file or directory are writable. False otherwise.

If an error occurred, undef will be returned an an exception will be set.

=head2 canonpath

Takes an optional parameter representing the name of the operating system for which to canonise this file path. If no operating system name is provided, this will revert to C<$^O>. See L<perlvar> for more information about this variable.

Returns the canon path of the file object based on the operating system specified.

=head2 changed

Returns true if the file was changed, false otherwise.

=head2 chdir

If the file object is a directory, this will attempt to L<perlfunc/chdir> to it.

It returns the current file object upon success, or undef and sets an exception object if an error occurred.

=head2 child

This should be called using a directory object.

Provided with a file name (not a full path), and this will return a new file object based on the combination of the directory path and the file specified.

=head2 children

    my $d = Module::Generic::File->new( '/some/directory' );
    # Returns a Module::Generic::Array object.
    my $files = $d->children;
    say "Found ", $files->length, " files.";

This method can only be used on a directory object. It returns a L<Module::Generic::Array> object of all the files and directories directly under the current directory object.

if the directory does not exist, it returns an empty L<Module::Generic::Array> object.

Upon error, it sets an L<error object|Module::Generic::Exception>, and returns C<undef> in scalar context, and an empty list in list context.

=head2 chmod

Provided with an octal value or a human file mode such as C<a+rw> and this will attempt to set the file or directory mode accordingly.

It returns the current object upon success or undef and sets an exception object upon error.

=head2 chown

Provided with an C<uid> and a C<gid> and this will call L<perlfunc/chown> on the underlying directory or file.

Both C<uid> and C<gid> must be provided, but you can provide a value of C<-1> to tell perl you do not want to change the value.

It returns true if the file or directory was changed, or o otherwise.

If an error occurred, it sets an L<error|Module::Generic/error> and return C<undef>

See L<perlport> for C<chown> portability limitations.

=head2 cleanup

This is an alias for L</auto_remove>. It enables or disables the auto cleanup of temporary file or directory upon perl cleanup phase.

    $tmp->cleanup(1); # Enable it
    my $bool = $tmp->cleanup;

=head2 close

Close the underlying file or directory.

Returns the current object, or the object itself if no handle is open.

=head2 code

Sets or gets the http-equivalent 3-digits code describing the status of the underlying directory or file.

If a value is provided, it will set the code, but if no value is provided it will guess the code based on the file readability, existence, etc.

=head2 collapse_dots

In line with section 5.2.4 of the rfc 33986, this will flaten (i.e. remove) any dots there may be in the element file path.

It takes an optional list or hash reference of parameters, including C<separator> which is used a directory separator. If not provided, it will revert to the default value for the current system.

=head2 contains

This can only be called using a directory object and is provided with a file or file object.

It returns true if the file is contained within the directory.

=head2 content

This method returns the content of the directory or file as a L<Module::Generic::Array>

If this is a directory, it returns an L<Module::Generic::Array> object with all the files within that directory, but excluding C<.> and C<..> and only within that directory, so this is not recurring.

If this is a regular file, it returns its content as an L<Module::Generic::Array> object.

If an error occurred, it returns undef and set an exception object.

=head2 content_objects

This methods works exclusively on directory object, and will return C<undef> and set an L<error|Module::Generic/error> if you attempt to use it on anything else but a directory object.

It returns an L<array object|Module::Generic::Array> of L<file objects|Module::Generic::File>. Do not use this on directory containing very large number of items for obvious reasons.

=head2 copy

    $src->copy( $destination );
    $src->copy( $destination, overwrite => 1 );
    $src->copy( $destination, { overwrite => 1 } );

Takes a dstination, and attempt to copy itself to the destination.

If the object represents a directory and the destination exists and is also a directory, it will copy the directory below the destination.

    my $d = Module::Generic::File->new( "my/other_directory" );
    my $new = $d->copy( "./another/directory" );



( run in 0.995 second using v1.01-cache-2.11-cpan-71847e10f99 )