The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
use 5.008001;
use strict;
use warnings;

package Dist::Zilla::Plugin::Upload::SCP;
# ABSTRACT: Dist::Zilla release plugin to upload via scp
our $VERSION = '0.002'; # VERSION

use autodie 2.00;
use Moose;
use MooseX::Types::Moose qw/Str Bool/;
use MooseX::Types::Path::Tiny qw/Path/;
use Net::OpenSSH 0.60;
use Path::Tiny;

use namespace::autoclean;

with 'Dist::Zilla::Role::Releaser';


has connection => (
    is       => 'ro',
    isa      => Str,
    required => 1,
);


has directory => (
    is       => 'ro',
    isa      => Path,
    coerce   => 1,
    required => 1,
);


has clobber => (
    is      => 'ro',
    isa     => Bool,
    default => 0,
);


has atomic => (
    is      => 'ro',
    isa     => Bool,
    default => 0,
);

has _ssh => (
    is         => 'ro',
    isa        => 'Net::OpenSSH',
    lazy_build => 1,
);

sub _build__ssh {
    my $self = shift;
    my $ssh  = Net::OpenSSH->new( $self->connection );
    $self->log_fatal( "Couldn't establish an ssh connection: " . $ssh->error )
      if $ssh->error;
    return $ssh;
}

sub release {
    my ( $self, $archive ) = @_;
    my $ssh = $self->_ssh;

    my $dest = $self->directory->child( $archive->basename );
    my $upload_name = $self->atomic ? "$dest.part." . int(rand(2**31)) : $dest;

    if ( $ssh->test( "/bin/ls", "$dest" ) && !$self->clobber ) {
        $self->log_fatal("dest file $dest exists.  Halting!");
    }

    $ssh->scp_put( "$archive", "$upload_name" )
      or $self->log_fatal( "Error uploading: " . $ssh->error );

    if ( $self->atomic ) {
        $ssh->system( "/bin/mv", "-f", "$upload_name", "$dest" )
            or $self->log_fatal( "Error renaming uploaded file: " . $ssh->error );
    }

    $self->log( "$archive uploaded to " . join( ":", $self->connection, $dest ) );

    return;
}

__PACKAGE__->meta->make_immutable();
1;


# vim: ts=4 sts=4 sw=4 et:

__END__

=pod

=encoding utf-8

=head1 NAME

Dist::Zilla::Plugin::Upload::SCP - Dist::Zilla release plugin to upload via scp

=head1 VERSION

version 0.002

=head1 SYNOPSIS

  [Upload::SCP]
  connection = david@example.com
  directory = public_html

=head1 DESCRIPTION

This module uploads a distribution tarball to a remote host via scp on release.

It does not manage passwords.  You can put that in your connection string if you're nuts,
but you really should use an SSH key and C<ssh-agent>.

=head1 ATTRIBUTES

=head2 connection (required)

An ssh connection string, either C<host> or C<user@host> or anything else L<Net::OpenSSH>
supports as a C<host> parameter.

=head2 directory (required)

Remote directory to receive the upload.

=head2 clobber

Boolean for whether an existing destination path should be clobbered.
Defaults to false.

=head2 atomic

Boolean for whether the file should be uploaded with a temporary name
and then renamed when the upload is complete.  Defaults to false.

=for Pod::Coverage release

=head1 SEE ALSO

=over 4

=item *

L<Dist::Zilla::Plugin::UploadToSFTP> -- very similar but allows you to set passwords via F<.netrc>

=back

=for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan

=head1 SUPPORT

=head2 Bugs / Feature Requests

Please report any bugs or feature requests through the issue tracker
at L<https://github.com/dagolden/dist-zilla-plugin-upload-scp/issues>.
You will be notified automatically of any progress on your issue.

=head2 Source Code

This is open source software.  The code repository is available for
public review and contribution under the terms of the license.

L<https://github.com/dagolden/dist-zilla-plugin-upload-scp>

  git clone git://github.com/dagolden/dist-zilla-plugin-upload-scp.git

=head1 AUTHOR

David Golden <dagolden@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is Copyright (c) 2013 by David Golden.

This is free software, licensed under:

  The Apache License, Version 2.0, January 2004

=cut