t5300: add test for "unpack-objects --strict"
[gitweb.git] / git-svn.perl
index 9b1113a33660c3a6565db2f81cb854e8640db6c5..9e2faf90aa1676974234882a2f557c17f7bc59f4 100755 (executable)
@@ -186,6 +186,9 @@ BEGIN
                    "Show info about the latest SVN revision
                     on the current branch",
                    { 'url' => \$_url, } ],
+       'blame' => [ \&Git::SVN::Log::cmd_blame,
+                   "Show what revision and author last modified each line of a file",
+                   {} ],
 );
 
 my $cmd;
@@ -1247,7 +1250,8 @@ package Git::SVN;
 use File::Copy qw/copy/;
 use IPC::Open3;
 
-my $_repack_nr;
+my ($_gc_nr, $_gc_period);
+
 # properties that we do not log:
 my %SKIP_PROP;
 BEGIN {
@@ -1283,8 +1287,11 @@ BEGIN
        }
 }
 
-my %LOCKFILES;
-END { unlink keys %LOCKFILES if %LOCKFILES }
+my (%LOCKFILES, %INDEX_FILES);
+END {
+       unlink keys %LOCKFILES if %LOCKFILES;
+       unlink keys %INDEX_FILES if %INDEX_FILES;
+}
 
 sub resolve_local_globs {
        my ($url, $fetch, $glob_spec) = @_;
@@ -1376,7 +1383,6 @@ sub fetch_all {
 
        ($base, $head) = parse_revision_argument($base, $head);
        $ra->gs_fetch_loop_common($base, $head, \@gs, \@globs);
-       unlink $_->{index} foreach @gs;
 }
 
 sub read_all_remotes {
@@ -1406,10 +1412,9 @@ sub read_all_remotes {
 }
 
 sub init_vars {
-       if (defined $_repack) {
-               $_repack = 1000 if ($_repack <= 0);
-               $_repack_nr = $_repack;
-               $_repack_flags ||= '-d';
+       $_gc_nr = $_gc_period = 1000;
+       if (defined $_repack || defined $_repack_flags) {
+              warn "Repack options are obsolete; they have no effect.\n";
        }
 }
 
@@ -1756,10 +1761,16 @@ sub svnsync {
        # see if we have it in our config, first:
        eval {
                my $section = "svn-remote.$self->{repo_id}";
-               $svnsync = {
-                 url => tmp_config('--get', "$section.svnsync-url"),
-                 uuid => tmp_config('--get', "$section.svnsync-uuid"),
-               }
+
+               my $url = tmp_config('--get', "$section.svnsync-url");
+               ($url) = ($url =~ m{^([a-z\+]+://\S+)$}) or
+                  die "doesn't look right - svn:sync-from-url is '$url'\n";
+
+               my $uuid = tmp_config('--get', "$section.svnsync-uuid");
+               ($uuid) = ($uuid =~ m{^([0-9a-f\-]{30,})$}) or
+                  die "doesn't look right - svn:sync-from-uuid is '$uuid'\n";
+
+               $svnsync = { url => $url, uuid => $uuid }
        };
        if ($svnsync && $svnsync->{url} && $svnsync->{uuid}) {
                return $self->{svnsync} = $svnsync;
@@ -1770,11 +1781,11 @@ sub svnsync {
        my $rp = $self->ra->rev_proplist(0);
 
        my $url = $rp->{'svn:sync-from-url'} or die $err . "url\n";
-       $url =~ m{^[a-z\+]+://} or
+       ($url) = ($url =~ m{^([a-z\+]+://\S+)$}) or
                   die "doesn't look right - svn:sync-from-url is '$url'\n";
 
        my $uuid = $rp->{'svn:sync-from-uuid'} or die $err . "uuid\n";
-       $uuid =~ m{^[0-9a-f\-]{30,}$} or
+       ($uuid) = ($uuid =~ m{^([0-9a-f\-]{30,})$}) or
                   die "doesn't look right - svn:sync-from-uuid is '$uuid'\n";
 
        my $section = "svn-remote.$self->{repo_id}";
@@ -1856,6 +1867,7 @@ sub rel_path {
 sub prop_walk {
        my ($self, $path, $rev, $sub) = @_;
 
+       $path =~ s#^/##;
        my ($dirent, undef, $props) = $self->ra->get_dir($path, $rev);
        $path =~ s#^/*#/#g;
        my $p = $path;
@@ -2089,6 +2101,10 @@ sub restore_commit_header_env {
        }
 }
 
+sub gc {
+       command_noisy('gc', '--auto');
+};
+
 sub do_git_commit {
        my ($self, $log_entry) = @_;
        my $lr = $self->last_rev;
@@ -2142,12 +2158,9 @@ sub do_git_commit {
                                   0, $self->svm_uuid);
        }
        print " = $commit ($self->{ref_id})\n";
-       if (defined $_repack && (--$_repack_nr == 0)) {
-               $_repack_nr = $_repack;
-               # repack doesn't use any arguments with spaces in them, does it?
-               print "Running git repack $_repack_flags ...\n";
-               command_noisy('repack', split(/\s+/, $_repack_flags));
-               print "Done repacking\n";
+       if (--$_gc_nr == 0) {
+               $_gc_nr = $_gc_period;
+               gc();
        }
        return $commit;
 }
@@ -2219,7 +2232,12 @@ sub find_parent_branch {
                # just grow a tail if we're not unique enough :x
                $ref_id .= '-' while find_ref($ref_id);
                print STDERR "Initializing parent: $ref_id\n";
-               $gs = Git::SVN->init($new_url, '', $ref_id, $ref_id, 1);
+               my ($u, $p) = ($new_url, '');
+               if ($u =~ s#^\Q$url\E(/|$)##) {
+                       $p = $u;
+                       $u = $url;
+               }
+               $gs = Git::SVN->init($u, $p, $self->{repo_id}, $ref_id, 1);
        }
        my ($r0, $parent) = $gs->find_rev_before($r, 1);
        if (!defined $r0 || !defined $parent) {
@@ -3625,6 +3643,7 @@ ()
          SVN::Client::get_ssl_client_cert_file_provider(),
          SVN::Client::get_ssl_client_cert_prompt_provider(
            \&Git::SVN::Prompt::ssl_client_cert, 2),
+         SVN::Client::get_ssl_client_cert_pw_file_provider(),
          SVN::Client::get_ssl_client_cert_pw_prompt_provider(
            \&Git::SVN::Prompt::ssl_client_cert_pw, 2),
          SVN::Client::get_username_provider(),
@@ -3945,6 +3964,7 @@ sub gs_fetch_loop_common {
                                if ($log_entry) {
                                        $gs->do_git_commit($log_entry);
                                }
+                               $INDEX_FILES{$gs->{index}} = 1;
                        }
                        foreach my $g (@$globs) {
                                my $k = "svn-remote.$g->{remote}." .
@@ -3975,6 +3995,7 @@ sub gs_fetch_loop_common {
                $max += $inc;
                $max = $head if ($max > $head);
        }
+       Git::SVN::gc();
 }
 
 sub match_globs {
@@ -4082,6 +4103,10 @@ sub skip_unknown_revs {
                        warn "W: Ignoring error from SVN, path probably ",
                             "does not exist: ($errno): ",
                             $err->expanded_message,"\n";
+                       warn "W: Do not be alarmed at the above message ",
+                            "git-svn is just searching aggressively for ",
+                            "old history.\n",
+                            "This may take a while on large repositories\n";
                        $ignored_err{$err_key} = 1;
                }
                return;
@@ -4427,6 +4452,24 @@ sub cmd_show_log {
        print commit_log_separator unless $incremental || $oneline;
 }
 
+sub cmd_blame {
+       my $path = shift;
+
+       config_pager();
+       run_pager();
+
+       my ($fh, $ctx) = command_output_pipe('blame', @_, $path);
+       while (my $line = <$fh>) {
+               if ($line =~ /^\^?([[:xdigit:]]+)\s/) {
+                       my (undef, $rev, undef) = ::cmt_metadata($1);
+                       $rev = sprintf('%-10s', $rev);
+                       $line =~ s/^\^?[[:xdigit:]]+(\s)/$rev$1/;
+               }
+               print $line;
+       }
+       command_close_pipe($fh, $ctx);
+}
+
 package Git::SVN::Migration;
 # these version numbers do NOT correspond to actual version numbers
 # of git nor git-svn.  They are just relative.