fix remote rsync://
authorJulien Moutinho <julm+git-remote-gpg@autogeree.net>
Mon, 28 Apr 2014 17:29:34 +0000 (19:29 +0200)
committerJulien Moutinho <julm+git-remote-gpg@autogeree.net>
Tue, 29 Apr 2014 15:08:27 +0000 (17:08 +0200)
git-remote-gpg

index 8e4e4e1902d2778a6eebf231d9b641dea684d90b..6d385d3ac981fad1732271aa75ef62362f3006a1 100755 (executable)
@@ -76,24 +76,23 @@ our $VERSION = '2014.01.28';
                croak("\e[31mERROR\e[m ", @_, "\n\t");
         }
 # System utilities
-       sub rm ($) {
-               my ($file) = @_;
-               debug(sub{"file="},$file);
-               unlink($file)
-                       or error("rm $file");
-        }
-       sub mkdir ($) {
-               my ($dir) = @_;
-               debug(sub{"dir=\"$dir\"\n"});
-               File::Path::make_path($dir, {verbose=>0, error => \my $error});
-               if (@$error) {
-                       for my $diag (@$error) {
-                               my ($dir, $message) = %$diag;
-                               if ($dir eq '') {
-                                       print "general error: $message\n";
-                                }
-                               else {
-                                       print "problem mkdir $dir: $message\n";
+       sub rm (@) {
+               foreach my $file (@_) {
+                       debug(sub{"file=$file\n"});
+                       if (not -e $file) {
+                               unlink($file)
+                                       or error("rm $file");
+                        }
+                }
+        }
+       sub mkdir (@) {
+               foreach my $dir (@_) {
+                       debug(sub{"dir=$dir\n"});
+                       File::Path::make_path($dir, {verbose=>0, error => \my $error});
+                       if (@$error) {
+                               for my $diag (@$error) {
+                                       my ($dir, $message) = %$diag;
+                                       error("dir=$dir: $message");
                                 }
                         }
                 }
@@ -241,14 +240,13 @@ our $VERSION = '2014.01.28';
                return $clear;
         }
 # grg remote I/O
-       sub grg_remote_fetch_file ($$$) {
-               my ($ctx, $files, $fetch_files) = @_;
+       sub grg_remote_fetch_file ($) {
+               my ($ctx) = @_;
                # NOTE: avoid File::Copy::copy().
-               while (my ($file, undef) = each %$fetch_files) {
+               while (my ($file, undef) = each %{$ctx->{remote}->{fetch}}) {
                        my $path = File::Spec->catfile($ctx->{remote}->{uri}->file, $file);
-                       debug(sub{'test path='}, $path);
                        if (-r $path) {
-                               my $h = $fetch_files->{$file};
+                               my $h = $ctx->{remote}->{fetch}->{$file};
                                $h->{path}     = $path;
                                $h->{preserve} = 1;
                         }
@@ -256,31 +254,45 @@ our $VERSION = '2014.01.28';
                 }
                return 1;
         }
-       sub grg_remote_fetch_rsync ($$$) {
-               my ($ctx, $files, $fetch_files) = @_;
+       sub grg_remote_fetch_rsync ($) {
+               my ($ctx) = @_;
                my $uri  = $ctx->{remote}->{uri}->clone;
-               $uri->scheme(undef);
-               $uri->fragment(undef);
-               $uri->query(undef);
-               $uri = $uri->as_string;
+               my @src;
+               if ($uri->opaque =~ m{^//}) {
+                       $uri->fragment(undef);
+                       $uri->query(undef);
+                       @src = map { $uri->path($_); $uri->as_string; }
+                        (keys %{$ctx->{remote}->{fetch}});
+                }
+               else {
+                       my ($authority, $path, $fragment)
+                        = $uri->as_string =~ m|^rsync:(?:([^/#:]+):)?([^?#]*)(?:#(.*))?$|;
+                       @src = map { "$authority:$path/$_" }
+                        (keys %{$ctx->{remote}->{fetch}});
+                }
                IPC::Run::run([@{$ctx->{config}->{rsync}}
-                , '--verbose', '--ignore-times', '--inplace', '--progress'
-                , (map { File::Spec->catfile($uri, $_) } @$files)
+                , '-i', '--ignore-times', '--inplace', '--progress'
+                , @src
                 , $ctx->{'dir-cache'}.'/']
                 , '>&2')
         }
-       sub grg_remote_fetch_sftp ($$$) {
-               my ($ctx, $files, $fetch_files) = @_;
+       sub grg_remote_fetch_sftp ($) {
+               my ($ctx) = @_;
                IPC::Run::run([@{$ctx->{config}->{curl}}
                 , '--show-error'
                 , '--output', File::Spec->catfile($ctx->{'dir-cache'}, '#1')
-                , File::Spec->catfile($ctx->{remote}->{uri}, '{'.join(',',@$files).'}') ])
+                , File::Spec->catfile($ctx->{remote}->{uri}->as_string
+                        , '{'.join(',', (keys %{$ctx->{remote}->{fetch}})).'}') ])
         }
        sub grg_remote_fetch ($$) {
                my ($ctx, $files) = @_;
                debug(sub{'files='}, $files);
                my $scheme = $ctx->{remote}->{uri}->scheme;
-               my $fetch_files = {map { $_ => { path => File::Spec->catfile($ctx->{'dir-cache'}, $_), preserve => 0 } } @$files};
+               $ctx->{remote}->{fetch}
+                = {map { $_ =>
+                        { path => File::Spec->catfile($ctx->{'dir-cache'}, $_)
+                        , preserve => 0 }
+                } @$files};
                my $fct =
                 { file  => \&grg_remote_fetch_file
                 , rsync => \&grg_remote_fetch_rsync
@@ -288,11 +300,9 @@ our $VERSION = '2014.01.28';
                 }->{$scheme};
                error("URL scheme not supported: `$scheme'")
                        unless $fct;
-               debug(sub{'fetch_files='}, $fetch_files);
-               $fct->($ctx, $files, $fetch_files)
-                       or $fetch_files = {};
-               debug(sub{'fetch_files='}, $fetch_files);
-               return $fetch_files;
+               $fct->($ctx)
+                       or $ctx->{remote}->{fetch} = {};
+               return $ctx->{remote}->{fetch};
         }
        sub grg_remote_init_file ($) {
                my ($ctx) = @_;
@@ -302,17 +312,27 @@ our $VERSION = '2014.01.28';
         }
        sub grg_remote_init_rsync ($) {
                my ($ctx) = @_;
-               my $tmp = File::Temp->tempdir(CLEANUP => 1);
-               my $path = $ctx->{remote}->{uri}->path;
-               my $uri  = $ctx->{remote}->{uri}->clone;
-               $uri->fragment(undef);
-               $uri->path(undef);
-               $uri->query(undef);
+               my $tmp = File::Temp->tempdir('grg_rsync_XXXXXXXX', CLEANUP => 1);
+               my $uri = $ctx->{remote}->{uri}->clone;
+               my ($path, $dst);
+               if ($uri->opaque =~ m{^//}) {
+                       $uri->fragment(undef);
+                       $uri->query(undef);
+                       $path = $uri->path;
+                       $dst = $uri->as_string;
+                }
+               else {
+                       my ($authority, $fragment);
+                       ($authority, $path, $fragment)
+                        = $uri->as_string =~ m|^rsync:(?:([^/#:]+):)?([^?#]*)(?:#(.*))?$|;
+                       $dst = "$authority:";
+                }
                &mkdir(File::Spec->catdir($tmp, $path));
                IPC::Run::run([@{$ctx->{config}->{rsync}}
-                , '--verbose', '--recursive', '--relative'
+                , '-i', '--recursive', '--relative'
                 , '--exclude=*', '.'
-                , File::Spec->catfile($uri->as_string)]
+                , $dst]
+                , '>&2'
                 , init => sub { chdir $tmp or die $!; })
         }
        sub grg_remote_init_sftp ($) {
@@ -341,10 +361,10 @@ our $VERSION = '2014.01.28';
                        or error("remote init failed");
                return;
         }
-       sub grg_remote_push_file ($$) {
-               my ($ctx, $files) = @_;
+       sub grg_remote_push_file ($) {
+               my ($ctx) = @_;
                my $ok = 1;
-               foreach my $file (@$files) {
+               foreach my $file (@{$ctx->{remote}->{push}}) {
                        my $src = File::Spec->catfile($ctx->{'dir-cache'}, $file);
                        my $dst = File::Spec->catfile($ctx->{remote}->{uri}->file, $file);
                        debug(sub{"File::Copy::move('$src', '$dst')\n"});
@@ -355,24 +375,37 @@ our $VERSION = '2014.01.28';
                 }
                return $ok;
         }
-       sub grg_remote_push_rsync ($$) {
-               my ($ctx, $files) = @_;
-               my $uri  = $ctx->{remote}->{uri}->clone;
-               $uri->fragment('');
-               $uri->query('');
+       sub grg_remote_push_rsync ($) {
+               my ($ctx) = @_;
+               my $uri = $ctx->{remote}->{uri}->clone;
+               $uri->fragment(undef);
+               $uri->query(undef);
+               my ($path, $dst);
+               if ($uri->opaque =~ m{^//}) {
+                       $uri->fragment(undef);
+                       $uri->query(undef);
+                       $dst = $uri->as_string;
+                }
+               else {
+                       my ($authority, $path, $fragment)
+                        = $uri->as_string =~ m|^rsync:(?:([^/#:]+):)?([^?#]*)(?:#(.*))?$|;
+                       $dst = "$authority:$path/";
+                }
                IPC::Run::run([@{$ctx->{config}->{rsync}}
-                , '--verbose', '--relative'
-                , @$files
-                , $uri->as_string])
+                , '-i', '--relative'
+                , (@{$ctx->{remote}->{push}})
+                , $dst]
+                , '>&2'
+                , init => sub { chdir $ctx->{'dir-cache'} or die $!; });
         }
-       sub grg_remote_push_sftp ($$) {
-               my ($ctx, $files) = @_;
+       sub grg_remote_push_sftp ($) {
+               my ($ctx) = @_;
                my $uri  = $ctx->{remote}->{uri}->clone;
                $uri->fragment('');
                $uri->query('');
                IPC::Run::run([@{$ctx->{config}->{curl}}
                 , '--show-error', '--ftp-create-dirs', '--upload-file'
-                , '{'.join(',', @$files).'}'
+                , '{'.join(',', @{$ctx->{remote}->{push}}).'}'
                 , $uri->as_string.'/'])
         }
        sub grg_remote_push ($) {
@@ -389,8 +422,9 @@ our $VERSION = '2014.01.28';
                 }->{$scheme};
                error("URL scheme not supported: `$scheme'")
                        unless $fct;
-               $fct->($ctx, $ctx->{remote}->{push})
+               $fct->($ctx)
                        or error("remote push failed");
+               rm(map {File::Spec->catfile($ctx->{'dir-cache'}, $_)} @{$ctx->{remote}->{push}});
                return 1;
         }
        sub grg_remote_remove ($) {
@@ -876,7 +910,7 @@ sub main {
                &mkdir($ctx->{'dir-cache'});
         }
        else {
-               $ctx->{'dir-cache'} = File::Temp->tempdir(CLEANUP => 1);
+               $ctx->{'dir-cache'} = File::Temp->tempdir('grg_cache_XXXXXXXX', CLEANUP => 1);
         }
        debug(sub{"ctx="},$ctx);
        grg_commands($ctx);
@@ -911,11 +945,13 @@ git-remote-gpg - git-remote-helpers(1) to encrypt remote repository through gpg(
 
 =head2 Via rsync(1)
 
-=item git remote add $remote gpg::rsync://${user:+$user@}$host/$path
+=item git remote add $remote gpg::rsync:${user:+$user@}$host:$path
+
+=item git remote add $remote gpg::rsync://${user:+$user@}$host${port:+:$port}/$path
 
 =head2 Via curl(1)
 
-=item git remote add $remote gpg::sftp://${user:+$user@}$host/$path
+=item git remote add $remote gpg::sftp://${user:+$user@}$host${port:+:$port}/$path
 
 =head2 Via File::Copy(3pm)