Code

Documentation/config.txt: Correct info about subsection name
[git.git] / git-svn.perl
index b28c5bbc7238120d1d98445f1bf0f116dd7a0b8a..83ec03d4786a39f250f8f83c075c9dabf782b1db 100755 (executable)
@@ -70,7 +70,7 @@ my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit,
        $_version, $_upgrade, $_authors, $_branch_all_refs, @_opt_m,
        $_merge, $_strategy, $_dry_run, $_ignore_nodate, $_non_recursive,
        $_username, $_config_dir, $_no_auth_cache,
-       $_pager, $_color);
+       $_pager, $_color, $_prefix);
 my (@_branch_from, %tree_map, %users, %rusers, %equiv);
 my ($_svn_can_do_switch);
 my @repo_path_split_cache;
@@ -102,7 +102,7 @@ my %cmt_opts = ( 'edit|e' => \$_edit,
 );
 
 my %cmd = (
-       fetch => [ \&fetch, "Download new revisions from SVN",
+       fetch => [ \&cmd_fetch, "Download new revisions from SVN",
                        { 'revision|r=s' => \$_revision, %fc_opts } ],
        init => [ \&init, "Initialize a repo for tracking" .
                          " (requires URL argument)",
@@ -134,6 +134,7 @@ my %cmd = (
                         'username=s' => \$_username,
                         'config-dir=s' => \$_config_dir,
                         'no-auth-cache' => \$_no_auth_cache,
+                        'prefix=s' => \$_prefix,
                        } ],
        'multi-fetch' => [ \&multi_fetch,
                        'Fetch multiple trees (like git-svnimport)',
@@ -285,7 +286,7 @@ sub init {
 
        $SVN_URL = $url;
        unless (-d $GIT_DIR) {
-               my @init_db = ('init-db');
+               my @init_db = ('init');
                push @init_db, "--template=$_template" if defined $_template;
                push @init_db, "--shared" if defined $_shared;
                command_noisy(@init_db);
@@ -293,6 +294,10 @@ sub init {
        setup_git_svn();
 }
 
+sub cmd_fetch {
+       fetch_child_id($GIT_SVN, @_);
+}
+
 sub fetch {
        check_upgrade_needed();
        $SVN_URL ||= file_to_s("$GIT_SVN_DIR/info/url");
@@ -532,7 +537,7 @@ sub show_ignore {
        my $repo;
        $SVN ||= libsvn_connect($SVN_URL);
        my $r = defined $_revision ? $_revision : $SVN->get_latest_revnum;
-       libsvn_traverse_ignore(\*STDOUT, $SVN->{svn_path}, $r);
+       libsvn_traverse_ignore(\*STDOUT, '', $r);
 }
 
 sub graft_branches {
@@ -571,31 +576,29 @@ sub graft_branches {
 
 sub multi_init {
        my $url = shift;
-       $_trunk ||= 'trunk';
-       $_trunk =~ s#/+$##;
-       $url =~ s#/+$## if $url;
-       if ($_trunk !~ m#^[a-z\+]+://#) {
-               $_trunk = '/' . $_trunk if ($_trunk !~ m#^/#);
-               unless ($url) {
-                       print STDERR "E: '$_trunk' is not a complete URL ",
-                               "and a separate URL is not specified\n";
-                       exit 1;
-               }
-               $_trunk = $url . $_trunk;
+       unless (defined $_trunk || defined $_branches || defined $_tags) {
+               usage(1);
        }
-       my $ch_id;
-       if ($GIT_SVN eq 'git-svn') {
-               $ch_id = 1;
-               $GIT_SVN = $ENV{GIT_SVN_ID} = 'trunk';
-       }
-       init_vars();
-       unless (-d $GIT_SVN_DIR) {
-               print "GIT_SVN_ID set to 'trunk' for $_trunk\n" if $ch_id;
-               init($_trunk);
-               command_noisy('repo-config', 'svn.trunk', $_trunk);
+       if (defined $_trunk) {
+               my $trunk_url = complete_svn_url($url, $_trunk);
+               my $ch_id;
+               if ($GIT_SVN eq 'git-svn') {
+                       $ch_id = 1;
+                       $GIT_SVN = $ENV{GIT_SVN_ID} = 'trunk';
+               }
+               init_vars();
+               unless (-d $GIT_SVN_DIR) {
+                       if ($ch_id) {
+                               print "GIT_SVN_ID set to 'trunk' for ",
+                                     "$trunk_url ($_trunk)\n";
+                       }
+                       init($trunk_url);
+                       command_noisy('repo-config', 'svn.trunk', $trunk_url);
+               }
        }
-       complete_url_ls_init($url, $_branches, '--branches/-b', '');
-       complete_url_ls_init($url, $_tags, '--tags/-t', 'tags/');
+       $_prefix = '' unless defined $_prefix;
+       complete_url_ls_init($url, $_branches, '--branches/-b', $_prefix);
+       complete_url_ls_init($url, $_tags, '--tags/-t', $_prefix . 'tags/');
 }
 
 sub multi_fetch {
@@ -839,7 +842,6 @@ sub fetch_child_id {
        my $ref = "$GIT_DIR/refs/remotes/$id";
        defined(my $pid = open my $fh, '-|') or croak $!;
        if (!$pid) {
-               $_repack = undef;
                $GIT_SVN = $ENV{GIT_SVN_ID} = $id;
                init_vars();
                fetch(@_);
@@ -847,7 +849,7 @@ sub fetch_child_id {
        }
        while (<$fh>) {
                print $_;
-               check_repack() if (/^r\d+ = $sha1/);
+               check_repack() if (/^r\d+ = $sha1/o);
        }
        close $fh or croak $?;
 }
@@ -872,29 +874,34 @@ sub rec_fetch {
        }
 }
 
+sub complete_svn_url {
+       my ($url, $path) = @_;
+       $path =~ s#/+$##;
+       $url =~ s#/+$## if $url;
+       if ($path !~ m#^[a-z\+]+://#) {
+               $path = '/' . $path if ($path !~ m#^/#);
+               if (!defined $url || $url !~ m#^[a-z\+]+://#) {
+                       fatal("E: '$path' is not a complete URL ",
+                             "and a separate URL is not specified\n");
+               }
+               $path = $url . $path;
+       }
+       return $path;
+}
+
 sub complete_url_ls_init {
-       my ($url, $var, $switch, $pfx) = @_;
-       unless ($var) {
+       my ($url, $path, $switch, $pfx) = @_;
+       unless ($path) {
                print STDERR "W: $switch not specified\n";
                return;
        }
-       $var =~ s#/+$##;
-       if ($var !~ m#^[a-z\+]+://#) {
-               $var = '/' . $var if ($var !~ m#^/#);
-               unless ($url) {
-                       print STDERR "E: '$var' is not a complete URL ",
-                               "and a separate URL is not specified\n";
-                       exit 1;
-               }
-               $var = $url . $var;
-       }
-       my @ls = libsvn_ls_fullurl($var);
-       my $old = $GIT_SVN;
+       my $full_url = complete_svn_url($url, $path);
+       my @ls = libsvn_ls_fullurl($full_url);
        defined(my $pid = fork) or croak $!;
        if (!$pid) {
-               foreach my $u (map { "$var/$_" } (grep m!/$!, @ls)) {
+               foreach my $u (map { "$full_url/$_" } (grep m!/$!, @ls)) {
                        $u =~ s#/+$##;
-                       if ($u !~ m!\Q$var\E/(.+)$!) {
+                       if ($u !~ m!\Q$full_url\E/(.+)$!) {
                                print STDERR "W: Unrecognized URL: $u\n";
                                die "This should never happen\n";
                        }
@@ -912,7 +919,7 @@ sub complete_url_ls_init {
        waitpid $pid, 0;
        croak $? if $?;
        my ($n) = ($switch =~ /^--(\w+)/);
-       command_noisy('repo-config', "svn.$n", $var);
+       command_noisy('repo-config', "svn.$n", $full_url);
 }
 
 sub common_prefix {
@@ -1079,7 +1086,7 @@ sub graft_merge_msg {
        my ($grafts, $l_map, $u, $p, @re) = @_;
 
        my $x = $l_map->{$u}->{$p};
-       my $rl = rev_list_raw($x);
+       my $rl = rev_list_raw("refs/remotes/$x");
        while (my $c = next_rev_list_entry($rl)) {
                foreach my $re (@re) {
                        my (@br) = ($c->{m} =~ /$re/g);
@@ -1405,7 +1412,6 @@ sub git_commit {
 
        # this output is read via pipe, do not change:
        print "r$log_msg->{revision} = $commit\n";
-       check_repack();
        return $commit;
 }
 
@@ -1912,7 +1918,8 @@ sub _simple_prompt {
        $default_username = $_username if defined $_username;
        if (defined $default_username && length $default_username) {
                if (defined $realm && length $realm) {
-                       print "Authentication realm: $realm\n";
+                       print STDERR "Authentication realm: $realm\n";
+                       STDERR->flush;
                }
                $cred->username($default_username);
        } else {
@@ -1927,36 +1934,38 @@ sub _simple_prompt {
 sub _ssl_server_trust_prompt {
        my ($cred, $realm, $failures, $cert_info, $may_save, $pool) = @_;
        $may_save = undef if $_no_auth_cache;
-       print "Error validating server certificate for '$realm':\n";
+       print STDERR "Error validating server certificate for '$realm':\n";
        if ($failures & $SVN::Auth::SSL::UNKNOWNCA) {
-               print " - The certificate is not issued by a trusted ",
+               print STDERR " - The certificate is not issued by a trusted ",
                      "authority. Use the\n",
                      "   fingerprint to validate the certificate manually!\n";
        }
        if ($failures & $SVN::Auth::SSL::CNMISMATCH) {
-               print " - The certificate hostname does not match.\n";
+               print STDERR " - The certificate hostname does not match.\n";
        }
        if ($failures & $SVN::Auth::SSL::NOTYETVALID) {
-               print " - The certificate is not yet valid.\n";
+               print STDERR " - The certificate is not yet valid.\n";
        }
        if ($failures & $SVN::Auth::SSL::EXPIRED) {
-               print " - The certificate has expired.\n";
+               print STDERR " - The certificate has expired.\n";
        }
        if ($failures & $SVN::Auth::SSL::OTHER) {
-               print " - The certificate has an unknown error.\n";
+               print STDERR " - The certificate has an unknown error.\n";
        }
-       printf( "Certificate information:\n".
+       printf STDERR
+               "Certificate information:\n".
                " - Hostname: %s\n".
                " - Valid: from %s until %s\n".
                " - Issuer: %s\n".
                " - Fingerprint: %s\n",
                map $cert_info->$_, qw(hostname valid_from valid_until
-                                      issuer_dname fingerprint) );
+                                      issuer_dname fingerprint);
        my $choice;
 prompt:
-       print $may_save ?
+       print STDERR $may_save ?
              "(R)eject, accept (t)emporarily or accept (p)ermanently? " :
              "(R)eject or accept (t)emporarily? ";
+       STDERR->flush;
        $choice = lc(substr(<STDIN> || 'R', 0, 1));
        if ($choice =~ /^t$/i) {
                $cred->may_save(undef);
@@ -1974,7 +1983,8 @@ prompt:
 sub _ssl_client_cert_prompt {
        my ($cred, $realm, $may_save, $pool) = @_;
        $may_save = undef if $_no_auth_cache;
-       print "Client certificate filename: ";
+       print STDERR "Client certificate filename: ";
+       STDERR->flush;
        chomp(my $filename = <STDIN>);
        $cred->cert_file($filename);
        $cred->may_save($may_save);
@@ -1993,13 +2003,14 @@ sub _username_prompt {
        my ($cred, $realm, $may_save, $pool) = @_;
        $may_save = undef if $_no_auth_cache;
        if (defined $realm && length $realm) {
-               print "Authentication realm: $realm\n";
+               print STDERR "Authentication realm: $realm\n";
        }
        my $username;
        if (defined $_username) {
                $username = $_username;
        } else {
-               print "Username: ";
+               print STDERR "Username: ";
+               STDERR->flush;
                chomp($username = <STDIN>);
        }
        $cred->username($username);
@@ -2009,7 +2020,8 @@ sub _username_prompt {
 
 sub _read_password {
        my ($prompt, $realm) = @_;
-       print $prompt;
+       print STDERR $prompt;
+       STDERR->flush;
        require Term::ReadKey;
        Term::ReadKey::ReadMode('noecho');
        my $password = '';
@@ -2018,7 +2030,8 @@ sub _read_password {
                $password .= $key;
        }
        Term::ReadKey::ReadMode('restore');
-       print "\n";
+       print STDERR "\n";
+       STDERR->flush;
        $password;
 }
 
@@ -2843,7 +2856,7 @@ sub rmdirs {
        foreach my $d (sort { $b =~ tr#/#/# <=> $a =~ tr#/#/# } keys %$rm) {
                $self->close_directory($bat->{$d}, $p);
                my ($dn) = ($d =~ m#^(.*?)/?(?:[^/]+)$#);
-               print "\tD+\t/$d/\n" unless $q;
+               print "\tD+\t$d/\n" unless $q;
                $self->SUPER::delete_entry($d, $r, $bat->{$dn}, $p);
                delete $bat->{$d};
        }