#!/usr/bin/perl
#
# Written by Adam Lewenberg <adamhl@stanford.edu>

use strict ;
use warnings ;

# Copies a local git repository to a remote server in preparation
# for using puppet-dry-run

# Use:
#
# copy-puppet-repo <remotedirectory>
#
# Example:
#
# copy-puppet-repo root@integration-test2:/root/tmp/abc/

# Step 1. Get the remote directory.
my $remote = $ARGV[0] ;

if (!$remote) {
    print usage_string() ;
    exit 0 ;
}

# Get the remote directory
my ($remote_user_server, $remote_dir) ;
if ($remote =~ m{(^[^\/]*):(\/.*$)}xsm) {
    $remote_user_server = $1 ;
    $remote_dir         = $2 ;
} else {
    exit_with_error(q{remote must be of the form 'user@server:/root/tmp/a/b/c'}) ;
}

if ($remote_dir !~ m{^\/root\/tmp\/}xsm) {
    exit_with_error('can only copy to a subdirectory of /root/tmp') ;
}

# Make sure we are in the top-level directory. We do this by checking
# for the .git directory.
if (!(-d '.git')) {
    exit_with_error('must be run from the top-level git directory') ;
}

# Step 2. Create the remote directory
my (@cmd, $stdout, $stderr, $exit_value) ;

@cmd = (
           'ssh',
           $remote_user_server,
           "mkdir -p $remote_dir",
           ) ;
($stdout, $stderr, $exit_value) = run_command_improved(@cmd) ;
if ($exit_value != 0) {
    exit_with_error("remote directory create failed: $stderr") ;
}

# Step 3. Rsync the files
@cmd = (
         'rsync',
         '-Rav',
         '-e ssh',
         '--exclude', '.git',
         '--exclude', '.tmp_sps',
         q{.},
         $remote,
       ) ;
($stdout, $stderr, $exit_value) = run_command_improved(@cmd) ;
if ($exit_value != 0) {
    exit_with_error("rsync failed: $stderr") ;
} else {
    print $stdout ;
}

# Step 4. Change the owner and group to root
@cmd = (
         'ssh',
         $remote_user_server,
         "chown -R root:root $remote_dir",
    ) ;
($stdout, $stderr, $exit_value) = run_command_improved(@cmd) ;
if ($exit_value != 0) {
    exit_with_error("chown failed: $stderr") ;
} else {
    print $stdout ;
}

print "Done\n" ;
exit 0 ;

################################
sub usage_string {
    return <<'EOS';
Use:
copy-puppet-repo <remotedirectory>

Example:
  copy-puppet-repo root@integration-test2:/root/tmp/abc/
EOS
}

sub exit_with_error {
    my ($msg) = @_ ;

    print "error: $msg\n" ;
    exit 255 ;
}

# Use: pass in an array, returns ($stdout, $stderr, $exit_value)
sub run_command_improved {
    my (@command) = @_ ;

    ## no critic (ProhibitStringyEval, RequireCheckingReturnValueOfEval);
    eval 'use IPC::Run' ;

    my ($out, $err) ;
    IPC::Run::run(\@command, q{>}, \$out, q{2>}, \$err) ;
    return ($out, $err, $? >> 8) ;
}

__END__

=head1 NAME

copy-puppet-repo - Copy a Puppet git repo to /root/tmp space on a remote server

=head1 SYNOPSIS

B<copy-puppet-repo> root@myserver.stanford.edu:/root/tmp/abc/

=head1 DESCRIPTION

Running this script at the top of a Git repository will copy
all the files in that repository to the C</root/tmp> subdirectory indicated
in the provided argument.

This script was written to aid those using C<puppet-dry-run>.

Note that the destination directory B<must> be a subdirectory
of C</root/tmp> or the script will fail. The copy uses ssh and assumes
that you have valid GSSAPI credentials.

=head1 SEE ALSO

puppet-dry-run(8)

=head1 AUTHOR

Adam H. Lewenberg <adamhl@stanford.edu>

=cut
