[Bps-public-commit] app-wsgetmail branch prep-0.05-release updated. 2869f27af9fc2e81a024a26ee6e185a710afd7ce

BPS Git Server git at git.bestpractical.com
Fri Jan 21 19:28:07 UTC 2022


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "app-wsgetmail".

The branch, prep-0.05-release has been updated
       via  2869f27af9fc2e81a024a26ee6e185a710afd7ce (commit)
       via  49425a8fb0fed65f4256129738267a69d11a4d20 (commit)
       via  30a9e99c7d6c27362a8ff765f7691e0d673dcc48 (commit)
       via  de415706d96ff7a1192bda99c462e292b4ec3731 (commit)
      from  1c85a79e64a04eae3744907ed1c64ed28c8d9996 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 2869f27af9fc2e81a024a26ee6e185a710afd7ce
Author: Jim Brandt <jbrandt at bestpractical.com>
Date:   Fri Jan 21 14:25:42 2022 -0500

    Sync up Module::Install files

diff --git a/inc/Module/Install/Scripts.pm b/inc/Module/Install/Scripts.pm
index 2fc8f32..8c80fcd 100644
--- a/inc/Module/Install/Scripts.pm
+++ b/inc/Module/Install/Scripts.pm
@@ -1,3 +1,4 @@
+#line 1
 package Module::Install::Scripts;
 
 use strict 'vars';
diff --git a/inc/YAML/Tiny.pm b/inc/YAML/Tiny.pm
deleted file mode 100644
index fb157a6..0000000
--- a/inc/YAML/Tiny.pm
+++ /dev/null
@@ -1,872 +0,0 @@
-#line 1
-use 5.008001; # sane UTF-8 support
-use strict;
-use warnings;
-package YAML::Tiny; # git description: v1.72-7-g8682f63
-# XXX-INGY is 5.8.1 too old/broken for utf8?
-# XXX-XDG Lancaster consensus was that it was sufficient until
-# proven otherwise
-
-our $VERSION = '1.73';
-
-#####################################################################
-# The YAML::Tiny API.
-#
-# These are the currently documented API functions/methods and
-# exports:
-
-use Exporter;
-our @ISA       = qw{ Exporter  };
-our @EXPORT    = qw{ Load Dump };
-our @EXPORT_OK = qw{ LoadFile DumpFile freeze thaw };
-
-###
-# Functional/Export API:
-
-sub Dump {
-    return YAML::Tiny->new(@_)->_dump_string;
-}
-
-# XXX-INGY Returning last document seems a bad behavior.
-# XXX-XDG I think first would seem more natural, but I don't know
-# that it's worth changing now
-sub Load {
-    my $self = YAML::Tiny->_load_string(@_);
-    if ( wantarray ) {
-        return @$self;
-    } else {
-        # To match YAML.pm, return the last document
-        return $self->[-1];
-    }
-}
-
-# XXX-INGY Do we really need freeze and thaw?
-# XXX-XDG I don't think so.  I'd support deprecating them.
-BEGIN {
-    *freeze = \&Dump;
-    *thaw   = \&Load;
-}
-
-sub DumpFile {
-    my $file = shift;
-    return YAML::Tiny->new(@_)->_dump_file($file);
-}
-
-sub LoadFile {
-    my $file = shift;
-    my $self = YAML::Tiny->_load_file($file);
-    if ( wantarray ) {
-        return @$self;
-    } else {
-        # Return only the last document to match YAML.pm,
-        return $self->[-1];
-    }
-}
-
-
-###
-# Object Oriented API:
-
-# Create an empty YAML::Tiny object
-# XXX-INGY Why do we use ARRAY object?
-# NOTE: I get it now, but I think it's confusing and not needed.
-# Will change it on a branch later, for review.
-#
-# XXX-XDG I don't support changing it yet.  It's a very well-documented
-# "API" of YAML::Tiny.  I'd support deprecating it, but Adam suggested
-# we not change it until YAML.pm's own OO API is established so that
-# users only have one API change to digest, not two
-sub new {
-    my $class = shift;
-    bless [ @_ ], $class;
-}
-
-# XXX-INGY It probably doesn't matter, and it's probably too late to
-# change, but 'read/write' are the wrong names. Read and Write
-# are actions that take data from storage to memory
-# characters/strings. These take the data to/from storage to native
-# Perl objects, which the terms dump and load are meant. As long as
-# this is a legacy quirk to YAML::Tiny it's ok, but I'd prefer not
-# to add new {read,write}_* methods to this API.
-
-sub read_string {
-    my $self = shift;
-    $self->_load_string(@_);
-}
-
-sub write_string {
-    my $self = shift;
-    $self->_dump_string(@_);
-}
-
-sub read {
-    my $self = shift;
-    $self->_load_file(@_);
-}
-
-sub write {
-    my $self = shift;
-    $self->_dump_file(@_);
-}
-
-
-
-
-#####################################################################
-# Constants
-
-# Printed form of the unprintable characters in the lowest range
-# of ASCII characters, listed by ASCII ordinal position.
-my @UNPRINTABLE = qw(
-    0    x01  x02  x03  x04  x05  x06  a
-    b    t    n    v    f    r    x0E  x0F
-    x10  x11  x12  x13  x14  x15  x16  x17
-    x18  x19  x1A  e    x1C  x1D  x1E  x1F
-);
-
-# Printable characters for escapes
-my %UNESCAPES = (
-    0 => "\x00", z => "\x00", N    => "\x85",
-    a => "\x07", b => "\x08", t    => "\x09",
-    n => "\x0a", v => "\x0b", f    => "\x0c",
-    r => "\x0d", e => "\x1b", '\\' => '\\',
-);
-
-# XXX-INGY
-# I(ngy) need to decide if these values should be quoted in
-# YAML::Tiny or not. Probably yes.
-
-# These 3 values have special meaning when unquoted and using the
-# default YAML schema. They need quotes if they are strings.
-my %QUOTE = map { $_ => 1 } qw{
-    null true false
-};
-
-# The commented out form is simpler, but overloaded the Perl regex
-# engine due to recursion and backtracking problems on strings
-# larger than 32,000ish characters. Keep it for reference purposes.
-# qr/\"((?:\\.|[^\"])*)\"/
-my $re_capture_double_quoted = qr/\"([^\\"]*(?:\\.[^\\"]*)*)\"/;
-my $re_capture_single_quoted = qr/\'([^\']*(?:\'\'[^\']*)*)\'/;
-# unquoted re gets trailing space that needs to be stripped
-my $re_capture_unquoted_key  = qr/([^:]+(?::+\S(?:[^:]*|.*?(?=:)))*)(?=\s*\:(?:\s+|$))/;
-my $re_trailing_comment      = qr/(?:\s+\#.*)?/;
-my $re_key_value_separator   = qr/\s*:(?:\s+(?:\#.*)?|$)/;
-
-
-
-
-
-#####################################################################
-# YAML::Tiny Implementation.
-#
-# These are the private methods that do all the work. They may change
-# at any time.
-
-
-###
-# Loader functions:
-
-# Create an object from a file
-sub _load_file {
-    my $class = ref $_[0] ? ref shift : shift;
-
-    # Check the file
-    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 \"YAML::Tiny 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 \"YAML::Tiny failed to classify the line '$lines[0]'";
-            }
-        }
-    };
-    my $err = $@;
-    if ( ref $err eq 'SCALAR' ) {
-        $self->_error(${$err});
-    } elsif ( $err ) {
-        $self->_error($err);
-    }
-
-    return $self;
-}
-
-sub _unquote_single {
-    my ($self, $string) = @_;
-    return '' unless length $string;
-    $string =~ s/\'\'/\'/g;
-    return $string;
-}
-
-sub _unquote_double {
-    my ($self, $string) = @_;
-    return '' unless length $string;
-    $string =~ s/\\"/"/g;
-    $string =~
-        s{\\([Nnever\\fartz0b]|x([0-9a-fA-F]{2}))}
-         {(length($1)>1)?pack("H2",$2):$UNESCAPES{$1}}gex;
-    return $string;
-}
-
-# Load a YAML scalar string to the actual Perl scalar
-sub _load_scalar {
-    my ($self, $string, $indent, $lines) = @_;
-
-    # Trim trailing whitespace
-    $string =~ s/\s*\z//;
-
-    # Explitic null/undef
-    return undef if $string eq '~';
-
-    # Single quote
-    if ( $string =~ /^$re_capture_single_quoted$re_trailing_comment\z/ ) {
-        return $self->_unquote_single($1);
-    }
-
-    # Double quote.
-    if ( $string =~ /^$re_capture_double_quoted$re_trailing_comment\z/ ) {
-        return $self->_unquote_double($1);
-    }
-
-    # Special cases
-    if ( $string =~ /^[\'\"!&]/ ) {
-        die \"YAML::Tiny does not support a feature in line '$string'";
-    }
-    return {} if $string =~ /^{}(?:\s+\#.*)?\z/;
-    return [] if $string =~ /^\[\](?:\s+\#.*)?\z/;
-
-    # Regular unquoted string
-    if ( $string !~ /^[>|]/ ) {
-        die \"YAML::Tiny found illegal characters in plain scalar: '$string'"
-            if $string =~ /^(?:-(?:\s|$)|[\@\%\`])/ or
-                $string =~ /:(?:\s|$)/;
-        $string =~ s/\s+#.*\z//;
-        return $string;
-    }
-
-    # Error
-    die \"YAML::Tiny failed to find multi-line scalar content" unless @$lines;
-
-    # Check the indent depth
-    $lines->[0]   =~ /^(\s*)/;
-    $indent->[-1] = length("$1");
-    if ( defined $indent->[-2] and $indent->[-1] <= $indent->[-2] ) {
-        die \"YAML::Tiny found bad indenting in line '$lines->[0]'";
-    }
-
-    # Pull the lines
-    my @multiline = ();
-    while ( @$lines ) {
-        $lines->[0] =~ /^(\s*)/;
-        last unless length($1) >= $indent->[-1];
-        push @multiline, substr(shift(@$lines), $indent->[-1]);
-    }
-
-    my $j = (substr($string, 0, 1) eq '>') ? ' ' : "\n";
-    my $t = (substr($string, 1, 1) eq '-') ? ''  : "\n";
-    return join( $j, @multiline ) . $t;
-}
-
-# Load an array
-sub _load_array {
-    my ($self, $array, $indent, $lines) = @_;
-
-    while ( @$lines ) {
-        # Check for a new document
-        if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) {
-            while ( @$lines and $lines->[0] !~ /^---/ ) {
-                shift @$lines;
-            }
-            return 1;
-        }
-
-        # Check the indent level
-        $lines->[0] =~ /^(\s*)/;
-        if ( length($1) < $indent->[-1] ) {
-            return 1;
-        } elsif ( length($1) > $indent->[-1] ) {
-            die \"YAML::Tiny found bad indenting in line '$lines->[0]'";
-        }
-
-        if ( $lines->[0] =~ /^(\s*\-\s+)[^\'\"]\S*\s*:(?:\s+|$)/ ) {
-            # Inline nested hash
-            my $indent2 = length("$1");
-            $lines->[0] =~ s/-/ /;
-            push @$array, { };
-            $self->_load_hash( $array->[-1], [ @$indent, $indent2 ], $lines );
-
-        } elsif ( $lines->[0] =~ /^\s*\-\s*\z/ ) {
-            shift @$lines;
-            unless ( @$lines ) {
-                push @$array, undef;
-                return 1;
-            }
-            if ( $lines->[0] =~ /^(\s*)\-/ ) {
-                my $indent2 = length("$1");
-                if ( $indent->[-1] == $indent2 ) {
-                    # Null array entry
-                    push @$array, undef;
-                } else {
-                    # Naked indenter
-                    push @$array, [ ];
-                    $self->_load_array(
-                        $array->[-1], [ @$indent, $indent2 ], $lines
-                    );
-                }
-
-            } elsif ( $lines->[0] =~ /^(\s*)\S/ ) {
-                push @$array, { };
-                $self->_load_hash(
-                    $array->[-1], [ @$indent, length("$1") ], $lines
-                );
-
-            } else {
-                die \"YAML::Tiny failed to classify line '$lines->[0]'";
-            }
-
-        } elsif ( $lines->[0] =~ /^\s*\-(\s*)(.+?)\s*\z/ ) {
-            # Array entry with a value
-            shift @$lines;
-            push @$array, $self->_load_scalar(
-                "$2", [ @$indent, undef ], $lines
-            );
-
-        } elsif ( defined $indent->[-2] and $indent->[-1] == $indent->[-2] ) {
-            # This is probably a structure like the following...
-            # ---
-            # foo:
-            # - list
-            # bar: value
-            #
-            # ... so lets return and let the hash parser handle it
-            return 1;
-
-        } else {
-            die \"YAML::Tiny failed to classify line '$lines->[0]'";
-        }
-    }
-
-    return 1;
-}
-
-# Load a hash
-sub _load_hash {
-    my ($self, $hash, $indent, $lines) = @_;
-
-    while ( @$lines ) {
-        # Check for a new document
-        if ( $lines->[0] =~ /^(?:---|\.\.\.)/ ) {
-            while ( @$lines and $lines->[0] !~ /^---/ ) {
-                shift @$lines;
-            }
-            return 1;
-        }
-
-        # Check the indent level
-        $lines->[0] =~ /^(\s*)/;
-        if ( length($1) < $indent->[-1] ) {
-            return 1;
-        } elsif ( length($1) > $indent->[-1] ) {
-            die \"YAML::Tiny found bad indenting in line '$lines->[0]'";
-        }
-
-        # Find the key
-        my $key;
-
-        # Quoted keys
-        if ( $lines->[0] =~
-            s/^\s*$re_capture_single_quoted$re_key_value_separator//
-        ) {
-            $key = $self->_unquote_single($1);
-        }
-        elsif ( $lines->[0] =~
-            s/^\s*$re_capture_double_quoted$re_key_value_separator//
-        ) {
-            $key = $self->_unquote_double($1);
-        }
-        elsif ( $lines->[0] =~
-            s/^\s*$re_capture_unquoted_key$re_key_value_separator//
-        ) {
-            $key = $1;
-            $key =~ s/\s+$//;
-        }
-        elsif ( $lines->[0] =~ /^\s*\?/ ) {
-            die \"YAML::Tiny does not support a feature in line '$lines->[0]'";
-        }
-        else {
-            die \"YAML::Tiny failed to classify line '$lines->[0]'";
-        }
-
-        if ( exists $hash->{$key} ) {
-            warn "YAML::Tiny found a duplicate key '$key' in line '$lines->[0]'";
-        }
-
-        # Do we have a value?
-        if ( length $lines->[0] ) {
-            # Yes
-            $hash->{$key} = $self->_load_scalar(
-                shift(@$lines), [ @$indent, undef ], $lines
-            );
-        } else {
-            # An indent
-            shift @$lines;
-            unless ( @$lines ) {
-                $hash->{$key} = undef;
-                return 1;
-            }
-            if ( $lines->[0] =~ /^(\s*)-/ ) {
-                $hash->{$key} = [];
-                $self->_load_array(
-                    $hash->{$key}, [ @$indent, length($1) ], $lines
-                );
-            } elsif ( $lines->[0] =~ /^(\s*)./ ) {
-                my $indent2 = length("$1");
-                if ( $indent->[-1] >= $indent2 ) {
-                    # Null hash entry
-                    $hash->{$key} = undef;
-                } else {
-                    $hash->{$key} = {};
-                    $self->_load_hash(
-                        $hash->{$key}, [ @$indent, length($1) ], $lines
-                    );
-                }
-            }
-        }
-    }
-
-    return 1;
-}
-
-
-###
-# Dumper functions:
-
-# Save an object to a file
-sub _dump_file {
-    my $self = shift;
-
-    require Fcntl;
-
-    # Check the file
-    my $file = shift or $self->_error( 'You did not specify a file name' );
-
-    my $fh;
-    # flock if available (or warn if not possible for OS-specific reasons)
-    if ( _can_flock() ) {
-        # Open without truncation (truncate comes after lock)
-        my $flags = Fcntl::O_WRONLY()|Fcntl::O_CREAT();
-        sysopen( $fh, $file, $flags )
-            or $self->_error("Failed to open file '$file' for writing: $!");
-
-        # Use no translation and strict UTF-8
-        binmode( $fh, ":raw:encoding(UTF-8)");
-
-        flock( $fh, Fcntl::LOCK_EX() )
-            or warn "Couldn't lock '$file' for reading: $!";
-
-        # truncate and spew contents
-        truncate $fh, 0;
-        seek $fh, 0, 0;
-    }
-    else {
-        open $fh, ">:unix:encoding(UTF-8)", $file;
-    }
-
-    # serialize and spew to the handle
-    print {$fh} $self->_dump_string;
-
-    # close the file (release the lock)
-    unless ( close $fh ) {
-        $self->_error("Failed to close file '$file': $!");
-    }
-
-    return 1;
-}
-
-# Save an object to a string
-sub _dump_string {
-    my $self = shift;
-    return '' unless ref $self && @$self;
-
-    # Iterate over the documents
-    my $indent = 0;
-    my @lines  = ();
-
-    eval {
-        foreach my $cursor ( @$self ) {
-            push @lines, '---';
-
-            # An empty document
-            if ( ! defined $cursor ) {
-                # Do nothing
-
-            # A scalar document
-            } elsif ( ! ref $cursor ) {
-                $lines[-1] .= ' ' . $self->_dump_scalar( $cursor );
-
-            # A list at the root
-            } elsif ( ref $cursor eq 'ARRAY' ) {
-                unless ( @$cursor ) {
-                    $lines[-1] .= ' []';
-                    next;
-                }
-                push @lines, $self->_dump_array( $cursor, $indent, {} );
-
-            # A hash at the root
-            } elsif ( ref $cursor eq 'HASH' ) {
-                unless ( %$cursor ) {
-                    $lines[-1] .= ' {}';
-                    next;
-                }
-                push @lines, $self->_dump_hash( $cursor, $indent, {} );
-
-            } else {
-                die \("Cannot serialize " . ref($cursor));
-            }
-        }
-    };
-    if ( ref $@ eq 'SCALAR' ) {
-        $self->_error(${$@});
-    } elsif ( $@ ) {
-        $self->_error($@);
-    }
-
-    join '', map { "$_\n" } @lines;
-}
-
-sub _has_internal_string_value {
-    my $value = shift;
-    my $b_obj = B::svref_2object(\$value);  # for round trip problem
-    return $b_obj->FLAGS & B::SVf_POK();
-}
-
-sub _dump_scalar {
-    my $string = $_[1];
-    my $is_key = $_[2];
-    # Check this before checking length or it winds up looking like a string!
-    my $has_string_flag = _has_internal_string_value($string);
-    return '~'  unless defined $string;
-    return "''" unless length  $string;
-    if (Scalar::Util::looks_like_number($string)) {
-        # keys and values that have been used as strings get quoted
-        if ( $is_key || $has_string_flag ) {
-            return qq['$string'];
-        }
-        else {
-            return $string;
-        }
-    }
-    if ( $string =~ /[\x00-\x09\x0b-\x0d\x0e-\x1f\x7f-\x9f\'\n]/ ) {
-        $string =~ s/\\/\\\\/g;
-        $string =~ s/"/\\"/g;
-        $string =~ s/\n/\\n/g;
-        $string =~ s/[\x85]/\\N/g;
-        $string =~ s/([\x00-\x1f])/\\$UNPRINTABLE[ord($1)]/g;
-        $string =~ s/([\x7f-\x9f])/'\x' . sprintf("%X",ord($1))/ge;
-        return qq|"$string"|;
-    }
-    if ( $string =~ /(?:^[~!@#%&*|>?:,'"`{}\[\]]|^-+$|\s|:\z)/ or
-        $QUOTE{$string}
-    ) {
-        return "'$string'";
-    }
-    return $string;
-}
-
-sub _dump_array {
-    my ($self, $array, $indent, $seen) = @_;
-    if ( $seen->{refaddr($array)}++ ) {
-        die \"YAML::Tiny does not support circular references";
-    }
-    my @lines  = ();
-    foreach my $el ( @$array ) {
-        my $line = ('  ' x $indent) . '-';
-        my $type = ref $el;
-        if ( ! $type ) {
-            $line .= ' ' . $self->_dump_scalar( $el );
-            push @lines, $line;
-
-        } elsif ( $type eq 'ARRAY' ) {
-            if ( @$el ) {
-                push @lines, $line;
-                push @lines, $self->_dump_array( $el, $indent + 1, $seen );
-            } else {
-                $line .= ' []';
-                push @lines, $line;
-            }
-
-        } elsif ( $type eq 'HASH' ) {
-            if ( keys %$el ) {
-                push @lines, $line;
-                push @lines, $self->_dump_hash( $el, $indent + 1, $seen );
-            } else {
-                $line .= ' {}';
-                push @lines, $line;
-            }
-
-        } else {
-            die \"YAML::Tiny does not support $type references";
-        }
-    }
-
-    @lines;
-}
-
-sub _dump_hash {
-    my ($self, $hash, $indent, $seen) = @_;
-    if ( $seen->{refaddr($hash)}++ ) {
-        die \"YAML::Tiny does not support circular references";
-    }
-    my @lines  = ();
-    foreach my $name ( sort keys %$hash ) {
-        my $el   = $hash->{$name};
-        my $line = ('  ' x $indent) . $self->_dump_scalar($name, 1) . ":";
-        my $type = ref $el;
-        if ( ! $type ) {
-            $line .= ' ' . $self->_dump_scalar( $el );
-            push @lines, $line;
-
-        } elsif ( $type eq 'ARRAY' ) {
-            if ( @$el ) {
-                push @lines, $line;
-                push @lines, $self->_dump_array( $el, $indent + 1, $seen );
-            } else {
-                $line .= ' []';
-                push @lines, $line;
-            }
-
-        } elsif ( $type eq 'HASH' ) {
-            if ( keys %$el ) {
-                push @lines, $line;
-                push @lines, $self->_dump_hash( $el, $indent + 1, $seen );
-            } else {
-                $line .= ' {}';
-                push @lines, $line;
-            }
-
-        } else {
-            die \"YAML::Tiny does not support $type references";
-        }
-    }
-
-    @lines;
-}
-
-
-
-#####################################################################
-# DEPRECATED API methods:
-
-# Error storage (DEPRECATED as of 1.57)
-our $errstr    = '';
-
-# Set error
-sub _error {
-    require Carp;
-    $errstr = $_[1];
-    $errstr =~ s/ at \S+ line \d+.*//;
-    Carp::croak( $errstr );
-}
-
-# Retrieve error
-my $errstr_warned;
-sub errstr {
-    require Carp;
-    Carp::carp( "YAML::Tiny->errstr and \$YAML::Tiny::errstr is deprecated" )
-        unless $errstr_warned++;
-    $errstr;
-}
-
-
-
-
-#####################################################################
-# Helper functions. Possibly not needed.
-
-
-# Use to detect nv or iv
-use B;
-
-# XXX-INGY Is flock YAML::Tiny's responsibility?
-# Some platforms can't flock :-(
-# XXX-XDG I think it is.  When reading and writing files, we ought
-# to be locking whenever possible.  People (foolishly) use YAML
-# files for things like session storage, which has race issues.
-my $HAS_FLOCK;
-sub _can_flock {
-    if ( defined $HAS_FLOCK ) {
-        return $HAS_FLOCK;
-    }
-    else {
-        require Config;
-        my $c = \%Config::Config;
-        $HAS_FLOCK = grep { $c->{$_} } qw/d_flock d_fcntl_can_lock d_lockf/;
-        require Fcntl if $HAS_FLOCK;
-        return $HAS_FLOCK;
-    }
-}
-
-
-# XXX-INGY Is this core in 5.8.1? Can we remove this?
-# XXX-XDG Scalar::Util 1.18 didn't land until 5.8.8, so we need this
-#####################################################################
-# Use Scalar::Util if possible, otherwise emulate it
-
-use Scalar::Util ();
-BEGIN {
-    local $@;
-    if ( eval { Scalar::Util->VERSION(1.18); } ) {
-        *refaddr = *Scalar::Util::refaddr;
-    }
-    else {
-        eval <<'END_PERL';
-# Scalar::Util failed to load or too old
-sub refaddr {
-    my $pkg = ref($_[0]) or return undef;
-    if ( !! UNIVERSAL::can($_[0], 'can') ) {
-        bless $_[0], 'Scalar::Util::Fake';
-    } else {
-        $pkg = undef;
-    }
-    "$_[0]" =~ /0x(\w+)/;
-    my $i = do { no warnings 'portable'; hex $1 };
-    bless $_[0], $pkg if defined $pkg;
-    $i;
-}
-END_PERL
-    }
-}
-
-delete $YAML::Tiny::{refaddr};
-
-1;
-
-# XXX-INGY Doc notes I'm putting up here. Changing the doc when it's wrong
-# but leaving grey area stuff up here.
-#
-# I would like to change Read/Write to Load/Dump below without
-# changing the actual API names.
-#
-# It might be better to put Load/Dump API in the SYNOPSIS instead of the
-# dubious OO API.
-#
-# null and bool explanations may be outdated.
-
-__END__
-
-#line 1487

commit 49425a8fb0fed65f4256129738267a69d11a4d20
Author: Jim Brandt <jbrandt at bestpractical.com>
Date:   Fri Jan 21 14:25:30 2022 -0500

    Update MANIFEST

diff --git a/MANIFEST b/MANIFEST
index f92f319..2280c25 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1,7 +1,8 @@
 bin/wsgetmail.in
 Changes
-inc/Module/Install.pm
 inc/Module/AutoInstall.pm
+inc/Module/Install.pm
+inc/Module/Install/AutoInstall.pm
 inc/Module/Install/Base.pm
 inc/Module/Install/Can.pm
 inc/Module/Install/Fetch.pm
@@ -9,12 +10,10 @@ inc/Module/Install/Include.pm
 inc/Module/Install/Makefile.pm
 inc/Module/Install/Metadata.pm
 inc/Module/Install/ReadmeFromPod.pm
-inc/Module/Install/Substitute.pm
 inc/Module/Install/Scripts.pm
+inc/Module/Install/Substitute.pm
 inc/Module/Install/Win32.pm
 inc/Module/Install/WriteAll.pm
-inc/Module/Install/AutoInstall.pm
-inc/YAML/Tiny.pm
 INSTALL.SKIP
 lib/App/wsgetmail.pm
 lib/App/wsgetmail/MDA.pm

commit 30a9e99c7d6c27362a8ff765f7691e0d673dcc48
Author: Jim Brandt <jbrandt at bestpractical.com>
Date:   Fri Jan 21 14:06:50 2022 -0500

    Add a few more links to MS documentation

diff --git a/README.md b/README.md
index 4ff01dc..2704063 100644
--- a/README.md
+++ b/README.md
@@ -27,12 +27,12 @@ where `wsgetmail.json` looks like:
 wsgetmail retrieves mail from a folder available through a web services API
 and delivers it to another system. Currently, it only knows how to retrieve
 mail from the Microsoft Graph API, and deliver it by running another command
-on the local system. It may grow to support other systems in the future.
+on the local system.
 
 # INSTALLATION
 
     perl Makefile.PL
-    make PERL_CANARY_STABILITY_NOPROMPT=1
+    make
     make test
     sudo make install
 
@@ -75,9 +75,21 @@ system Perl, or in the same directory as `perl` if you built your own.
 
 ## Configuring Microsoft 365 Client Access
 
-To use wsgetmail, first you need to set up the app in Microsoft 365. This
-section walks you through each piece of configuration wsgetmail needs, and
-how to obtain it.
+To use wsgetmail, first you need to set up the app in Microsoft 365.
+Two authentication methods are supported:
+
+- Client Credentials
+
+    This method uses shared secrets and is preferred method by Microsoft.
+    (See [Client credentials](https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-authentication-flows#client-credentials))
+
+- Username/password
+
+    This method is more like previous connections via IMAP. It is currently
+    supported by Microsoft, but not recommended. (See [Username/password](https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-authentication-flows#usernamepassword))
+
+This section walks you through each piece of configuration wsgetmail needs,
+and how to obtain it.
 
 - tenant\_id
 
@@ -149,9 +161,9 @@ a completely random string, not a UUID/GUID.
 ### Configuring user+password authentication
 
 If you do not want to use a client secret, you can also configure wsgetmail
-to authenticate with a traditional username+password combination. This is
-easier to set up initially, but harder to manage in the long run, because
-the password needs to be kept in sync across applications.
+to authenticate with a traditional username+password combination. As noted
+above, this method is not recommended by Microsoft. It also does not work
+for systems with federated authentication enabled.
 
 - global\_access
 
@@ -170,32 +182,32 @@ the password needs to be kept in sync across applications.
 ## Configuring the mail delivery command
 
 Now that you've configured wsgetmail to access a mail account, all that's
-left is configuring delivery.
+left is configuring delivery. Set the following in your wsgetmail
+configuration file.
 
 - folder
 
-    Set this to the name string of a mail folder to read in your wsgetmail
-    configuration file.
+    Set this to the name string of a mail folder to read.
 
 - command
 
-    Set this to executable command string in your wsgetmail configuration
-    file. You can specify an absolute path, or a plain command name which will
-    be found from `$PATH`. For each email wsgetmail retrieves, it will run this
-    command and pass the message data to it via standard input.
+    Set this to an executable command. You can specify an absolute path,
+    or a plain command name which will be found from `$PATH`. For each
+    email wsgetmail retrieves, it will run this command and pass the
+    message data to it via standard input.
 
 - command\_args
 
-    Set this to a string with additional arguments to call `command` with in
-    your wsgetmail configuration file. These arguments follow shell quoting
-    rules: you can escape characters with a backslash, and denote a single
-    string argument with single or double quotes.
+    Set this to a string with additional arguments to pass to `command`.
+    These arguments follow shell quoting rules: you can escape characters
+    with a backslash, and denote a single string argument with single or
+    double quotes.
 
 - action\_on\_fetched
 
-    Set this to a literal string `"mark_as_read"` or `"delete"` in your
-    wsgetmail configuration file. For each email wsgetmail retrieves, after the
-    configured delivery command succeeds, it will take this action on the message.
+    Set this to a literal string `"mark_as_read"` or `"delete"`.
+    For each email wsgetmail retrieves, after the configured delivery
+    command succeeds, it will take this action on the message.
 
     If you set this to `"mark_as_read"`, wsgetmail will only retrieve and
     deliver messages that are marked unread in the configured folder, so it does
@@ -217,6 +229,8 @@ periodically through cron or a systemd service on a timer.
 
 # LIMITATIONS
 
+## Fetching from Multiple Accounts
+
 wsgetmail can only read from a single folder each time it runs. If you need
 to read multiple folders (possibly spanning different accounts), then you
 need to run it multiple times with different configuration.
@@ -236,6 +250,13 @@ configuration, just run wsgetmail with different configurations:
     wsgetmail --config=account01.json
     wsgetmail --config=account02.json
 
+## Office 365 API Limits
+
+Microsoft applies some limits to the amount of API requests allowed as
+documented in their [Microsoft Graph throttling guidance](https://docs.microsoft.com/en-us/graph/throttling).
+If you reach a limit, requests to the API will start failing for a period
+of time.
+
 # AUTHOR
 
 Best Practical Solutions, LLC <modules at bestpractical.com>
diff --git a/bin/wsgetmail.in b/bin/wsgetmail.in
index b7ea893..8db9b0b 100755
--- a/bin/wsgetmail.in
+++ b/bin/wsgetmail.in
@@ -79,12 +79,12 @@ where C<wsgetmail.json> looks like:
 wsgetmail retrieves mail from a folder available through a web services API
 and delivers it to another system. Currently, it only knows how to retrieve
 mail from the Microsoft Graph API, and deliver it by running another command
-on the local system. It may grow to support other systems in the future.
+on the local system.
 
 =head1 INSTALLATION
 
     perl Makefile.PL
-    make PERL_CANARY_STABILITY_NOPROMPT=1
+    make
     make test
     sudo make install
 
@@ -131,9 +131,25 @@ Show this help documentation.
 
 =head2 Configuring Microsoft 365 Client Access
 
-To use wsgetmail, first you need to set up the app in Microsoft 365. This
-section walks you through each piece of configuration wsgetmail needs, and
-how to obtain it.
+To use wsgetmail, first you need to set up the app in Microsoft 365.
+Two authentication methods are supported:
+
+=over
+
+=item Client Credentials
+
+This method uses shared secrets and is preferred method by Microsoft.
+(See L<Client credentials|https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-authentication-flows#client-credentials>)
+
+=item Username/password
+
+This method is more like previous connections via IMAP. It is currently
+supported by Microsoft, but not recommended. (See L<Username/password|https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-authentication-flows#usernamepassword>)
+
+=back
+
+This section walks you through each piece of configuration wsgetmail needs,
+and how to obtain it.
 
 =over 4
 
@@ -222,9 +238,9 @@ address string in your wsgetmail configuration file.
 =head3 Configuring user+password authentication
 
 If you do not want to use a client secret, you can also configure wsgetmail
-to authenticate with a traditional username+password combination. This is
-easier to set up initially, but harder to manage in the long run, because
-the password needs to be kept in sync across applications.
+to authenticate with a traditional username+password combination. As noted
+above, this method is not recommended by Microsoft. It also does not work
+for systems with federated authentication enabled.
 
 =over 4
 
@@ -247,34 +263,34 @@ configuration file.
 =head2 Configuring the mail delivery command
 
 Now that you've configured wsgetmail to access a mail account, all that's
-left is configuring delivery.
+left is configuring delivery. Set the following in your wsgetmail
+configuration file.
 
 =over 4
 
 =item folder
 
-Set this to the name string of a mail folder to read in your wsgetmail
-configuration file.
+Set this to the name string of a mail folder to read.
 
 =item command
 
-Set this to executable command string in your wsgetmail configuration
-file. You can specify an absolute path, or a plain command name which will
-be found from C<$PATH>. For each email wsgetmail retrieves, it will run this
-command and pass the message data to it via standard input.
+Set this to an executable command. You can specify an absolute path,
+or a plain command name which will be found from C<$PATH>. For each
+email wsgetmail retrieves, it will run this command and pass the
+message data to it via standard input.
 
 =item command_args
 
-Set this to a string with additional arguments to call C<command> with in
-your wsgetmail configuration file. These arguments follow shell quoting
-rules: you can escape characters with a backslash, and denote a single
-string argument with single or double quotes.
+Set this to a string with additional arguments to pass to C<command>.
+These arguments follow shell quoting rules: you can escape characters
+with a backslash, and denote a single string argument with single or
+double quotes.
 
 =item action_on_fetched
 
-Set this to a literal string C<"mark_as_read"> or C<"delete"> in your
-wsgetmail configuration file. For each email wsgetmail retrieves, after the
-configured delivery command succeeds, it will take this action on the message.
+Set this to a literal string C<"mark_as_read"> or C<"delete">.
+For each email wsgetmail retrieves, after the configured delivery
+command succeeds, it will take this action on the message.
 
 If you set this to C<"mark_as_read">, wsgetmail will only retrieve and
 deliver messages that are marked unread in the configured folder, so it does
@@ -298,6 +314,8 @@ periodically through cron or a systemd service on a timer.
 
 =head1 LIMITATIONS
 
+=head2 Fetching from Multiple Accounts
+
 wsgetmail can only read from a single folder each time it runs. If you need
 to read multiple folders (possibly spanning different accounts), then you
 need to run it multiple times with different configuration.
@@ -317,6 +335,13 @@ configuration, just run wsgetmail with different configurations:
     wsgetmail --config=account01.json
     wsgetmail --config=account02.json
 
+=head2 Office 365 API Limits
+
+Microsoft applies some limits to the amount of API requests allowed as
+documented in their L<Microsoft Graph throttling guidance|https://docs.microsoft.com/en-us/graph/throttling>.
+If you reach a limit, requests to the API will start failing for a period
+of time.
+
 =head1 AUTHOR
 
 Best Practical Solutions, LLC <modules at bestpractical.com>

commit de415706d96ff7a1192bda99c462e292b4ec3731
Author: Jim Brandt <jbrandt at bestpractical.com>
Date:   Fri Jan 21 13:01:53 2022 -0500

    Update MANIFEST.SKIP formatting to work with make distcheck

diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP
index 41acf44..f004d32 100644
--- a/MANIFEST.SKIP
+++ b/MANIFEST.SKIP
@@ -1,3 +1,7 @@
-/.git/
-/.gitignore
-/bin/wsgetmail
+.git/*
+.gitignore
+bin/wsgetmail$
+Makefile$
+MYMETA.*
+blib/*
+pm_to_blib

-----------------------------------------------------------------------

Summary of changes:
 MANIFEST                      |   7 +-
 MANIFEST.SKIP                 |  10 +-
 README.md                     |  65 ++--
 bin/wsgetmail.in              |  69 ++--
 inc/Module/Install/Scripts.pm |   1 +
 inc/YAML/Tiny.pm              | 872 ------------------------------------------
 6 files changed, 101 insertions(+), 923 deletions(-)
 delete mode 100644 inc/YAML/Tiny.pm


hooks/post-receive
-- 
app-wsgetmail


More information about the Bps-public-commit mailing list