App-GitFind

 view release on metacpan or  search on metacpan

lib/App/GitFind/PathClassMicro.pm  view on Meta::CPAN

sub is_dir { 0 }

sub _spec_class {
  my ($class, $type) = @_;

  die "Invalid system type '$type'" unless ($type) = $type =~ /^(\w+)$/;  # Untaint
  my $spec = "File::Spec::$type";
  ## no critic
  eval "require $spec; 1" or die $@;
  return $spec;
}

sub new_foreign {
  my ($class, $type) = (shift, shift);
  local $App::GitFind::PathClassMicro::Foreign = $class->_spec_class($type);
  return $class->new(@_);
}

sub _spec { (ref($_[0]) && $_[0]->{file_spec_class}) || 'File::Spec' }

sub boolify { 1 }

sub is_absolute {
  # 5.6.0 has a bug with regexes and stringification that's ticked by
  # file_name_is_absolute().  Help it along with an explicit stringify().
  $_[0]->_spec->file_name_is_absolute($_[0]->stringify)
}

sub is_relative { ! $_[0]->is_absolute }

sub cleanup {
  my $self = shift;
  my $cleaned = $self->new( $self->_spec->canonpath("$self") );
  %$self = %$cleaned;
  return $self;
}

sub resolve {
  my $self = shift;
  croak($! . " $self") unless -e $self;  # No such file or directory
  my $cleaned = $self->new( scalar Cwd::realpath($self->stringify) );

  # realpath() always returns absolute path, kind of annoying
  $cleaned = $cleaned->relative if $self->is_relative;

  %$self = %$cleaned;
  return $self;
}

sub absolute {
  my $self = shift;
  return $self if $self->is_absolute;
  return $self->new($self->_spec->rel2abs($self->stringify, @_));
}

sub relative {
  my $self = shift;
  return $self->new($self->_spec->abs2rel($self->stringify, @_));
}

sub stat  { [stat("$_[0]")] }
sub lstat { [lstat("$_[0]")] }

sub PRUNE { return \&PRUNE; }

1;
# End of App::GitFind::PathClassMicro::Entity

=head1 NAME

App::GitFind::PathClassMicro::Entity - Base class for files and directories

=head1 VERSION

version 0.37

=head1 DESCRIPTION

This class is the base class for C<App::GitFind::PathClassMicro::File> and
C<App::GitFind::PathClassMicro::Dir>, it is not used directly by callers.

=head1 AUTHOR

Ken Williams, kwilliams@cpan.org

=head1 SEE ALSO

L<Path::Class>

=cut

# }}}1
##############################################################################
# File {{{1

package App::GitFind::PathClassMicro::File;
{
  $App::GitFind::PathClassMicro::File::VERSION = '0.37';
}

use strict;

#use App::GitFind::PathClassMicro::Dir;
  # In the same file and has no import() - don't need to `use` it
use parent -norequire, qw(App::GitFind::PathClassMicro::Entity);
#use Carp;
sub croak { require Carp; goto &Carp::croak; }

use IO::File ();

sub new {
  my $self = shift->SUPER::new;
  my $file = pop();
  my @dirs = @_;

  my ($volume, $dirs, $base) = $self->_spec->splitpath($file);

  if (length $dirs) {
    push @dirs, $self->_spec->catpath($volume, $dirs, '');
  }

  $self->{dir}  = @dirs ? $self->dir_class->new(@dirs) : undef;

lib/App/GitFind/PathClassMicro.pm  view on Meta::CPAN

You may also use the C<iomode> parameter to pass in an IO mode to use
when opening the file, usually IO layers (though anything accepted by
the MODE argument of C<open()> is accepted here).  Just make sure it's
a I<reading> mode.

  my @lines = $file->slurp(iomode => ':crlf');
  my $lines = $file->slurp(iomode => '<:encoding(UTF-8)');

The default C<iomode> is C<r>.

Lines can also be automatically split, mimicking the perl command-line
option C<-a> by using the C<split> parameter. If this parameter is used,
each line will be returned as an array ref.

    my @lines = $file->slurp( chomp => 1, split => qr/\s*,\s*/ );

The C<split> parameter can only be used in a list context.

=item $file->spew( $content );

The opposite of L</slurp>, this takes a list of strings and prints them
to the file in write mode.  If the file can't be written to, this method
will throw an exception.

The content to be written can be either an array ref or a plain scalar.
If the content is an array ref then each entry in the array will be
written to the file.

You may use the C<iomode> parameter to pass in an IO mode to use when
opening the file, just like L</slurp> supports.

  $file->spew(iomode => '>:raw', $content);

The default C<iomode> is C<w>.

=item $file->spew_lines( $content );

Just like C<spew>, but, if $content is a plain scalar, appends $/
to it, or, if $content is an array ref, appends $/ to each element
of the array.

Can also take an C<iomode> parameter like C<spew>. Again, the
default C<iomode> is C<w>.

=item $file->traverse(sub { ... }, @args)

Calls the given callback on $file. This doesn't do much on its own,
but see the associated documentation in L<App::GitFind::PathClassMicro::Dir>.

=item $file->remove()

This method will remove the file in a way that works well on all
platforms, and returns a boolean value indicating whether or not the
file was successfully removed.

C<remove()> is better than simply calling Perl's C<unlink()> function,
because on some platforms (notably VMS) you actually may need to call
C<unlink()> several times before all versions of the file are gone -
the C<remove()> method handles this process for you.

=item $st = $file->stat()

Invokes C<< File::stat::stat() >> on this file and returns a
L<File::stat> object representing the result.

MODIFIED: returns an arrayref of C<stat()> results.

=item $st = $file->lstat()

Same as C<stat()>, but if C<$file> is a symbolic link, C<lstat()>
stats the link instead of the file the link points to.

MODIFIED: returns an arrayref of C<lstat()> results.

=item $class = $file->dir_class()

Returns the class which should be used to create directory objects.

Generally overridden whenever this class is subclassed.

=item $copy = $file->copy_to( $dest );

Copies the C<$file> to C<$dest>. It returns a L<App::GitFind::PathClassMicro::File>
object when successful, C<undef> otherwise.

=item $moved = $file->move_to( $dest );

Moves the C<$file> to C<$dest>, and updates C<$file> accordingly.

It returns C<$file> is successful, C<undef> otherwise.

=back

=head1 AUTHOR

Ken Williams, kwilliams@cpan.org

=head1 SEE ALSO

L<Path::Class>, L<Path::Class::Dir>, L<File::Spec>

=cut

# }}}1
##############################################################################
# Dir {{{1

package App::GitFind::PathClassMicro::Dir;
{
  $App::GitFind::PathClassMicro::Dir::VERSION = '0.37';
}

use strict;

#use App::GitFind::PathClassMicro::File;
  # In the same file and has no import() - don't need to `use` it
#use Carp();
sub croak { require Carp; goto &Carp::croak; }
use parent -norequire, qw(App::GitFind::PathClassMicro::Entity);

#use IO::Dir ();
#use File::Path ();
#use File::Temp ();
use Scalar::Util ();

# updir & curdir on the local machine, for screening them out in
# children().  Note that they don't respect 'foreign' semantics.
my $Updir  = __PACKAGE__->_spec->updir;
my $Curdir = __PACKAGE__->_spec->curdir;

sub new {
  my $self = shift->SUPER::new();

lib/App/GitFind/PathClassMicro.pm  view on Meta::CPAN

    my ($child, $cont) = @_;
    return if -l $child; # don't follow symlinks
    # do something with $child
    return $cont->();
  });

=item $dir->traverse_if( sub { ... }, sub { ... }, @args )

traverse with additional "should I visit this child" callback.
Particularly useful in case examined tree contains inaccessible
directories.

Canonical example:

  $dir->traverse_if(
    sub {
       my ($child, $cont) = @_;
       # do something with $child
       return $cont->();
    },
    sub {
       my ($child) = @_;
       # Process only readable items
       return -r $child;
    });

Second callback gets single parameter: child. Only children for
which it returns true will be processed by the first callback.

Remaining parameters are interpreted as in traverse, in particular
C<traverse_if(callback, sub { 1 }, @args> is equivalent to
C<traverse(callback, @args)>.

=item $dir->recurse( callback => sub {...} )

Iterates through this directory and all of its children, and all of
its children's children, etc., calling the C<callback> subroutine for
each entry.  This is a lot like what the L<File::Find> module does,
and of course C<File::Find> will work fine on L<App::GitFind::PathClassMicro> objects,
but the advantage of the C<recurse()> method is that it will also feed
your callback routine C<App::GitFind::PathClassMicro> objects rather than just pathname
strings.

The C<recurse()> method requires a C<callback> parameter specifying
the subroutine to invoke for each entry.  It will be passed the
C<App::GitFind::PathClassMicro> object as its first argument.

C<recurse()> also accepts two boolean parameters, C<depthfirst> and
C<preorder> that control the order of recursion.  The default is a
preorder, breadth-first search, i.e. C<< depthfirst => 0, preorder => 1 >>.
At the time of this writing, all combinations of these two parameters
are supported I<except> C<< depthfirst => 0, preorder => 0 >>.

C<callback> is normally not required to return any value. If it
returns special constant C<App::GitFind::PathClassMicro::Entity::PRUNE()> (more easily
available as C<< $item->PRUNE >>),  no children of analyzed
item will be analyzed (mostly as if you set C<$File::Find::prune=1>). Of course
pruning is available only in C<preorder>, in postorder return value
has no effect.

=item $st = $file->stat()

Invokes C<< File::stat::stat() >> on this directory and returns a
C<File::stat> object representing the result.

MODIFIED: returns an arrayref of C<stat()> results.

=item $st = $file->lstat()

Same as C<stat()>, but if C<$file> is a symbolic link, C<lstat()>
stats the link instead of the directory the link points to.

MODIFIED: returns an arrayref of C<lstat()> results.

=item $class = $file->file_class()

Returns the class which should be used to create file objects.

Generally overridden whenever this class is subclassed.

=back

=head1 AUTHOR

Ken Williams, kwilliams@cpan.org

=head1 SEE ALSO

L<Path::Class>, L<Path::Class::File>, L<File::Spec>

=cut


# }}}1
# vi: set fdm=marker: #



( run in 0.983 second using v1.01-cache-2.11-cpan-39bf76dae61 )