In perl.git, the branch blead has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/57d69a4016b981268198cf744741335a9b1fbb23?hp=446b89af54d4dd848d5432e339a1456502eaee01>

- Log -----------------------------------------------------------------
commit 57d69a4016b981268198cf744741335a9b1fbb23
Author: Chris 'BinGOs' Williams <[email protected]>
Date:   Wed Jul 30 09:12:58 2014 +0100

    Update HTTP-Tiny to CPAN version 0.047
    
      [DELTA]
    
    0.047     2014-07-29 14:09:05-04:00 America/New_York
    
        [CHANGED]
    
        - Updated Mozilla::CA module recommendation version to 20130114
    
        [FIXED]
    
        - Fixed t/00-report-prereqs.t when CPAN::Meta is not installed
    
    0.046     2014-07-21 10:32:32-04:00 America/New_York
    
        [FIXED]
    
        - Empty header fields are now allowed; headers with the 'undef' value
          will be rendered as an empty header.
    
        [DOCUMENTED]
    
        - Updated HTTP/1.1 spec description from RFC 2616 to RFC 7230-7235
    
    0.045     2014-07-19 23:17:28-04:00 America/New_York (TRIAL RELEASE)
    
        [FIXED]
    
        - Fixed t/002_croakage.t for various operating systems.

M       Porting/Maintainers.pl
M       cpan/HTTP-Tiny/lib/HTTP/Tiny.pm
M       cpan/HTTP-Tiny/t/002_croakage.t
M       cpan/HTTP-Tiny/t/020_headers.t
M       cpan/HTTP-Tiny/t/140_proxy.t

commit 5f8324b5a4472646efc8d3efc3e79abd7ca8993f
Author: Chris 'BinGOs' Williams <[email protected]>
Date:   Wed Jul 30 09:05:06 2014 +0100

    Update CPAN-Meta to CPAN version 2.142060
    
      [DELTA]
    
    2.142060  2014-07-25 13:30:06-04:00 America/New_York
    
      [ADDED]
    
      - CPAN::Meta::Merge is a new class for merging two possibly overlapping
        instances of metadata. It will accept both CPAN::Meta objects and
        (possibly incomplete) hashrefs of metadata.

M       MANIFEST
M       META.json
M       META.yml
M       Porting/Maintainers.pl
M       cpan/CPAN-Meta/lib/CPAN/Meta.pm
M       cpan/CPAN-Meta/lib/CPAN/Meta/Converter.pm
M       cpan/CPAN-Meta/lib/CPAN/Meta/Feature.pm
M       cpan/CPAN-Meta/lib/CPAN/Meta/History.pm
A       cpan/CPAN-Meta/lib/CPAN/Meta/Merge.pm
M       cpan/CPAN-Meta/lib/CPAN/Meta/Prereqs.pm
M       cpan/CPAN-Meta/lib/CPAN/Meta/Spec.pm
M       cpan/CPAN-Meta/lib/CPAN/Meta/Validator.pm
A       cpan/CPAN-Meta/t/merge.t

commit d79626a55aac49404ed146f9ee6890e0ba43c343
Author: Chris 'BinGOs' Williams <[email protected]>
Date:   Wed Jul 30 08:57:06 2014 +0100

    Sync Module-CoreList version after CPAN release

M       Porting/Maintainers.pl
-----------------------------------------------------------------------

Summary of changes:
 MANIFEST                                  |   2 +
 META.json                                 |   2 +-
 META.yml                                  |   2 +-
 Porting/Maintainers.pl                    |   8 +-
 cpan/CPAN-Meta/lib/CPAN/Meta.pm           |   4 +-
 cpan/CPAN-Meta/lib/CPAN/Meta/Converter.pm |  24 +-
 cpan/CPAN-Meta/lib/CPAN/Meta/Feature.pm   |   4 +-
 cpan/CPAN-Meta/lib/CPAN/Meta/History.pm   |   4 +-
 cpan/CPAN-Meta/lib/CPAN/Meta/Merge.pm     | 248 +++++++++++
 cpan/CPAN-Meta/lib/CPAN/Meta/Prereqs.pm   |   4 +-
 cpan/CPAN-Meta/lib/CPAN/Meta/Spec.pm      |   4 +-
 cpan/CPAN-Meta/lib/CPAN/Meta/Validator.pm |   4 +-
 cpan/CPAN-Meta/t/merge.t                  | 118 ++++++
 cpan/HTTP-Tiny/lib/HTTP/Tiny.pm           | 658 +++++++++++++++---------------
 cpan/HTTP-Tiny/t/002_croakage.t           |  12 +
 cpan/HTTP-Tiny/t/020_headers.t            |   9 +
 cpan/HTTP-Tiny/t/140_proxy.t              |  14 +
 17 files changed, 766 insertions(+), 355 deletions(-)
 create mode 100644 cpan/CPAN-Meta/lib/CPAN/Meta/Merge.pm
 create mode 100644 cpan/CPAN-Meta/t/merge.t

diff --git a/MANIFEST b/MANIFEST
index 1bb915f..47a0a8d 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -232,6 +232,7 @@ cpan/CPAN/lib/CPAN/Version.pm               Simple math 
with different flavors of version str
 cpan/CPAN-Meta/lib/CPAN/Meta/Converter.pm
 cpan/CPAN-Meta/lib/CPAN/Meta/Feature.pm
 cpan/CPAN-Meta/lib/CPAN/Meta/History.pm
+cpan/CPAN-Meta/lib/CPAN/Meta/Merge.pm
 cpan/CPAN-Meta/lib/CPAN/Meta.pm
 cpan/CPAN-Meta/lib/CPAN/Meta/Prereqs.pm
 cpan/CPAN-Meta/lib/CPAN/Meta/Spec.pm
@@ -296,6 +297,7 @@ cpan/CPAN-Meta/t/data-valid/META-1_0.yml
 cpan/CPAN-Meta/t/data-valid/META-1_1.yml
 cpan/CPAN-Meta/t/data-valid/scalar-meta-spec.yml
 cpan/CPAN-Meta/t/load-bad.t
+cpan/CPAN-Meta/t/merge.t
 cpan/CPAN-Meta/t/meta-obj.t
 cpan/CPAN-Meta/t/no-index.t
 cpan/CPAN-Meta/t/prereqs-finalize.t
diff --git a/META.json b/META.json
index d639e63..24a4d11 100644
--- a/META.json
+++ b/META.json
@@ -4,7 +4,7 @@
       "[email protected]"
    ],
    "dynamic_config" : 1,
-   "generated_by" : "CPAN::Meta version 2.141520",
+   "generated_by" : "CPAN::Meta version 2.142060",
    "license" : [
       "perl_5"
    ],
diff --git a/META.yml b/META.yml
index 474ba24..f521122 100644
--- a/META.yml
+++ b/META.yml
@@ -4,7 +4,7 @@ author:
   - [email protected]
 build_requires: {}
 dynamic_config: 1
-generated_by: 'CPAN::Meta version 2.141520, CPAN::Meta::Converter version 
2.141520'
+generated_by: 'CPAN::Meta version 2.142060, CPAN::Meta::Converter version 
2.142060'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
diff --git a/Porting/Maintainers.pl b/Porting/Maintainers.pl
index d3d4793..bffd16e 100755
--- a/Porting/Maintainers.pl
+++ b/Porting/Maintainers.pl
@@ -282,10 +282,11 @@ use File::Glob qw(:case);
     # Note: When updating CPAN-Meta the META.* files will need to be 
regenerated
     # perl -Icpan/CPAN-Meta/lib Porting/makemeta
     'CPAN::Meta' => {
-        'DISTRIBUTION' => 'DAGOLDEN/CPAN-Meta-2.141520.tar.gz',
+        'DISTRIBUTION' => 'DAGOLDEN/CPAN-Meta-2.142060.tar.gz',
         'FILES'        => q[cpan/CPAN-Meta],
         'EXCLUDED'     => [
             qw[t/00-report-prereqs.t],
+            qw[t/00-report-prereqs.dd],
             qr{t/README-data.txt},
             qr{^xt},
             qr{^history},
@@ -576,10 +577,11 @@ use File::Glob qw(:case);
     },
 
     'HTTP::Tiny' => {
-        'DISTRIBUTION' => 'DAGOLDEN/HTTP-Tiny-0.043.tar.gz',
+        'DISTRIBUTION' => 'DAGOLDEN/HTTP-Tiny-0.047.tar.gz',
         'FILES'        => q[cpan/HTTP-Tiny],
         'EXCLUDED'     => [
             't/00-report-prereqs.t',
+            't/00-report-prereqs.dd',
             't/200_live.t',
             't/200_live_local_ip.t',
             't/210_live_ssl.t',
@@ -780,7 +782,7 @@ use File::Glob qw(:case);
     },
 
     'Module::CoreList' => {
-        'DISTRIBUTION' => 'BINGOS/Module-CoreList-5.021001.tar.gz',
+        'DISTRIBUTION' => 'BINGOS/Module-CoreList-5.021002.tar.gz',
         'FILES'        => q[dist/Module-CoreList],
     },
 
diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta.pm b/cpan/CPAN-Meta/lib/CPAN/Meta.pm
index 1b6723f..0c9048a 100644
--- a/cpan/CPAN-Meta/lib/CPAN/Meta.pm
+++ b/cpan/CPAN-Meta/lib/CPAN/Meta.pm
@@ -2,7 +2,7 @@ use 5.006;
 use strict;
 use warnings;
 package CPAN::Meta;
-our $VERSION = '2.141520'; # VERSION
+our $VERSION = '2.142060'; # VERSION
 
 #pod =head1 SYNOPSIS
 #pod
@@ -641,7 +641,7 @@ CPAN::Meta - the distribution metadata for a CPAN dist
 
 =head1 VERSION
 
-version 2.141520
+version 2.142060
 
 =head1 SYNOPSIS
 
diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta/Converter.pm 
b/cpan/CPAN-Meta/lib/CPAN/Meta/Converter.pm
index 0b2d83c..83b6c59 100644
--- a/cpan/CPAN-Meta/lib/CPAN/Meta/Converter.pm
+++ b/cpan/CPAN-Meta/lib/CPAN/Meta/Converter.pm
@@ -2,7 +2,7 @@ use 5.006;
 use strict;
 use warnings;
 package CPAN::Meta::Converter;
-our $VERSION = '2.141520'; # VERSION
+our $VERSION = '2.142060'; # VERSION
 
 #pod =head1 SYNOPSIS
 #pod
@@ -741,12 +741,15 @@ sub _provides {
 }
 
 sub _convert {
-  my ($data, $spec, $to_version) = @_;
+  my ($data, $spec, $to_version, $is_fragment) = @_;
 
   my $new_data = {};
   for my $key ( keys %$spec ) {
     next if $key eq ':custom' || $key eq ':drop';
     next unless my $fcn = $spec->{$key};
+    if ( $is_fragment && $key eq 'generated_by' ) {
+      $fcn = \&_keep;
+    }
     die "spec for '$key' is not a coderef"
       unless ref $fcn && ref $fcn eq 'CODE';
     my $new_value = $fcn->($data->{$key}, $key, $data, $to_version);
@@ -1384,13 +1387,14 @@ sub convert {
   my $args = { %args };
 
   my $new_version = $args->{version} || $HIGHEST;
+  my $is_fragment = $args->{is_fragment};
 
   my ($old_version) = $self->{spec};
   my $converted = _dclone($self->{data});
 
   if ( $old_version == $new_version ) {
-    $converted = _convert( $converted, $cleanup{$old_version}, $old_version );
-    unless ( $args->{no_validation} ) {
+    $converted = _convert( $converted, $cleanup{$old_version}, $old_version, 
$is_fragment );
+    unless ( $args->{is_fragment} ) {
       my $cmv = CPAN::Meta::Validator->new( $converted );
       unless ( $cmv->is_valid ) {
         my $errs = join("\n", $cmv->errors);
@@ -1405,8 +1409,8 @@ sub convert {
       next if $vers[$i] > $old_version;
       last if $vers[$i+1] < $new_version;
       my $spec_string = "$vers[$i+1]-from-$vers[$i]";
-      $converted = _convert( $converted, $down_convert{$spec_string}, 
$vers[$i+1] );
-      unless ( $args->{no_validation} ) {
+      $converted = _convert( $converted, $down_convert{$spec_string}, 
$vers[$i+1], $is_fragment );
+      unless ( $args->{is_fragment} ) {
         my $cmv = CPAN::Meta::Validator->new( $converted );
         unless ( $cmv->is_valid ) {
           my $errs = join("\n", $cmv->errors);
@@ -1422,8 +1426,8 @@ sub convert {
       next if $vers[$i] < $old_version;
       last if $vers[$i+1] > $new_version;
       my $spec_string = "$vers[$i+1]-from-$vers[$i]";
-      $converted = _convert( $converted, $up_convert{$spec_string}, 
$vers[$i+1] );
-      unless ( $args->{no_validation} ) {
+      $converted = _convert( $converted, $up_convert{$spec_string}, 
$vers[$i+1], $is_fragment );
+      unless ( $args->{is_fragment} ) {
         my $cmv = CPAN::Meta::Validator->new( $converted );
         unless ( $cmv->is_valid ) {
           my $errs = join("\n", $cmv->errors);
@@ -1453,7 +1457,7 @@ sub upgrade_fragment {
     grep { defined }
     map { $fragments_generate{$old_version}{$_} }
     keys %{ $self->{data} };
-  my $converted = $self->convert( version => $HIGHEST, no_validation => 1 );
+  my $converted = $self->convert( version => $HIGHEST, is_fragment => 1 );
   for my $key ( keys %$converted ) {
     next if $key =~ /^x_/i || $key eq 'meta-spec';
     delete $converted->{$key} unless $expected{$key};
@@ -1475,7 +1479,7 @@ CPAN::Meta::Converter - Convert CPAN distribution 
metadata structures
 
 =head1 VERSION
 
-version 2.141520
+version 2.142060
 
 =head1 SYNOPSIS
 
diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta/Feature.pm 
b/cpan/CPAN-Meta/lib/CPAN/Meta/Feature.pm
index 52e3e93..db4f1ce 100644
--- a/cpan/CPAN-Meta/lib/CPAN/Meta/Feature.pm
+++ b/cpan/CPAN-Meta/lib/CPAN/Meta/Feature.pm
@@ -2,7 +2,7 @@ use 5.006;
 use strict;
 use warnings;
 package CPAN::Meta::Feature;
-our $VERSION = '2.141520'; # VERSION
+our $VERSION = '2.142060'; # VERSION
 
 use CPAN::Meta::Prereqs;
 
@@ -78,7 +78,7 @@ CPAN::Meta::Feature - an optional feature provided by a CPAN 
distribution
 
 =head1 VERSION
 
-version 2.141520
+version 2.142060
 
 =head1 DESCRIPTION
 
diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta/History.pm 
b/cpan/CPAN-Meta/lib/CPAN/Meta/History.pm
index c28273a..9d6c660 100644
--- a/cpan/CPAN-Meta/lib/CPAN/Meta/History.pm
+++ b/cpan/CPAN-Meta/lib/CPAN/Meta/History.pm
@@ -3,7 +3,7 @@ use 5.006;
 use strict;
 use warnings;
 package CPAN::Meta::History;
-our $VERSION = '2.141520'; # VERSION
+our $VERSION = '2.142060'; # VERSION
 
 1;
 
@@ -21,7 +21,7 @@ CPAN::Meta::History - history of CPAN Meta Spec changes
 
 =head1 VERSION
 
-version 2.141520
+version 2.142060
 
 =head1 DESCRIPTION
 
diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta/Merge.pm 
b/cpan/CPAN-Meta/lib/CPAN/Meta/Merge.pm
new file mode 100644
index 0000000..5648d77
--- /dev/null
+++ b/cpan/CPAN-Meta/lib/CPAN/Meta/Merge.pm
@@ -0,0 +1,248 @@
+package CPAN::Meta::Merge;
+
+use strict;
+use warnings;
+
+our $VERSION = '2.142060'; # VERSION
+
+use Carp qw/croak/;
+use Scalar::Util qw/blessed/;
+use CPAN::Meta::Converter;
+
+sub _identical {
+  my ($left, $right, $path) = @_;
+  croak "Can't merge attribute " . join '.', @{$path} unless $left eq $right;
+  return $left;
+}
+
+sub _merge {
+  my ($current, $next, $mergers, $path) = @_;
+  for my $key (keys %{$next}) {
+    if (not exists $current->{$key}) {
+      $current->{$key} = $next->{$key};
+    }
+    elsif (my $merger = $mergers->{$key}) {
+      $current->{$key} = $merger->($current->{$key}, $next->{$key}, [ 
@{$path}, $key ]);
+    }
+    elsif ($merger = $mergers->{':default'}) {
+      $current->{$key} = $merger->($current->{$key}, $next->{$key}, [ 
@{$path}, $key ]);
+    }
+    else {
+      croak sprintf "Can't merge unknown attribute '%s'", join '.', @{$path}, 
$key;
+    }
+  }
+  return $current;
+}
+
+sub _uniq {
+  my %seen = ();
+  return grep { not $seen{$_}++ } @_;
+}
+
+sub _set_addition {
+  my ($left, $right) = @_;
+  return [ +_uniq(@{$left}, @{$right}) ];
+}
+
+sub _uniq_map {
+  my ($left, $right, $path) = @_;
+  for my $key (keys %{$right}) {
+    if (not exists $left->{$key}) {
+      $left->{$key} = $right->{$key};
+    }
+    else {
+      croak 'Duplication of element ' . join '.', @{$path}, $key;
+    }
+  }
+  return $left;
+}
+
+sub _improvize {
+  my ($left, $right, $path) = @_;
+  my ($name) = reverse @{$path};
+  if ($name =~ /^x_/) {
+    if (ref($left) eq 'ARRAY') {
+      return _set_addition($left, $right, $path);
+    }
+    elsif (ref($left) eq 'HASH') {
+      return _uniq_map($left, $right, $path);
+    }
+    else {
+      return _identical($left, $right, $path);
+    }
+  }
+  croak sprintf "Can't merge '%s'", join '.', @{$path};
+}
+
+my %default = (
+  abstract       => \&_identical,
+  author         => \&_set_addition,
+  dynamic_config => sub {
+    my ($left, $right) = @_;
+    return $left || $right;
+  },
+  generated_by => sub {
+    my ($left, $right) = @_;
+    return join ', ', _uniq(split(/, /, $left), split(/, /, $right));
+  },
+  license     => \&_set_addition,
+  'meta-spec' => {
+    version => \&_identical,
+    url     => \&_identical
+  },
+  name              => \&_identical,
+  release_status    => \&_identical,
+  version           => \&_identical,
+  description       => \&_identical,
+  keywords          => \&_set_addition,
+  no_index          => { map { ($_ => \&_set_addition) } qw/file directory 
package namespace/ },
+  optional_features => \&_uniq_map,
+  prereqs           => sub {
+    require CPAN::Meta::Prereqs;
+    my ($left, $right) = map { CPAN::Meta::Prereqs->new($_) } @_[0,1];
+    return $left->with_merged_prereqs($right)->as_string_hash;
+  },
+  provides  => \&_uniq_map,
+  resources => {
+    license    => \&_set_addition,
+    homepage   => \&_identical,
+    bugtracker => \&_uniq_map,
+    repository => \&_uniq_map,
+    ':default' => \&_improvize,
+  },
+  ':default' => \&_improvize,
+);
+
+sub new {
+  my ($class, %arguments) = @_;
+  croak 'default version required' if not exists $arguments{default_version};
+  my %mapping = %default;
+  my %extra = %{ $arguments{extra_mappings} || {} };
+  for my $key (keys %extra) {
+    if (ref($mapping{$key}) eq 'HASH') {
+      $mapping{$key} = { %{ $mapping{$key} }, %{ $extra{$key} } };
+    }
+    else {
+      $mapping{$key} = $extra{$key};
+    }
+  }
+  return bless {
+    default_version => $arguments{default_version},
+    mapping => _coerce_mapping(\%mapping, []),
+  }, $class;
+}
+
+my %coderef_for = (
+  set_addition => \&_set_addition,
+  uniq_map     => \&_uniq_map,
+  identical    => \&_identical,
+  improvize    => \&_improvize,
+);
+
+sub _coerce_mapping {
+  my ($orig, $map_path) = @_;
+  my %ret;
+  for my $key (keys %{$orig}) {
+    my $value = $orig->{$key};
+    if (ref($orig->{$key}) eq 'CODE') {
+      $ret{$key} = $value;
+    }
+    elsif (ref($value) eq 'HASH') {
+      my $mapping = _coerce_mapping($value, [ @{$map_path}, $key ]);
+      $ret{$key} = sub {
+        my ($left, $right, $path) = @_;
+        return _merge($left, $right, $mapping, [ @{$path}, $key ]);
+      };
+    }
+    elsif ($coderef_for{$value}) {
+      $ret{$key} = $coderef_for{$value};
+    }
+    else {
+      croak "Don't know what to do with " . join '.', @{$map_path}, $key;
+    }
+  }
+  return \%ret;
+}
+
+sub merge {
+  my ($self, @items) = @_;
+  my $current = {};
+  for my $next (@items) {
+    if ( blessed($next) && $next->isa('CPAN::Meta') ) {
+      $next = $next->as_string_hash;
+    }
+    elsif ( ref($next) eq 'HASH' ) {
+      my $cmc = CPAN::Meta::Converter->new(
+        $next, default_version => $self->{default_version}
+      );
+      $next = $cmc->upgrade_fragment;
+    }
+    else {
+      croak "Don't know how to merge '$next'";
+    }
+    $current = _merge($current, $next, $self->{mapping}, []);
+  }
+  return $current;
+}
+
+1;
+
+# ABSTRACT: Merging CPAN Meta fragments
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+CPAN::Meta::Merge - Merging CPAN Meta fragments
+
+=head1 VERSION
+
+version 2.142060
+
+=head1 SYNOPSIS
+
+ my $merger = CPAN::Meta::Merge->new(default_version => "2");
+ my $meta = $merger->merge($base, @additional);
+
+=head1 DESCRIPTION
+
+=head1 METHODS
+
+=head2 new
+
+This creates a CPAN::Meta::Merge object. It takes one mandatory named
+argument, C<version>, declaring the version of the meta-spec that must be
+used for the merge. It can optionally take an C<extra_mappings> argument
+that allows one to add additional merging functions for specific elements.
+
+=head2 merge(@fragments)
+
+Merge all C<@fragments> together. It will accept both CPAN::Meta objects and
+(possibly incomplete) hashrefs of metadata.
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+David Golden <[email protected]>
+
+=item *
+
+Ricardo Signes <[email protected]>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2010 by David Golden and Ricardo Signes.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta/Prereqs.pm 
b/cpan/CPAN-Meta/lib/CPAN/Meta/Prereqs.pm
index 0535f74..60248b9 100644
--- a/cpan/CPAN-Meta/lib/CPAN/Meta/Prereqs.pm
+++ b/cpan/CPAN-Meta/lib/CPAN/Meta/Prereqs.pm
@@ -2,7 +2,7 @@ use 5.006;
 use strict;
 use warnings;
 package CPAN::Meta::Prereqs;
-our $VERSION = '2.141520'; # VERSION
+our $VERSION = '2.142060'; # VERSION
 
 #pod =head1 DESCRIPTION
 #pod
@@ -286,7 +286,7 @@ CPAN::Meta::Prereqs - a set of distribution prerequisites 
by phase and type
 
 =head1 VERSION
 
-version 2.141520
+version 2.142060
 
 =head1 DESCRIPTION
 
diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta/Spec.pm 
b/cpan/CPAN-Meta/lib/CPAN/Meta/Spec.pm
index ce5eafb..873580d 100644
--- a/cpan/CPAN-Meta/lib/CPAN/Meta/Spec.pm
+++ b/cpan/CPAN-Meta/lib/CPAN/Meta/Spec.pm
@@ -7,7 +7,7 @@ use 5.006;
 use strict;
 use warnings;
 package CPAN::Meta::Spec;
-our $VERSION = '2.141520'; # VERSION
+our $VERSION = '2.142060'; # VERSION
 
 1;
 
@@ -28,7 +28,7 @@ CPAN::Meta::Spec - specification for CPAN distribution 
metadata
 
 =head1 VERSION
 
-version 2.141520
+version 2.142060
 
 =head1 SYNOPSIS
 
diff --git a/cpan/CPAN-Meta/lib/CPAN/Meta/Validator.pm 
b/cpan/CPAN-Meta/lib/CPAN/Meta/Validator.pm
index 21cf295..7f08de7 100644
--- a/cpan/CPAN-Meta/lib/CPAN/Meta/Validator.pm
+++ b/cpan/CPAN-Meta/lib/CPAN/Meta/Validator.pm
@@ -2,7 +2,7 @@ use 5.006;
 use strict;
 use warnings;
 package CPAN::Meta::Validator;
-our $VERSION = '2.141520'; # VERSION
+our $VERSION = '2.142060'; # VERSION
 
 #pod =head1 SYNOPSIS
 #pod
@@ -997,7 +997,7 @@ CPAN::Meta::Validator - validate CPAN distribution metadata 
structures
 
 =head1 VERSION
 
-version 2.141520
+version 2.142060
 
 =head1 SYNOPSIS
 
diff --git a/cpan/CPAN-Meta/t/merge.t b/cpan/CPAN-Meta/t/merge.t
new file mode 100644
index 0000000..77ae09f
--- /dev/null
+++ b/cpan/CPAN-Meta/t/merge.t
@@ -0,0 +1,118 @@
+#! perl
+
+use strict;
+use warnings;
+
+use Test::More;
+use CPAN::Meta::Merge;
+
+my %base = (
+       abstract => 'This is a test',
+       author => ['A.U. Thor'],
+       generated_by => 'Myself',
+       license => [ 'perl_5' ],
+       resources => {
+               license => [ 'http://dev.perl.org/licenses/' ],
+       },
+       prereqs => {
+               runtime => {
+                       requires => {
+                               Foo => '0',
+                       },
+               },
+       },
+       dynamic_config => 0,
+       provides => {
+               Baz => {
+                       file => 'lib/Baz.pm',
+               },
+       },
+       'meta-spec' => {
+               url => "http://search.cpan.org/perldoc?CPAN::Meta::Spec";,
+               version => 2,
+       },
+);
+
+my %first = (
+       author => [ 'I.M. Poster' ],
+       generated_by => 'Some other guy',
+       license => [ 'bsd' ],
+       resources => {
+               license => [ 'http://opensource.org/licenses/bsd-license.php' ],
+       },
+       prereqs => {
+               runtime => {
+                       requires => {
+                               Foo => '< 1',
+                       },
+                       recommends => {
+                               Bar => '3.14',
+                       },
+               },
+               test => {
+                       requires => {
+                               'Test::Bar' => 0,
+                       },
+               },
+       },
+       dynamic_config => 1,
+       provides => {
+               Quz => {
+                       file => 'lib/Quz.pm',
+               },
+       },
+);
+my %first_expected = (
+       abstract => 'This is a test',
+       author => [ 'A.U. Thor', 'I.M. Poster' ],
+       generated_by => 'Myself, Some other guy',
+       license => [ 'perl_5', 'bsd' ],
+       resources => {
+               license => [ 'http://dev.perl.org/licenses/', 
'http://opensource.org/licenses/bsd-license.php' ],
+       },
+       prereqs => {
+               runtime => {
+                       requires => {
+                               Foo => '>= 0, < 1',
+                       },
+                       recommends => {
+                               Bar => '3.14',
+                       },
+               },
+               test => {
+                       requires => {
+                               'Test::Bar' => 0,
+                       },
+               },
+       },
+       provides => {
+               Baz => {
+                       file => 'lib/Baz.pm',
+               },
+               Quz => {
+                       file => 'lib/Quz.pm',
+               },
+       },
+       dynamic_config => 1,
+       'meta-spec' => {
+               url => "http://search.cpan.org/perldoc?CPAN::Meta::Spec";,
+               version => 2,
+       },
+);
+
+my $merger = CPAN::Meta::Merge->new(default_version => '2');
+
+my $first_result = $merger->merge(\%base, \%first);
+
+is_deeply($first_result, \%first_expected, 'First result is as expected');
+
+is_deeply($merger->merge(\%base, { abstract => 'This is a test' }), \%base, 
'Can merge in identical abstract');
+my $failure = eval { $merger->merge(\%base, { abstract => 'And now for 
something else' }) };
+is($failure, undef, 'Trying to merge different author gives an exception');
+like $@, qr/^Can't merge attribute abstract /, 'Exception looks right';
+
+my $failure2 = eval { $merger->merge(\%base, { provides => { Baz => { file => 
'Baz.pm' } } }) };
+is($failure2, undef, 'Trying to merge different author gives an exception');
+like $@, qr/^Duplication of element provides\.Baz /, 'Exception looks right';
+
+done_testing();
diff --git a/cpan/HTTP-Tiny/lib/HTTP/Tiny.pm b/cpan/HTTP-Tiny/lib/HTTP/Tiny.pm
index e348753..06c0961 100644
--- a/cpan/HTTP-Tiny/lib/HTTP/Tiny.pm
+++ b/cpan/HTTP-Tiny/lib/HTTP/Tiny.pm
@@ -3,60 +3,63 @@ package HTTP::Tiny;
 use strict;
 use warnings;
 # ABSTRACT: A small, simple, correct HTTP/1.1 client
-our $VERSION = '0.043'; # VERSION
+our $VERSION = '0.047'; # VERSION
 
 use Carp ();
 
-# =method new
-#
-#     $http = HTTP::Tiny->new( %attributes );
-#
-# This constructor returns a new HTTP::Tiny object.  Valid attributes include:
-#
-# =for :list
-# * C<agent>
-# A user-agent string (defaults to 'HTTP-Tiny/$VERSION'). If C<agent> ends in 
a space character, the default user-agent string is appended.
-# * C<cookie_jar>
-# An instance of L<HTTP::CookieJar> or equivalent class that supports the 
C<add> and C<cookie_header> methods
-# * C<default_headers>
-# A hashref of default headers to apply to requests
-# * C<local_address>
-# The local IP address to bind to
-# * C<keep_alive>
-# Whether to reuse the last connection (if for the same scheme, host and port) 
(defaults to 1)
-# * C<max_redirect>
-# Maximum number of redirects allowed (defaults to 5)
-# * C<max_size>
-# Maximum response size (only when not using a data callback).  If defined, 
responses larger than this will return an exception.
-# * C<http_proxy>
-# URL of a proxy server to use for HTTP connections (default is 
C<$ENV{http_proxy}> if set)
-# * C<https_proxy>
-# URL of a proxy server to use for HTTPS connections (default is 
C<$ENV{https_proxy}> if set)
-# * C<proxy>
-# URL of a generic proxy server for both HTTP and HTTPS connections (default 
is C<$ENV{all_proxy}> if set)
-# * C<no_proxy>
-# List of domain suffixes that should not be proxied.  Must be a 
comma-separated string or an array reference. (default is C<$ENV{no_proxy}>)
-# * C<timeout>
-# Request timeout in seconds (default is 60)
-# * C<verify_SSL>
-# A boolean that indicates whether to validate the SSL certificate of an 
C<https>
-# connection (default is false)
-# * C<SSL_options>
-# A hashref of C<SSL_*> options to pass through to L<IO::Socket::SSL>
-#
-# Exceptions from C<max_size>, C<timeout> or other errors will result in a
-# pseudo-HTTP status code of 599 and a reason of "Internal Exception". The
-# content field in the response will contain the text of the exception.
-#
-# The C<keep_alive> parameter enables a persistent connection, but only to a
-# single destination scheme, host and port.  Also, if any connection-relevant
-# attributes are modified, a persistent connection will be dropped.  If you 
want
-# persistent connections across multiple destinations, use multiple HTTP::Tiny
-# objects.
-#
-# See L</SSL SUPPORT> for more on the C<verify_SSL> and C<SSL_options> 
attributes.
-#
-# =cut
+#pod =method new
+#pod
+#pod     $http = HTTP::Tiny->new( %attributes );
+#pod
+#pod This constructor returns a new HTTP::Tiny object.  Valid attributes 
include:
+#pod
+#pod =for :list
+#pod * C<agent> —
+#pod     A user-agent string (defaults to 'HTTP-Tiny/$VERSION'). If C<agent> 
— ends in a space character, the default user-agent string is appended.
+#pod * C<cookie_jar> —
+#pod     An instance of L<HTTP::CookieJar> — or equivalent class that 
supports the C<add> and C<cookie_header> methods
+#pod * C<default_headers> —
+#pod     A hashref of default headers to apply to requests
+#pod * C<local_address> —
+#pod     The local IP address to bind to
+#pod * C<keep_alive> —
+#pod     Whether to reuse the last connection (if for the same scheme, host 
and port) (defaults to 1)
+#pod * C<max_redirect> —
+#pod     Maximum number of redirects allowed (defaults to 5)
+#pod * C<max_size> —
+#pod     Maximum response size (only when not using a data callback).  If 
defined, responses larger than this will return an exception.
+#pod * C<http_proxy> —
+#pod     URL of a proxy server to use for HTTP connections (default is 
C<$ENV{http_proxy}> — if set)
+#pod * C<https_proxy> —
+#pod     URL of a proxy server to use for HTTPS connections (default is 
C<$ENV{https_proxy}> — if set)
+#pod * C<proxy> —
+#pod     URL of a generic proxy server for both HTTP and HTTPS connections 
(default is C<$ENV{all_proxy}> — if set)
+#pod * C<no_proxy> —
+#pod     List of domain suffixes that should not be proxied.  Must be a 
comma-separated string or an array reference. (default is C<$ENV{no_proxy}> —)
+#pod * C<timeout> —
+#pod     Request timeout in seconds (default is 60)
+#pod * C<verify_SSL> —
+#pod     A boolean that indicates whether to validate the SSL certificate of 
an C<https> —
+#pod     connection (default is false)
+#pod * C<SSL_options> —
+#pod     A hashref of C<SSL_*> — options to pass through to 
L<IO::Socket::SSL>
+#pod
+#pod Passing an explicit C<undef> for C<proxy>, C<http_proxy> or 
C<https_proxy> will
+#pod prevent getting the corresponding proxies from the environment.
+#pod
+#pod Exceptions from C<max_size>, C<timeout> or other errors will result in a
+#pod pseudo-HTTP status code of 599 and a reason of "Internal Exception". The
+#pod content field in the response will contain the text of the exception.
+#pod
+#pod The C<keep_alive> parameter enables a persistent connection, but only to a
+#pod single destination scheme, host and port.  Also, if any 
connection-relevant
+#pod attributes are modified, a persistent connection will be dropped.  If you 
want
+#pod persistent connections across multiple destinations, use multiple 
HTTP::Tiny
+#pod objects.
+#pod
+#pod See L</SSL SUPPORT> for more on the C<verify_SSL> and C<SSL_options> 
attributes.
+#pod
+#pod =cut
 
 my @attributes;
 BEGIN {
@@ -120,36 +123,45 @@ sub new {
 sub _set_proxies {
     my ($self) = @_;
 
-    if (! $self->{proxy} ) {
+    # get proxies from %ENV only if not provided; explicit undef will disable
+    # getting proxies from the environment
+
+    # generic proxy
+    if (! exists $self->{proxy} ) {
         $self->{proxy} = $ENV{all_proxy} || $ENV{ALL_PROXY};
-        if ( defined $self->{proxy} ) {
-            $self->_split_proxy( 'generic proxy' => $self->{proxy} ); # 
validate
-        }
-        else {
-            delete $self->{proxy};
-        }
     }
 
-    if (! $self->{http_proxy} ) {
+    if ( defined $self->{proxy} ) {
+        $self->_split_proxy( 'generic proxy' => $self->{proxy} ); # validate
+    }
+    else {
+        delete $self->{proxy};
+    }
+
+    # http proxy
+    if (! exists $self->{http_proxy} ) {
         $self->{http_proxy} = $ENV{http_proxy} || $self->{proxy};
-        if ( defined $self->{http_proxy} ) {
-            $self->_split_proxy( http_proxy => $self->{http_proxy} ); # 
validate
-            $self->{_has_proxy}{http} = 1;
-        }
-        else {
-            delete $self->{http_proxy};
-        }
     }
 
-    if (! $self->{https_proxy} ) {
+    if ( defined $self->{http_proxy} ) {
+        $self->_split_proxy( http_proxy => $self->{http_proxy} ); # validate
+        $self->{_has_proxy}{http} = 1;
+    }
+    else {
+        delete $self->{http_proxy};
+    }
+
+    # https proxy
+    if (! exists $self->{https_proxy} ) {
         $self->{https_proxy} = $ENV{https_proxy} || $ENV{HTTPS_PROXY} || 
$self->{proxy};
-        if ( $self->{https_proxy} ) {
-            $self->_split_proxy( https_proxy => $self->{https_proxy} ); # 
validate
-            $self->{_has_proxy}{https} = 1;
-        }
-        else {
-            delete $self->{https_proxy};
-        }
+    }
+
+    if ( $self->{https_proxy} ) {
+        $self->_split_proxy( https_proxy => $self->{https_proxy} ); # validate
+        $self->{_has_proxy}{https} = 1;
+    }
+    else {
+        delete $self->{https_proxy};
     }
 
     # Split no_proxy to array reference if not provided as such
@@ -161,19 +173,19 @@ sub _set_proxies {
     return;
 }
 
-# =method get|head|put|post|delete
-#
-#     $response = $http->get($url);
-#     $response = $http->get($url, \%options);
-#     $response = $http->head($url);
-#
-# These methods are shorthand for calling C<request()> for the given method.  
The
-# URL must have unsafe characters escaped and international domain names 
encoded.
-# See C<request()> for valid options and a description of the response.
-#
-# The C<success> field of the response will be true if the status code is 2XX.
-#
-# =cut
+#pod =method get|head|put|post|delete
+#pod
+#pod     $response = $http->get($url);
+#pod     $response = $http->get($url, \%options);
+#pod     $response = $http->head($url);
+#pod
+#pod These methods are shorthand for calling C<request()> for the given 
method.  The
+#pod URL must have unsafe characters escaped and international domain names 
encoded.
+#pod See C<request()> for valid options and a description of the response.
+#pod
+#pod The C<success> field of the response will be true if the status code is 
2XX.
+#pod
+#pod =cut
 
 for my $sub_name ( qw/get head put post delete/ ) {
     my $req_method = uc $sub_name;
@@ -188,25 +200,25 @@ for my $sub_name ( qw/get head put post delete/ ) {
 HERE
 }
 
-# =method post_form
-#
-#     $response = $http->post_form($url, $form_data);
-#     $response = $http->post_form($url, $form_data, \%options);
-#
-# This method executes a C<POST> request and sends the key/value pairs from a
-# form data hash or array reference to the given URL with a C<content-type> of
-# C<application/x-www-form-urlencoded>.  If data is provided as an array
-# reference, the order is preserved; if provided as a hash reference, the terms
-# are sorted on key and value for consistency.  See documentation for the
-# C<www_form_urlencode> method for details on the encoding.
-#
-# The URL must have unsafe characters escaped and international domain names
-# encoded.  See C<request()> for valid options and a description of the 
response.
-# Any C<content-type> header or content in the options hashref will be ignored.
-#
-# The C<success> field of the response will be true if the status code is 2XX.
-#
-# =cut
+#pod =method post_form
+#pod
+#pod     $response = $http->post_form($url, $form_data);
+#pod     $response = $http->post_form($url, $form_data, \%options);
+#pod
+#pod This method executes a C<POST> request and sends the key/value pairs from 
a
+#pod form data hash or array reference to the given URL with a C<content-type> 
of
+#pod C<application/x-www-form-urlencoded>.  If data is provided as an array
+#pod reference, the order is preserved; if provided as a hash reference, the 
terms
+#pod are sorted on key and value for consistency.  See documentation for the
+#pod C<www_form_urlencode> method for details on the encoding.
+#pod
+#pod The URL must have unsafe characters escaped and international domain names
+#pod encoded.  See C<request()> for valid options and a description of the 
response.
+#pod Any C<content-type> header or content in the options hashref will be 
ignored.
+#pod
+#pod The C<success> field of the response will be true if the status code is 
2XX.
+#pod
+#pod =cut
 
 sub post_form {
     my ($self, $url, $data, $args) = @_;
@@ -230,28 +242,28 @@ sub post_form {
     );
 }
 
-# =method mirror
-#
-#     $response = $http->mirror($url, $file, \%options)
-#     if ( $response->{success} ) {
-#         print "$file is up to date\n";
-#     }
-#
-# Executes a C<GET> request for the URL and saves the response body to the file
-# name provided.  The URL must have unsafe characters escaped and international
-# domain names encoded.  If the file already exists, the request will include 
an
-# C<If-Modified-Since> header with the modification timestamp of the file.  You
-# may specify a different C<If-Modified-Since> header yourself in the C<<
-# $options->{headers} >> hash.
-#
-# The C<success> field of the response will be true if the status code is 2XX
-# or if the status code is 304 (unmodified).
-#
-# If the file was modified and the server response includes a properly
-# formatted C<Last-Modified> header, the file modification time will
-# be updated accordingly.
-#
-# =cut
+#pod =method mirror
+#pod
+#pod     $response = $http->mirror($url, $file, \%options)
+#pod     if ( $response->{success} ) {
+#pod         print "$file is up to date\n";
+#pod     }
+#pod
+#pod Executes a C<GET> request for the URL and saves the response body to the 
file
+#pod name provided.  The URL must have unsafe characters escaped and 
international
+#pod domain names encoded.  If the file already exists, the request will 
include an
+#pod C<If-Modified-Since> header with the modification timestamp of the file.  
You
+#pod may specify a different C<If-Modified-Since> header yourself in the C<<
+#pod $options->{headers} >> hash.
+#pod
+#pod The C<success> field of the response will be true if the status code is 
2XX
+#pod or if the status code is 304 (unmodified).
+#pod
+#pod If the file was modified and the server response includes a properly
+#pod formatted C<Last-Modified> header, the file modification time will
+#pod be updated accordingly.
+#pod
+#pod =cut
 
 sub mirror {
     my ($self, $url, $file, $args) = @_;
@@ -284,86 +296,90 @@ sub mirror {
     return $response;
 }
 
-# =method request
-#
-#     $response = $http->request($method, $url);
-#     $response = $http->request($method, $url, \%options);
-#
-# Executes an HTTP request of the given method type ('GET', 'HEAD', 'POST',
-# 'PUT', etc.) on the given URL.  The URL must have unsafe characters escaped 
and
-# international domain names encoded.
-#
-# If the URL includes a "user:password" stanza, they will be used for 
Basic-style
-# authorization headers.  (Authorization headers will not be included in a
-# redirected request.) For example:
-#
-#     $http->request('GET', 'http://Aladdin:open [email protected]/');
-#
-# If the "user:password" stanza contains reserved characters, they must
-# be percent-escaped:
-#
-#     $http->request('GET', 'http://john%40example.com:[email protected]/');
-#
-# A hashref of options may be appended to modify the request.
-#
-# Valid options are:
-#
-# =for :list
-# * C<headers>
-# A hashref containing headers to include with the request.  If the value for
-# a header is an array reference, the header will be output multiple times with
-# each value in the array.  These headers over-write any default headers.
-# * C<content>
-# A scalar to include as the body of the request OR a code reference
-# that will be called iteratively to produce the body of the request
-# * C<trailer_callback>
-# A code reference that will be called if it exists to provide a hashref
-# of trailing headers (only used with chunked transfer-encoding)
-# * C<data_callback>
-# A code reference that will be called for each chunks of the response
-# body received.
-#
-# If the C<content> option is a code reference, it will be called iteratively
-# to provide the content body of the request.  It should return the empty
-# string or undef when the iterator is exhausted.
-#
-# If the C<content> option is the empty string, no C<content-type> or
-# C<content-length> headers will be generated.
-#
-# If the C<data_callback> option is provided, it will be called iteratively 
until
-# the entire response body is received.  The first argument will be a string
-# containing a chunk of the response body, the second argument will be the
-# in-progress response hash reference, as described below.  (This allows
-# customizing the action of the callback based on the C<status> or C<headers>
-# received prior to the content body.)
-#
-# The C<request> method returns a hashref containing the response.  The hashref
-# will have the following keys:
-#
-# =for :list
-# * C<success>
-# Boolean indicating whether the operation returned a 2XX status code
-# * C<url>
-# URL that provided the response. This is the URL of the request unless
-# there were redirections, in which case it is the last URL queried
-# in a redirection chain
-# * C<status>
-# The HTTP status code of the response
-# * C<reason>
-# The response phrase returned by the server
-# * C<content>
-# The body of the response.  If the response does not have any content
-# or if a data callback is provided to consume the response body,
-# this will be the empty string
-# * C<headers>
-# A hashref of header fields.  All header field names will be normalized
-# to be lower case. If a header is repeated, the value will be an arrayref;
-# it will otherwise be a scalar string containing the value
-#
-# On an exception during the execution of the request, the C<status> field will
-# contain 599, and the C<content> field will contain the text of the exception.
-#
-# =cut
+#pod =method request
+#pod
+#pod     $response = $http->request($method, $url);
+#pod     $response = $http->request($method, $url, \%options);
+#pod
+#pod Executes an HTTP request of the given method type ('GET', 'HEAD', 'POST',
+#pod 'PUT', etc.) on the given URL.  The URL must have unsafe characters 
escaped and
+#pod international domain names encoded.
+#pod
+#pod If the URL includes a "user:password" stanza, they will be used for 
Basic-style
+#pod authorization headers.  (Authorization headers will not be included in a
+#pod redirected request.) For example:
+#pod
+#pod     $http->request('GET', 'http://Aladdin:open [email protected]/');
+#pod
+#pod If the "user:password" stanza contains reserved characters, they must
+#pod be percent-escaped:
+#pod
+#pod     $http->request('GET', 
'http://john%40example.com:[email protected]/');
+#pod
+#pod A hashref of options may be appended to modify the request.
+#pod
+#pod Valid options are:
+#pod
+#pod =for :list
+#pod * C<headers> —
+#pod     A hashref containing headers to include with the request.  If the 
value for
+#pod     a header is an array reference, the header will be output multiple 
times with
+#pod     each value in the array.  These headers over-write any default 
headers.
+#pod * C<content> —
+#pod     A scalar to include as the body of the request OR a code reference
+#pod     that will be called iteratively to produce the body of the request
+#pod * C<trailer_callback> —
+#pod     A code reference that will be called if it exists to provide a hashref
+#pod     of trailing headers (only used with chunked transfer-encoding)
+#pod * C<data_callback> —
+#pod     A code reference that will be called for each chunks of the response
+#pod     body received.
+#pod
+#pod The C<Host> header is generated from the URL in accordance with RFC 2616. 
 It
+#pod is a fatal error to specify C<Host> in the C<headers> option.  Other 
headers
+#pod may be ignored or overwritten if necessary for transport compliance.
+#pod
+#pod If the C<content> option is a code reference, it will be called 
iteratively
+#pod to provide the content body of the request.  It should return the empty
+#pod string or undef when the iterator is exhausted.
+#pod
+#pod If the C<content> option is the empty string, no C<content-type> or
+#pod C<content-length> headers will be generated.
+#pod
+#pod If the C<data_callback> option is provided, it will be called iteratively 
until
+#pod the entire response body is received.  The first argument will be a string
+#pod containing a chunk of the response body, the second argument will be the
+#pod in-progress response hash reference, as described below.  (This allows
+#pod customizing the action of the callback based on the C<status> or 
C<headers>
+#pod received prior to the content body.)
+#pod
+#pod The C<request> method returns a hashref containing the response.  The 
hashref
+#pod will have the following keys:
+#pod
+#pod =for :list
+#pod * C<success> —
+#pod     Boolean indicating whether the operation returned a 2XX status code
+#pod * C<url> —
+#pod     URL that provided the response. This is the URL of the request unless
+#pod     there were redirections, in which case it is the last URL queried
+#pod     in a redirection chain
+#pod * C<status> —
+#pod     The HTTP status code of the response
+#pod * C<reason> —
+#pod     The response phrase returned by the server
+#pod * C<content> —
+#pod     The body of the response.  If the response does not have any content
+#pod     or if a data callback is provided to consume the response body,
+#pod     this will be the empty string
+#pod * C<headers> —
+#pod     A hashref of header fields.  All header field names will be normalized
+#pod     to be lower case. If a header is repeated, the value will be an 
arrayref;
+#pod     it will otherwise be a scalar string containing the value
+#pod
+#pod On an exception during the execution of the request, the C<status> field 
will
+#pod contain 599, and the C<content> field will contain the text of the 
exception.
+#pod
+#pod =cut
 
 my %idempotent = map { $_ => 1 } qw/GET HEAD PUT DELETE OPTIONS TRACE/;
 
@@ -404,19 +420,19 @@ sub request {
     return $response;
 }
 
-# =method www_form_urlencode
-#
-#     $params = $http->www_form_urlencode( $data );
-#     $response = $http->get("http://example.com/query?$params";);
-#
-# This method converts the key/value pairs from a data hash or array reference
-# into a C<x-www-form-urlencoded> string.  The keys and values from the data
-# reference will be UTF-8 encoded and escaped per RFC 3986.  If a value is an
-# array reference, the key will be repeated with each of the values of the 
array
-# reference.  If data is provided as a hash reference, the key/value pairs in 
the
-# resulting string will be sorted by key and value for consistent ordering.
-#
-# =cut
+#pod =method www_form_urlencode
+#pod
+#pod     $params = $http->www_form_urlencode( $data );
+#pod     $response = $http->get("http://example.com/query?$params";);
+#pod
+#pod This method converts the key/value pairs from a data hash or array 
reference
+#pod into a C<x-www-form-urlencoded> string.  The keys and values from the data
+#pod reference will be UTF-8 encoded and escaped per RFC 3986.  If a value is 
an
+#pod array reference, the key will be repeated with each of the values of the 
array
+#pod reference.  If data is provided as a hash reference, the key/value pairs 
in the
+#pod resulting string will be sorted by key and value for consistent ordering.
+#pod
+#pod =cut
 
 sub www_form_urlencode {
     my ($self, $data) = @_;
@@ -641,6 +657,11 @@ sub _prepare_headers_and_cb {
             $request->{headers}{lc $k} = $v;
         }
     }
+
+    if (exists $request->{headers}{'host'}) {
+        die(qq/The 'Host' header must not be provided as header option\n/);
+    }
+
     $request->{headers}{'host'}         = $request->{host_port};
     $request->{headers}{'user-agent'} ||= $self->{agent};
     $request->{headers}{'connection'}   = "close"
@@ -757,31 +778,27 @@ sub _split_url {
     my $url = pop;
 
     # URI regex adapted from the URI module
-    my ($scheme, $authority, $path_query) = $url =~ 
m<\A([^:/?#]+)://([^/?#]*)([^#]*)>
+    my ($scheme, $host, $path_query) = $url =~ 
m<\A([^:/?#]+)://([^/?#]*)([^#]*)>
       or die(qq/Cannot parse URL: '$url'\n/);
 
     $scheme     = lc $scheme;
     $path_query = "/$path_query" unless $path_query =~ m<\A/>;
 
-    my ($auth,$host);
-    $authority = (length($authority)) ? $authority : 'localhost';
-    if ( $authority =~ /@/ ) {
-        ($auth,$host) = $authority =~ m/\A([^@]*)@(.*)\z/;   # user:pass@host
+    my $auth = '';
+    if ( (my $i = index $host, '@') != -1 ) {
+        # user:pass@host
+        $auth = substr $host, 0, $i, ''; # take up to the @ for auth
+        substr $host, 0, 1, '';          # knock the @ off the host
+
         # userinfo might be percent escaped, so recover real auth info
         $auth =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
     }
-    else {
-        $host = $authority;
-        $auth = '';
-    }
-    $host = lc $host;
-    my $port = do {
-       $host =~ s/:([0-9]*)\z// && length $1
-         ? $1
-         : ($scheme eq 'http' ? 80 : $scheme eq 'https' ? 443 : undef);
-    };
+    my $port = $host =~ s/:(\d*)\z// && length $1 ? $1
+             : $scheme eq 'http'                  ? 80
+             : $scheme eq 'https'                 ? 443
+             : undef;
 
-    return ($scheme, $host, $port, $path_query, $auth);
+    return ($scheme, (length $host ? lc $host : "localhost") , $port, 
$path_query, $auth);
 }
 
 # Date conversions adapted from HTTP::Date
@@ -1132,8 +1149,7 @@ sub write_header_lines {
             $HeaderCase{lc $field_name} = $field_name;
         }
         for (ref $v eq 'ARRAY' ? @$v : $v) {
-            /[^\x0D\x0A]/
-              or die(qq/Invalid HTTP header field value ($field_name): / . 
$Printable->($_). "\n");
+            $_ = '' unless defined $_;
             $buf .= "$field_name: $_\x0D\x0A";
         }
     }
@@ -1428,7 +1444,7 @@ HTTP::Tiny - A small, simple, correct HTTP/1.1 client
 
 =head1 VERSION
 
-version 0.043
+version 0.047
 
 =head1 SYNOPSIS
 
@@ -1473,91 +1489,65 @@ This constructor returns a new HTTP::Tiny object.  
Valid attributes include:
 
 =item *
 
-C<agent>
-
-A user-agent string (defaults to 'HTTP-Tiny/$VERSION'). If C<agent> ends in a 
space character, the default user-agent string is appended.
+C<agent> — A user-agent string (defaults to 'HTTP-Tiny/$VERSION'). If 
C<agent> — ends in a space character, the default user-agent string is 
appended.
 
 =item *
 
-C<cookie_jar>
-
-An instance of L<HTTP::CookieJar> or equivalent class that supports the C<add> 
and C<cookie_header> methods
+C<cookie_jar> — An instance of L<HTTP::CookieJar> — or equivalent class 
that supports the C<add> and C<cookie_header> methods
 
 =item *
 
-C<default_headers>
-
-A hashref of default headers to apply to requests
+C<default_headers> — A hashref of default headers to apply to requests
 
 =item *
 
-C<local_address>
-
-The local IP address to bind to
+C<local_address> — The local IP address to bind to
 
 =item *
 
-C<keep_alive>
-
-Whether to reuse the last connection (if for the same scheme, host and port) 
(defaults to 1)
+C<keep_alive> — Whether to reuse the last connection (if for the same 
scheme, host and port) (defaults to 1)
 
 =item *
 
-C<max_redirect>
-
-Maximum number of redirects allowed (defaults to 5)
+C<max_redirect> — Maximum number of redirects allowed (defaults to 5)
 
 =item *
 
-C<max_size>
-
-Maximum response size (only when not using a data callback).  If defined, 
responses larger than this will return an exception.
+C<max_size> — Maximum response size (only when not using a data callback).  
If defined, responses larger than this will return an exception.
 
 =item *
 
-C<http_proxy>
-
-URL of a proxy server to use for HTTP connections (default is 
C<$ENV{http_proxy}> if set)
+C<http_proxy> — URL of a proxy server to use for HTTP connections (default 
is C<$ENV{http_proxy}> — if set)
 
 =item *
 
-C<https_proxy>
-
-URL of a proxy server to use for HTTPS connections (default is 
C<$ENV{https_proxy}> if set)
+C<https_proxy> — URL of a proxy server to use for HTTPS connections (default 
is C<$ENV{https_proxy}> — if set)
 
 =item *
 
-C<proxy>
-
-URL of a generic proxy server for both HTTP and HTTPS connections (default is 
C<$ENV{all_proxy}> if set)
+C<proxy> — URL of a generic proxy server for both HTTP and HTTPS connections 
(default is C<$ENV{all_proxy}> — if set)
 
 =item *
 
-C<no_proxy>
-
-List of domain suffixes that should not be proxied.  Must be a comma-separated 
string or an array reference. (default is C<$ENV{no_proxy}>)
+C<no_proxy> — List of domain suffixes that should not be proxied.  Must be a 
comma-separated string or an array reference. (default is C<$ENV{no_proxy}> —)
 
 =item *
 
-C<timeout>
-
-Request timeout in seconds (default is 60)
+C<timeout> — Request timeout in seconds (default is 60)
 
 =item *
 
-C<verify_SSL>
-
-A boolean that indicates whether to validate the SSL certificate of an C<https>
-connection (default is false)
+C<verify_SSL> — A boolean that indicates whether to validate the SSL 
certificate of an C<https> — connection (default is false)
 
 =item *
 
-C<SSL_options>
-
-A hashref of C<SSL_*> options to pass through to L<IO::Socket::SSL>
+C<SSL_options> — A hashref of C<SSL_*> — options to pass through to 
L<IO::Socket::SSL>
 
 =back
 
+Passing an explicit C<undef> for C<proxy>, C<http_proxy> or C<https_proxy> will
+prevent getting the corresponding proxies from the environment.
+
 Exceptions from C<max_size>, C<timeout> or other errors will result in a
 pseudo-HTTP status code of 599 and a reason of "Internal Exception". The
 content field in the response will contain the text of the exception.
@@ -1649,35 +1639,26 @@ Valid options are:
 
 =item *
 
-C<headers>
-
-A hashref containing headers to include with the request.  If the value for
-a header is an array reference, the header will be output multiple times with
-each value in the array.  These headers over-write any default headers.
+C<headers> — A hashref containing headers to include with the request.  If 
the value for a header is an array reference, the header will be output 
multiple times with each value in the array.  Thes ... [41 chars truncated]
 
 =item *
 
-C<content>
-
-A scalar to include as the body of the request OR a code reference
-that will be called iteratively to produce the body of the request
+C<content> — A scalar to include as the body of the request OR a code 
reference that will be called iteratively to produce the body of the request
 
 =item *
 
-C<trailer_callback>
-
-A code reference that will be called if it exists to provide a hashref
-of trailing headers (only used with chunked transfer-encoding)
+C<trailer_callback> — A code reference that will be called if it exists to 
provide a hashref of trailing headers (only used with chunked transfer-encoding)
 
 =item *
 
-C<data_callback>
-
-A code reference that will be called for each chunks of the response
-body received.
+C<data_callback> — A code reference that will be called for each chunks of 
the response body received.
 
 =back
 
+The C<Host> header is generated from the URL in accordance with RFC 2616.  It
+is a fatal error to specify C<Host> in the C<headers> option.  Other headers
+may be ignored or overwritten if necessary for transport compliance.
+
 If the C<content> option is a code reference, it will be called iteratively
 to provide the content body of the request.  It should return the empty
 string or undef when the iterator is exhausted.
@@ -1699,45 +1680,27 @@ will have the following keys:
 
 =item *
 
-C<success>
-
-Boolean indicating whether the operation returned a 2XX status code
+C<success> — Boolean indicating whether the operation returned a 2XX status 
code
 
 =item *
 
-C<url>
-
-URL that provided the response. This is the URL of the request unless
-there were redirections, in which case it is the last URL queried
-in a redirection chain
+C<url> — URL that provided the response. This is the URL of the request 
unless there were redirections, in which case it is the last URL queried in a 
redirection chain
 
 =item *
 
-C<status>
-
-The HTTP status code of the response
+C<status> — The HTTP status code of the response
 
 =item *
 
-C<reason>
-
-The response phrase returned by the server
+C<reason> — The response phrase returned by the server
 
 =item *
 
-C<content>
-
-The body of the response.  If the response does not have any content
-or if a data callback is provided to consume the response body,
-this will be the empty string
+C<content> — The body of the response.  If the response does not have any 
content or if a data callback is provided to consume the response body, this 
will be the empty string
 
 =item *
 
-C<headers>
-
-A hashref of header fields.  All header field names will be normalized
-to be lower case. If a header is repeated, the value will be an arrayref;
-it will otherwise be a scalar string containing the value
+C<headers> — A hashref of header fields.  All header field names will be 
normalized to be lower case. If a header is repeated, the value will be an 
arrayref; it will otherwise be a scalar string co ... [18 chars truncated]
 
 =back
 
@@ -1775,7 +1738,7 @@ verify_SSL
 
 Direct C<https> connections are supported only if L<IO::Socket::SSL> 1.56 or
 greater and L<Net::SSLeay> 1.49 or greater are installed. An exception will be
-thrown if a new enough versions of these modules not installed or if the SSL
+thrown if new enough versions of these modules are not installed or if the SSL
 encryption fails. An C<https> connection may be made via an C<http> proxy that
 supports the CONNECT command (i.e. RFC 2817).  You may not proxy C<https> via
 a proxy that itself requires C<https> to communicate.
@@ -1895,9 +1858,40 @@ environment variables.
 =head1 LIMITATIONS
 
 HTTP::Tiny is I<conditionally compliant> with the
-L<HTTP/1.1 specification|http://www.w3.org/Protocols/rfc2616/rfc2616.html>.
+L<HTTP/1.1 specifications|http://www.w3.org/Protocols/>:
+
+=over 4
+
+=item *
+
+"Message Syntax and Routing" [RFC7230]
+
+=item *
+
+"Semantics and Content" [RFC7231]
+
+=item *
+
+"Conditional Requests" [RFC7232]
+
+=item *
+
+"Range Requests" [RFC7233]
+
+=item *
+
+"Caching" [RFC7234]
+
+=item *
+
+"Authentication" [RFC7235]
+
+=back
+
 It attempts to meet all "MUST" requirements of the specification, but does not
-implement all "SHOULD" requirements.
+implement all "SHOULD" requirements.  (Note: it was developed against the
+earlier RFC 2616 specification and may not yet meet the revised RFC 7230-7235
+spec.)
 
 Some particular limitations of note include:
 
@@ -2035,7 +2029,7 @@ Chris Nehren <[email protected]>
 
 =item *
 
-Chris Weyl <[email protected]>
+Chris Weyl <[email protected]>
 
 =item *
 
@@ -2059,6 +2053,10 @@ Edward Zborowski <[email protected]>
 
 =item *
 
+James Raspass <[email protected]>
+
+=item *
+
 Jess Robinson <[email protected]>
 
 =item *
@@ -2091,6 +2089,10 @@ Syohei YOSHIDA <[email protected]>
 
 =item *
 
+Sören Kornetzki <[email protected]>
+
+=item *
+
 Tony Cook <[email protected]>
 
 =back
diff --git a/cpan/HTTP-Tiny/t/002_croakage.t b/cpan/HTTP-Tiny/t/002_croakage.t
index a243ebc..9e51b5d 100644
--- a/cpan/HTTP-Tiny/t/002_croakage.t
+++ b/cpan/HTTP-Tiny/t/002_croakage.t
@@ -4,8 +4,12 @@ use strict;
 use warnings;
 
 use Test::More;
+use t::Util qw[tmpfile monkey_patch set_socket_source];
+
 use HTTP::Tiny;
 
+BEGIN { monkey_patch() }
+
 my %usage = (
   'get' => q/Usage: $http->get(URL, [HASHREF])/,
   'mirror' => q/Usage: $http->mirror(URL, FILE, [HASHREF])/,
@@ -26,7 +30,11 @@ my @cases = (
   ['request','GET','http://www.example.com/','extra', 'extra'],
 );
 
+my $res_fh = tmpfile();
+my $req_fh = tmpfile();
+
 my $http = HTTP::Tiny->new;
+set_socket_source($req_fh, $res_fh);
 
 for my $c ( @cases ) {
   my ($method, @args) = @$c;
@@ -35,5 +43,9 @@ for my $c ( @cases ) {
   like ($err, qr/\Q$usage{$method}\E/, join("|",@$c) );
 }
 
+my $res = eval{ $http->get("http://www.example.com/";, { headers => { host => 
"www.example2.com" } } ) };
+is( $res->{status}, 599, "Providing a Host header errors with 599" );
+like( $res->{content}, qr/'Host' header/, "Providing a Host header gives right 
error message" );
+
 done_testing;
 
diff --git a/cpan/HTTP-Tiny/t/020_headers.t b/cpan/HTTP-Tiny/t/020_headers.t
index 970faa6..c10e075 100644
--- a/cpan/HTTP-Tiny/t/020_headers.t
+++ b/cpan/HTTP-Tiny/t/020_headers.t
@@ -49,3 +49,12 @@ use HTTP::Tiny;
     is_deeply($handle->read_header_lines, $headers, "roundtrip header lines");
 }
 
+{
+    my $fh      = tmpfile();
+    my $handle  = HTTP::Tiny::Handle->new(fh => $fh);
+    my $headers = { foo => ['Foo', 'Baz'], bar => 'Bar', baz => '' };
+    $handle->write_header_lines($headers);
+    rewind($fh);
+    is_deeply($handle->read_header_lines, $headers, "roundtrip header lines");
+}
+
diff --git a/cpan/HTTP-Tiny/t/140_proxy.t b/cpan/HTTP-Tiny/t/140_proxy.t
index 401f8ae..6ecc6a5 100644
--- a/cpan/HTTP-Tiny/t/140_proxy.t
+++ b/cpan/HTTP-Tiny/t/140_proxy.t
@@ -31,5 +31,19 @@ for my $proxy ("http://localhost:8080/";, 
"http://localhost:8080";){
     like($@, qr{http_proxy URL must be in format 
http\[s\]://\[auth\@\]<host>:<port>/});
 }
 
+# Explicitly disable proxy
+{
+    local $ENV{all_proxy} = "http://localhost:8080";;
+    local $ENV{http_proxy} = "http://localhost:8080";;
+    local $ENV{https_proxy} = "http://localhost:8080";;
+    my $c = HTTP::Tiny->new(
+        proxy => undef,
+        http_proxy => undef,
+        https_proxy => undef,
+    );
+    ok(!defined $c->proxy, "proxy => undef disables ENV proxy");
+    ok(!defined $c->http_proxy, "http_proxy => undef disables ENV proxy");
+    ok(!defined $c->https_proxy, "https_proxy => undef disables ENV proxy");
+}
 
 done_testing();

--
Perl5 Master Repository

Reply via email to