Merge branch 'maint-1.5.6' into maint-1.6.0
[gitweb.git] / git-svn.perl
index 4dc33801a88c63f62a263b5008649b05fc1b9d7d..25ed2f43335bfa717d9bbc1a799c7841c25b1cc0 100755 (executable)
@@ -421,7 +421,7 @@ sub cmd_dcommit {
        $head ||= 'HEAD';
        my @refs;
        my ($url, $rev, $uuid, $gs) = working_head_info($head, \@refs);
-       $url = $_commit_url if defined $_commit_url;
+       $url = defined $_commit_url ? $_commit_url : $gs->full_url;
        my $last_rev = $_revision if defined $_revision;
        if ($url) {
                print "Committing to $url ...\n";
@@ -437,6 +437,8 @@ sub cmd_dcommit {
                     "If these changes depend on each other, re-running ",
                     "without --no-rebase may be required."
        }
+       my $expect_url = $url;
+       Git::SVN::remove_username($expect_url);
        while (1) {
                my $d = shift @$linear_refs or last;
                unless (defined $last_rev) {
@@ -511,9 +513,9 @@ sub cmd_dcommit {
                                          $gs->refname,
                                          "\nBefore dcommitting";
                                }
-                               if ($url_ ne $url) {
+                               if ($url_ ne $expect_url) {
                                        fatal "URL mismatch after rebase: ",
-                                             "$url_ != $url";
+                                             "$url_ != $expect_url";
                                }
                                if ($uuid_ ne $uuid) {
                                        fatal "uuid mismatch after rebase: ",
@@ -1124,7 +1126,7 @@ sub read_repo_config {
                my $v = $opts->{$o};
                my ($key) = ($o =~ /^([a-zA-Z\-]+)/);
                $key =~ s/-//g;
-               my $arg = 'git-config';
+               my $arg = 'git config';
                $arg .= ' --int' if ($o =~ /[:=]i$/);
                $arg .= ' --bool' if ($o !~ /[:=][sfi]$/);
                if (ref $v eq 'ARRAY') {
@@ -1265,7 +1267,7 @@ sub md5sum {
        my $arg = shift;
        my $ref = ref $arg;
        my $md5 = Digest::MD5->new();
-        if ($ref eq 'GLOB' || $ref eq 'IO::File') {
+        if ($ref eq 'GLOB' || $ref eq 'IO::File' || $ref eq 'File::Temp') {
                $md5->addfile($arg) or croak $!;
        } elsif ($ref eq 'SCALAR') {
                $md5->add($$arg) or croak $!;
@@ -1328,6 +1330,7 @@ BEGIN
        }
 }
 
+
 my (%LOCKFILES, %INDEX_FILES);
 END {
        unlink keys %LOCKFILES if %LOCKFILES;
@@ -2199,7 +2202,7 @@ sub do_git_commit {
        }
        die "Tree is not a valid sha1: $tree\n" if $tree !~ /^$::sha1$/o;
 
-       my @exec = ('git-commit-tree', $tree);
+       my @exec = ('git', 'commit-tree', $tree);
        foreach ($self->get_commit_parents($log_entry)) {
                push @exec, '-p', $_;
        }
@@ -2315,12 +2318,20 @@ sub find_parent_branch {
                $gs = Git::SVN->init($u, $p, $repo_id, $ref_id, 1);
        }
        my ($r0, $parent) = $gs->find_rev_before($r, 1);
-       if (!defined $r0 || !defined $parent) {
-               my ($base, $head) = parse_revision_argument(0, $r);
-               if ($base <= $r) {
+       {
+               my ($base, $head);
+               if (!defined $r0 || !defined $parent) {
+                       ($base, $head) = parse_revision_argument(0, $r);
+               } else {
+                       if ($r0 < $r) {
+                               $gs->ra->get_log([$gs->{path}], $r0 + 1, $r, 1,
+                                       0, 1, sub { $base = $_[1] - 1 });
+                       }
+               }
+               if (defined $base && $base <= $r) {
                        $gs->fetch($base, $r);
                }
-               ($r0, $parent) = $gs->last_rev_commit;
+               ($r0, $parent) = $gs->find_rev_before($r, 1);
        }
        if (defined $r0 && defined $parent) {
                print STDERR "Found branch parent: ($self->{ref_id}) $parent\n";
@@ -2568,7 +2579,7 @@ sub set_tree {
        my ($self, $tree) = (shift, shift);
        my $log_entry = ::get_commit_entry($tree);
        unless ($self->{last_rev}) {
-               fatal("Must have an existing revision to commit");
+               ::fatal("Must have an existing revision to commit");
        }
        my %ed_opts = ( r => $self->{last_rev},
                        log => $log_entry->{log},
@@ -3230,13 +3241,11 @@ sub change_file_prop {
 
 sub apply_textdelta {
        my ($self, $fb, $exp) = @_;
-       my $fh = IO::File->new_tmpfile;
-       $fh->autoflush(1);
+       my $fh = Git::temp_acquire('svn_delta');
        # $fh gets auto-closed() by SVN::TxDelta::apply(),
        # (but $base does not,) so dup() it for reading in close_file
        open my $dup, '<&', $fh or croak $!;
-       my $base = IO::File->new_tmpfile;
-       $base->autoflush(1);
+       my $base = Git::temp_acquire('git_blob');
        if ($fb->{blob}) {
                print $base 'link ' if ($fb->{mode_a} == 120000);
                my $size = $::_repository->cat_blob($fb->{blob}, $base);
@@ -3251,9 +3260,9 @@ sub apply_textdelta {
                }
        }
        seek $base, 0, 0 or croak $!;
-       $fb->{fh} = $dup;
+       $fb->{fh} = $fh;
        $fb->{base} = $base;
-       [ SVN::TxDelta::apply($base, $fh, undef, $fb->{path}, $fb->{pool}) ];
+       [ SVN::TxDelta::apply($base, $dup, undef, $fb->{path}, $fb->{pool}) ];
 }
 
 sub close_file {
@@ -3269,35 +3278,36 @@ sub close_file {
                                    "expected: $exp\n    got: $got\n";
                        }
                }
-               sysseek($fh, 0, 0) or croak $!;
                if ($fb->{mode_b} == 120000) {
-                       eval {
-                               sysread($fh, my $buf, 5) == 5 or croak $!;
-                               $buf eq 'link ' or die "$path has mode 120000",
-                                                      " but is not a link";
-                       };
-                       if ($@) {
-                               warn "$@\n";
-                               sysseek($fh, 0, 0) or croak $!;
-                       }
-               }
+                       sysseek($fh, 0, 0) or croak $!;
+                       sysread($fh, my $buf, 5) == 5 or croak $!;
 
-               my ($tmp_fh, $tmp_filename) = File::Temp::tempfile(UNLINK => 1);
-               my $result;
-               while ($result = sysread($fh, my $string, 1024)) {
-                       my $wrote = syswrite($tmp_fh, $string, $result);
-                       defined($wrote) && $wrote == $result
-                               or croak("write $tmp_filename: $!\n");
-               }
-               defined $result or croak $!;
-               close $tmp_fh or croak $!;
+                       unless ($buf eq 'link ') {
+                               warn "$path has mode 120000",
+                                               " but is not a link\n";
+                       } else {
+                               my $tmp_fh = Git::temp_acquire('svn_hash');
+                               my $res;
+                               while ($res = sysread($fh, my $str, 1024)) {
+                                       my $out = syswrite($tmp_fh, $str, $res);
+                                       defined($out) && $out == $res
+                                               or croak("write ",
+                                                       Git::temp_path($tmp_fh),
+                                                       ": $!\n");
+                               }
+                               defined $res or croak $!;
 
-               close $fh or croak $!;
+                               ($fh, $tmp_fh) = ($tmp_fh, $fh);
+                               Git::temp_release($tmp_fh, 1);
+                       }
+               }
 
-               $hash = $::_repository->hash_and_insert_object($tmp_filename);
-               unlink($tmp_filename);
+               $hash = $::_repository->hash_and_insert_object(
+                               Git::temp_path($fh));
                $hash =~ /^[a-f\d]{40}$/ or die "not a sha1: $hash\n";
-               close $fb->{base} or croak $!;
+
+               Git::temp_release($fb->{base}, 1);
+               Git::temp_release($fh, 1);
        } else {
                $hash = $fb->{blob} or die "no blob information\n";
        }
@@ -3667,7 +3677,7 @@ sub chg_file {
        } elsif ($m->{mode_b} !~ /755$/ && $m->{mode_a} =~ /755$/) {
                $self->change_file_prop($fbat,'svn:executable',undef);
        }
-       my $fh = IO::File->new_tmpfile or croak $!;
+       my $fh = Git::temp_acquire('git_blob');
        if ($m->{mode_b} =~ /^120/) {
                print $fh 'link ' or croak $!;
                $self->change_file_prop($fbat,'svn:special','*');
@@ -3686,9 +3696,8 @@ sub chg_file {
        my $atd = $self->apply_textdelta($fbat, undef, $pool);
        my $got = SVN::TxDelta::send_stream($fh, @$atd, $pool);
        die "Checksum mismatch\nexpected: $exp\ngot: $got\n" if ($got ne $exp);
+       Git::temp_release($fh, 1);
        $pool->clear;
-
-       close $fh or croak $!;
 }
 
 sub D {
@@ -3968,21 +3977,21 @@ sub gs_do_switch {
        my $old_url = $full_url;
        $full_url .= '/' . escape_uri_only($path) if length $path;
        my ($ra, $reparented);
-       if ($old_url ne $full_url) {
-               if ($old_url !~ m#^svn(\+ssh)?://#) {
-                       SVN::_Ra::svn_ra_reparent($self->{session}, $full_url,
-                                                 $pool);
-                       $self->{url} = $full_url;
-                       $reparented = 1;
-               } else {
-                       $_[0] = undef;
-                       $self = undef;
-                       $RA = undef;
-                       $ra = Git::SVN::Ra->new($full_url);
-                       $ra_invalid = 1;
-               }
+
+       if ($old_url =~ m#^svn(\+ssh)?://#) {
+               $_[0] = undef;
+               $self = undef;
+               $RA = undef;
+               $ra = Git::SVN::Ra->new($full_url);
+               $ra_invalid = 1;
+       } elsif ($old_url ne $full_url) {
+               SVN::_Ra::svn_ra_reparent($self->{session}, $full_url, $pool);
+               $self->{url} = $full_url;
+               $reparented = 1;
        }
+
        $ra ||= $self;
+       $url_b = escape_url($url_b);
        my $reporter = $ra->do_switch($rev_b, '', 1, $url_b, $editor, $pool);
        my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef) : ();
        $reporter->set_path('', $rev_a, 0, @lock, $pool);
@@ -4382,7 +4391,7 @@ sub config_pager {
 
 sub run_pager {
        return unless -t *STDOUT && defined $pager;
-       pipe my $rfd, my $wfd or return;
+       pipe my ($rfd, $wfd) or return;
        defined(my $pid = fork) or ::fatal "Can't fork: $!";
        if (!$pid) {
                open STDOUT, '>&', $wfd or