@@ -421,15 +421,15 @@ sub cmd_dcommit {
421421 $head ||= ' HEAD' ;
422422 my @refs ;
423423 my ($url , $rev , $uuid , $gs ) = working_head_info($head , \@refs );
424+ unless ($gs ) {
425+ die " Unable to determine upstream SVN information from " ,
426+ " $head history.\n Perhaps the repository is empty." ;
427+ }
424428 $url = defined $_commit_url ? $_commit_url : $gs -> full_url;
425429 my $last_rev = $_revision if defined $_revision;
426430 if ($url ) {
427431 print " Committing to $url ...\n " ;
428432 }
429- unless ($gs ) {
430- die " Unable to determine upstream SVN information from " ,
431- " $head history.\n Perhaps the repository is empty." ;
432- }
433433 my ($linear_refs , $parents ) = linearize_history($gs , \@refs );
434434 if ($_no_rebase && scalar (@$linear_refs ) > 1) {
435435 warn " Attempting to commit more than one change while " ,
@@ -803,17 +803,37 @@ sub cmd_commit_diff {
803803 }
804804}
805805
806+ sub escape_uri_only {
807+ my ($uri ) = @_ ;
808+ my @tmp ;
809+ foreach (split m { /} , $uri ) {
810+ s / ([^\w .%+-]|%(?![a-fA-F0-9]{2}))/ sprintf("%%%02X",ord($1 ))/ eg ;
811+ push @tmp , $_ ;
812+ }
813+ join (' /' , @tmp );
814+ }
815+
816+ sub escape_url {
817+ my ($url ) = @_ ;
818+ if ($url =~ m # ^([^:]+)://([^/]*)(.*)$ # ) {
819+ my ($scheme , $domain , $uri ) = ($1 , $2 , escape_uri_only($3 ));
820+ $url = " $scheme ://$domain$uri " ;
821+ }
822+ $url ;
823+ }
824+
806825sub cmd_info {
807826 my $path = canonicalize_path(defined ($_ [0]) ? $_ [0] : " ." );
827+ my $fullpath = canonicalize_path($cmd_dir_prefix . $path );
808828 if (exists $_ [1]) {
809829 die " Too many arguments specified\n " ;
810830 }
811831
812832 my ($file_type , $diff_status ) = find_file_type_and_diff_status($path );
813833
814834 if (!$file_type && !$diff_status ) {
815- print STDERR " $path : (Not a versioned resource) \n \n" ;
816- return ;
835+ print STDERR " svn: ' $path ' is not under version control \n " ;
836+ exit 1 ;
817837 }
818838
819839 my ($url , $rev , $uuid , $gs ) = working_head_info(' HEAD' );
@@ -825,21 +845,21 @@ sub cmd_info {
825845 # canonicalize_path() will return "" to make libsvn 1.5.x happy,
826846 $path = " ." if $path eq " " ;
827847
828- my $full_url = $url . ($path eq " . " ? " " : " /$path " );
848+ my $full_url = $url . ($fullpath eq " " ? " " : " /$fullpath " );
829849
830850 if ($_url) {
831- print $full_url , " \n " ;
851+ print escape_url( $full_url ) , " \n " ;
832852 return ;
833853 }
834854
835855 my $result = " Path: $path \n " ;
836856 $result .= " Name: " . basename($path ) . " \n " if $file_type ne " dir" ;
837- $result .= " URL: " . $full_url . " \n " ;
857+ $result .= " URL: " . escape_url( $full_url ) . " \n " ;
838858
839859 eval {
840860 my $repos_root = $gs -> repos_root;
841861 Git::SVN::remove_username($repos_root );
842- $result .= " Repository Root: $repos_root \n " ;
862+ $result .= " Repository Root: " . escape_url( $repos_root ) . " \n " ;
843863 };
844864 if ($@ ) {
845865 $result .= " Repository Root: (offline)\n " ;
@@ -861,7 +881,7 @@ sub cmd_info {
861881 }
862882
863883 my ($lc_author , $lc_rev , $lc_date_utc );
864- my @args = Git::SVN::Log::git_svn_log_cmd($rev , $rev , " --" , $path );
884+ my @args = Git::SVN::Log::git_svn_log_cmd($rev , $rev , " --" , $fullpath );
865885 my $log = command_output_pipe(@args );
866886 my $esc_color = qr / (?:\033\[ (?:(?:\d +;)*\d *)?m)*/ ;
867887 while (<$log >) {
@@ -3380,11 +3400,12 @@ sub generate_diff {
33803400 while (<$diff_fh >) {
33813401 chomp $_ ; # this gets rid of the trailing "\0"
33823402 if ($state eq ' meta' && / ^:(\d {6})\s (\d {6})\s
3383- $: :sha1\s ($: :sha1)\s
3403+ ( $: :sha1) \s ($: :sha1)\s
33843404 ([MTCRAD])\d *$ /xo ) {
33853405 push @mods , { mode_a => $1 , mode_b => $2 ,
3386- sha1_b => $3 , chg => $4 };
3387- if ($4 =~ / ^(?:C|R)$ / ) {
3406+ sha1_a => $3 , sha1_b => $4 ,
3407+ chg => $5 };
3408+ if ($5 =~ / ^(?:C|R)$ / ) {
33883409 $state = ' file_a' ;
33893410 } else {
33903411 $state = ' file_b' ;
@@ -3636,6 +3657,7 @@ sub R {
36363657 my $fbat = $self -> add_file($self -> repo_path($m -> {file_b }), $pbat ,
36373658 $self -> url_path($m -> {file_a }), $self -> {r });
36383659 print " \t R\t $m ->{file_a} => $m ->{file_b}\n " unless $: :_q;
3660+ $self -> apply_autoprops($file , $fbat );
36393661 $self -> chg_file($fbat , $m );
36403662 $self -> close_file($fbat ,undef ,$self -> {pool });
36413663
@@ -3662,33 +3684,52 @@ sub change_file_prop {
36623684 $self -> SUPER::change_file_prop($fbat , $pname , $pval , $self -> {pool });
36633685}
36643686
3665- sub chg_file {
3666- my ($self , $fbat , $m ) = @_ ;
3667- if ($m -> {mode_b } =~ / 755$ / && $m -> {mode_a } !~ / 755$ / ) {
3668- $self -> change_file_prop($fbat ,' svn:executable' ,' *' );
3669- } elsif ($m -> {mode_b } !~ / 755$ / && $m -> {mode_a } =~ / 755$ / ) {
3670- $self -> change_file_prop($fbat ,' svn:executable' ,undef );
3671- }
3672- my $fh = Git::temp_acquire(' git_blob' );
3673- if ($m -> {mode_b } =~ / ^120/ ) {
3687+ sub _chg_file_get_blob ($$$$) {
3688+ my ($self , $fbat , $m , $which ) = @_ ;
3689+ my $fh = Git::temp_acquire(" git_blob_$which " );
3690+ if ($m -> {" mode_$which " } =~ / ^120/ ) {
36743691 print $fh ' link ' or croak $! ;
36753692 $self -> change_file_prop($fbat ,' svn:special' ,' *' );
3676- } elsif ($m -> {mode_a } =~ / ^120/ && $m -> {mode_b } !~ / ^120/ ) {
3693+ } elsif ($m -> {mode_a } =~ / ^120/ && $m -> {" mode_ $which " } !~ / ^120/ ) {
36773694 $self -> change_file_prop($fbat ,' svn:special' ,undef );
36783695 }
3679- my $size = $: :_repository-> cat_blob($m -> {sha1_b }, $fh );
3680- croak " Failed to read object $m ->{sha1_b}" if ($size < 0);
3696+ my $blob = $m -> {" sha1_$which " };
3697+ return ($fh ,) if ($blob =~ / ^0{40}$ / );
3698+ my $size = $: :_repository-> cat_blob($blob , $fh );
3699+ croak " Failed to read object $blob " if ($size < 0);
36813700 $fh -> flush == 0 or croak $! ;
36823701 seek $fh , 0, 0 or croak $! ;
36833702
36843703 my $exp = ::md5sum($fh );
36853704 seek $fh , 0, 0 or croak $! ;
3705+ return ($fh , $exp );
3706+ }
36863707
3708+ sub chg_file {
3709+ my ($self , $fbat , $m ) = @_ ;
3710+ if ($m -> {mode_b } =~ / 755$ / && $m -> {mode_a } !~ / 755$ / ) {
3711+ $self -> change_file_prop($fbat ,' svn:executable' ,' *' );
3712+ } elsif ($m -> {mode_b } !~ / 755$ / && $m -> {mode_a } =~ / 755$ / ) {
3713+ $self -> change_file_prop($fbat ,' svn:executable' ,undef );
3714+ }
3715+ my ($fh_a , $exp_a ) = _chg_file_get_blob $self , $fbat , $m , ' a' ;
3716+ my ($fh_b , $exp_b ) = _chg_file_get_blob $self , $fbat , $m , ' b' ;
36873717 my $pool = SVN::Pool-> new;
3688- my $atd = $self -> apply_textdelta($fbat , undef , $pool );
3689- my $got = SVN::TxDelta::send_stream($fh , @$atd , $pool );
3690- die " Checksum mismatch\n expected: $exp \n got: $got \n " if ($got ne $exp );
3691- Git::temp_release($fh , 1);
3718+ my $atd = $self -> apply_textdelta($fbat , $exp_a , $pool );
3719+ if (-s $fh_a ) {
3720+ my $txstream = SVN::TxDelta::new ($fh_a , $fh_b , $pool );
3721+ my $res = SVN::TxDelta::send_txstream($txstream , @$atd , $pool );
3722+ if (defined $res ) {
3723+ die " Unexpected result from send_txstream: $res \n " ,
3724+ " (SVN::Core::VERSION: $SVN::Core::VERSION )\n " ;
3725+ }
3726+ } else {
3727+ my $got = SVN::TxDelta::send_stream($fh_b , @$atd , $pool );
3728+ die " Checksum mismatch\n expected: $exp_b \n got: $got \n "
3729+ if ($got ne $exp_b );
3730+ }
3731+ Git::temp_release($fh_b , 1);
3732+ Git::temp_release($fh_a , 1);
36923733 $pool -> clear;
36933734}
36943735
0 commit comments