App-cpanminus

 view release on metacpan or  search on metacpan

lib/App/cpanminus/fatscript.pm  view on Meta::CPAN

      my $file = shift or $class->_error( 'You did not specify a file name' );
      $class->_error( "File '$file' does not exist" )
          unless -e $file;
      $class->_error( "'$file' is a directory, not a file" )
          unless -f _;
      $class->_error( "Insufficient permissions to read '$file'" )
          unless -r _;
  
      # Open unbuffered with strict UTF-8 decoding and no translation layers
      open( my $fh, "<:unix:encoding(UTF-8)", $file );
      unless ( $fh ) {
          $class->_error("Failed to open file '$file': $!");
      }
  
      # flock if available (or warn if not possible for OS-specific reasons)
      if ( _can_flock() ) {
          flock( $fh, Fcntl::LOCK_SH() )
              or warn "Couldn't lock '$file' for reading: $!";
      }
  
      # slurp the contents
      my $contents = eval {
          use warnings FATAL => 'utf8';
          local $/;
          <$fh>
      };
      if ( my $err = $@ ) {
          $class->_error("Error reading from file '$file': $err");
      }
  
      # close the file (release the lock)
      unless ( close $fh ) {
          $class->_error("Failed to close file '$file': $!");
      }
  
      $class->_load_string( $contents );
  }
  
  # Create an object from a string
  sub _load_string {
      my $class  = ref $_[0] ? ref shift : shift;
      my $self   = bless [], $class;
      my $string = $_[0];
      eval {
          unless ( defined $string ) {
              die \"Did not provide a string to load";
          }
  
          # Check if Perl has it marked as characters, but it's internally
          # inconsistent.  E.g. maybe latin1 got read on a :utf8 layer
          if ( utf8::is_utf8($string) && ! utf8::valid($string) ) {
              die \<<'...';
  Read an invalid UTF-8 string (maybe mixed UTF-8 and 8-bit character set).
  Did you decode with lax ":utf8" instead of strict ":encoding(UTF-8)"?
  ...
          }
  
          # Ensure Unicode character semantics, even for 0x80-0xff
          utf8::upgrade($string);
  
          # Check for and strip any leading UTF-8 BOM
          $string =~ s/^\x{FEFF}//;
  
          # Check for some special cases
          return $self unless length $string;
  
          # Split the file into lines
          my @lines = grep { ! /^\s*(?:\#.*)?\z/ }
                  split /(?:\015{1,2}\012|\015|\012)/, $string;
  
          # Strip the initial YAML header
          @lines and $lines[0] =~ /^\%YAML[: ][\d\.]+.*\z/ and shift @lines;
  
          # A nibbling parser
          my $in_document = 0;
          while ( @lines ) {
              # Do we have a document header?
              if ( $lines[0] =~ /^---\s*(?:(.+)\s*)?\z/ ) {
                  # Handle scalar documents
                  shift @lines;
                  if ( defined $1 and $1 !~ /^(?:\#.+|\%YAML[: ][\d\.]+)\z/ ) {
                      push @$self,
                          $self->_load_scalar( "$1", [ undef ], \@lines );
                      next;
                  }
                  $in_document = 1;
              }
  
              if ( ! @lines or $lines[0] =~ /^(?:---|\.\.\.)/ ) {
                  # A naked document
                  push @$self, undef;
                  while ( @lines and $lines[0] !~ /^---/ ) {
                      shift @lines;
                  }
                  $in_document = 0;
  
              # XXX The final '-+$' is to look for -- which ends up being an
              # error later.
              } elsif ( ! $in_document && @$self ) {
                  # only the first document can be explicit
                  die \"CPAN::Meta::YAML failed to classify the line '$lines[0]'";
              } elsif ( $lines[0] =~ /^\s*\-(?:\s|$|-+$)/ ) {
                  # An array at the root
                  my $document = [ ];
                  push @$self, $document;
                  $self->_load_array( $document, [ 0 ], \@lines );
  
              } elsif ( $lines[0] =~ /^(\s*)\S/ ) {
                  # A hash at the root
                  my $document = { };
                  push @$self, $document;
                  $self->_load_hash( $document, [ length($1) ], \@lines );
  
              } else {
                  # Shouldn't get here.  @lines have whitespace-only lines
                  # stripped, and previous match is a line with any
                  # non-whitespace.  So this clause should only be reachable via
                  # a perlbug where \s is not symmetric with \S
  
                  # uncoverable statement
                  die \"CPAN::Meta::YAML failed to classify the line '$lines[0]'";

lib/App/cpanminus/fatscript.pm  view on Meta::CPAN

        }
      }
    }
  
    $self->{version} = $self->{versions}{$self->{module}}
      if defined( $self->{module} );
  
    return $self;
  }
  
  # class method
  sub _do_find_module {
    my $class   = shift;
    my $module  = shift || croak 'find_module_by_name() requires a package name';
    my $dirs    = shift || \@INC;
  
    my $file = File::Spec->catfile(split( /::/, $module));
    foreach my $dir ( @$dirs ) {
      my $testfile = File::Spec->catfile($dir, $file);
      return [ File::Spec->rel2abs( $testfile ), $dir ]
        if -e $testfile and !-d _;  # For stuff like ExtUtils::xsubpp
      # CAVEAT (possible TODO): .pmc files are not discoverable here
      $testfile .= '.pm';
      return [ File::Spec->rel2abs( $testfile ), $dir ]
        if -e $testfile;
    }
    return;
  }
  
  # class method
  sub find_module_by_name {
    my $found = shift()->_do_find_module(@_) or return;
    return $found->[0];
  }
  
  # class method
  sub find_module_dir_by_name {
    my $found = shift()->_do_find_module(@_) or return;
    return $found->[1];
  }
  
  
  # given a line of perl code, attempt to parse it if it looks like a
  # $VERSION assignment, returning sigil, full name, & package name
  sub _parse_version_expression {
    my $self = shift;
    my $line = shift;
  
    my( $sigil, $variable_name, $package);
    if ( $line =~ /$VERS_REGEXP/o ) {
      ( $sigil, $variable_name, $package) = $2 ? ( $1, $2, $3 ) : ( $4, $5, $6 );
      if ( $package ) {
        $package = ($package eq '::') ? 'main' : $package;
        $package =~ s/::$//;
      }
    }
  
    return ( $sigil, $variable_name, $package );
  }
  
  # Look for a UTF-8/UTF-16BE/UTF-16LE BOM at the beginning of the stream.
  # If there's one, then skip it and set the :encoding layer appropriately.
  sub _handle_bom {
    my ($self, $fh, $filename) = @_;
  
    my $pos = tell $fh;
    return unless defined $pos;
  
    my $buf = ' ' x 2;
    my $count = read $fh, $buf, length $buf;
    return unless defined $count and $count >= 2;
  
    my $encoding;
    if ( $buf eq "\x{FE}\x{FF}" ) {
      $encoding = 'UTF-16BE';
    }
    elsif ( $buf eq "\x{FF}\x{FE}" ) {
      $encoding = 'UTF-16LE';
    }
    elsif ( $buf eq "\x{EF}\x{BB}" ) {
      $buf = ' ';
      $count = read $fh, $buf, length $buf;
      if ( defined $count and $count >= 1 and $buf eq "\x{BF}" ) {
        $encoding = 'UTF-8';
      }
    }
  
    if ( defined $encoding ) {
      if ( "$]" >= 5.008 ) {
        binmode( $fh, ":encoding($encoding)" );
      }
    }
    else {
      seek $fh, $pos, SEEK_SET
        or croak( sprintf "Can't reset position to the top of '$filename'" );
    }
  
    return $encoding;
  }
  
  sub _parse_fh {
    my ($self, $fh) = @_;
  
    my( $in_pod, $seen_end, $need_vers ) = ( 0, 0, 0 );
    my( @packages, %vers, %pod, @pod );
    my $package = 'main';
    my $pod_sect = '';
    my $pod_data = '';
    my $in_end = 0;
    my $encoding = '';
  
    while (defined( my $line = <$fh> )) {
      my $line_num = $.;
  
      chomp( $line );
  
      # From toke.c : any line that begins by "=X", where X is an alphabetic
      # character, introduces a POD segment.
      my $is_cut;
      if ( $line =~ /^=([a-zA-Z].*)/ ) {
        my $cmd = $1;



( run in 2.336 seconds using v1.01-cache-2.11-cpan-c966e8aa7e8 )