Code

Revert "builtin-archive: use RUN_SETUP"
[git.git] / git-svn.perl
index 1bcf058ef662081bff7116df3a0d78db03bfdf4f..d307d430f3a9475ff6db3fb73bad44bf37dfa404 100755 (executable)
@@ -9,6 +9,7 @@ use vars qw/    $AUTHOR $VERSION
 $AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
 $VERSION = '@@GIT_VERSION@@';
 
+my $git_dir_user_set = 1 if defined $ENV{GIT_DIR};
 $ENV{GIT_DIR} ||= '.git';
 $Git::SVN::default_repo_id = 'svn';
 $Git::SVN::default_ref_id = $ENV{GIT_SVN_ID} || 'git-svn';
@@ -55,7 +56,7 @@ my ($_stdin, $_help, $_edit,
        $_message, $_file,
        $_template, $_shared,
        $_version, $_fetch_all,
-       $_merge, $_strategy, $_dry_run,
+       $_merge, $_strategy, $_dry_run, $_local,
        $_prefix, $_no_checkout, $_verbose);
 $Git::SVN::_follow_parent = 1;
 my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
@@ -75,9 +76,14 @@ my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent,
                %remote_opts );
 
 my ($_trunk, $_tags, $_branches);
+my %icv;
 my %init_opts = ( 'template=s' => \$_template, 'shared:s' => \$_shared,
                   'trunk|T=s' => \$_trunk, 'tags|t=s' => \$_tags,
                   'branches|b=s' => \$_branches, 'prefix=s' => \$_prefix,
+                 'no-metadata' => sub { $icv{noMetadata} = 1 },
+                 'use-svm-props' => sub { $icv{useSvmProps} = 1 },
+                 'use-svnsync-props' => sub { $icv{useSvnsyncProps} = 1 },
+                 'rewrite-root=s' => sub { $icv{rewriteRoot} = $_[1] },
                   %remote_opts );
 my %cmt_opts = ( 'edit|e' => \$_edit,
                'rmdir' => \$SVN::Git::Editor::_rmdir,
@@ -139,6 +145,7 @@ my %cmd = (
                        { 'merge|m|M' => \$_merge,
                          'verbose|v' => \$_verbose,
                          'strategy|s=s' => \$_strategy,
+                         'local|l' => \$_local,
                          'fetch-all|all' => \$_fetch_all,
                          %fc_opts } ],
        'commit-diff' => [ \&cmd_commit_diff,
@@ -173,6 +180,28 @@ usage(0) if $_help;
 version() if $_version;
 usage(1) unless defined $cmd;
 load_authors() if $_authors;
+
+# make sure we're always running
+unless ($cmd =~ /(?:clone|init|multi-init)$/) {
+       unless (-d $ENV{GIT_DIR}) {
+               if ($git_dir_user_set) {
+                       die "GIT_DIR=$ENV{GIT_DIR} explicitly set, ",
+                           "but it is not a directory\n";
+               }
+               my $git_dir = delete $ENV{GIT_DIR};
+               chomp(my $cdup = command_oneline(qw/rev-parse --show-cdup/));
+               unless (length $cdup) {
+                       die "Already at toplevel, but $git_dir ",
+                           "not found '$cdup'\n";
+               }
+               chdir $cdup or die "Unable to chdir up to '$cdup'\n";
+               unless (-d $git_dir) {
+                       die "$git_dir still not found after going to ",
+                           "'$cdup'\n";
+               }
+               $ENV{GIT_DIR} = $git_dir;
+       }
+}
 unless ($cmd =~ /^(?:clone|init|multi-init|commit-diff)$/) {
        Git::SVN::Migration::migration_check();
 }
@@ -234,13 +263,21 @@ sub do_git_init_db {
                }
                command_noisy(@init_db);
        }
+       my $set;
+       my $pfx = "svn-remote.$Git::SVN::default_repo_id";
+       foreach my $i (keys %icv) {
+               die "'$set' and '$i' cannot both be set\n" if $set;
+               next unless defined $icv{$i};
+               command_noisy('config', "$pfx.$i", $icv{$i});
+               $set = $i;
+       }
 }
 
 sub init_subdir {
        my $repo_path = shift or return;
        mkpath([$repo_path]) unless -d $repo_path;
        chdir $repo_path or die "Couldn't chdir to $repo_path: $!\n";
-       $ENV{GIT_DIR} = $repo_path . "/.git";
+       $ENV{GIT_DIR} = '.git';
 }
 
 sub cmd_clone {
@@ -250,12 +287,8 @@ sub cmd_clone {
            $url !~ m#^[a-z\+]+://#) {
                $path = $url;
        }
-       warn "--path: $path\n" if defined $path;
        $path = basename($url) if !defined $path || !length $path;
-       warn "++path: $path\n" if defined $path;
-       mkpath([$path]);
-       chdir $path or die "Couldn't chdir to $path\n";
-       cmd_init(@_);
+       cmd_init($url, $path);
        Git::SVN::fetch_all($Git::SVN::default_repo_id);
 }
 
@@ -402,19 +435,25 @@ sub cmd_rebase {
        }
 
        my $gs = Git::SVN->find_by_url($url);
+       unless ($gs) {
+               die "Unable to determine remote information from URL: $url\n";
+       }
        if (command(qw/diff-index HEAD --/)) {
                print STDERR "Cannot rebase with uncommited changes:\n";
                command_noisy('status');
                exit 1;
        }
-       $_fetch_all ? $gs->fetch_all : $gs->fetch;
+       unless ($_local) {
+               $_fetch_all ? $gs->fetch_all : $gs->fetch;
+       }
        command_noisy(rebase_cmd(), $gs->refname);
 }
 
 sub cmd_show_ignore {
-       my $gs = Git::SVN->new;
+       my $url = (::working_head_info('HEAD'))[0];
+       my $gs = Git::SVN->find_by_url($url) || Git::SVN->new;
        my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
-       $gs->traverse_ignore(\*STDOUT, '', $r);
+       $gs->traverse_ignore(\*STDOUT, $gs->{path}, $r);
 }
 
 sub cmd_multi_init {
@@ -422,12 +461,12 @@ sub cmd_multi_init {
        unless (defined $_trunk || defined $_branches || defined $_tags) {
                usage(1);
        }
-       do_git_init_db();
        $_prefix = '' unless defined $_prefix;
        if (defined $url) {
                $url =~ s#/+$##;
                init_subdir(@_);
        }
+       do_git_init_db();
        if (defined $_trunk) {
                my $trunk_ref = $_prefix . 'trunk';
                # try both old-style and new-style lookups:
@@ -1021,6 +1060,7 @@ sub init_remote_config {
 
 sub find_by_url { # repos_root and, path are optional
        my ($class, $full_url, $repos_root, $path) = @_;
+       return undef unless defined $full_url;
        my $remotes = read_all_remotes();
        if (defined $full_url && defined $repos_root && !defined $path) {
                $path = $full_url;
@@ -1290,8 +1330,10 @@ sub rel_path {
        my ($self) = @_;
        my $repos_root = $self->ra->{repos_root};
        return $self->{path} if ($self->{url} eq $repos_root);
-       die "BUG: rel_path failed! repos_root: $repos_root, Ra URL: ",
-           $self->ra->{url}, " path: $self->{path},  URL: $self->{url}\n";
+       my $url = $self->{url} .
+                 (length $self->{path} ? "/$self->{path}" : $self->{path});
+       $url =~ s!^\Q$repos_root\E(?:/+|$)!!g;
+       $url;
 }
 
 sub traverse_ignore {
@@ -1300,7 +1342,7 @@ sub traverse_ignore {
        my $ra = $self->ra;
        my ($dirent, undef, $props) = $ra->get_dir($path, $r);
        my $p = $path;
-       $p =~ s#^\Q$ra->{svn_path}\E/##;
+       $p =~ s#^\Q$self->{path}\E(/|$)##;
        print $fh length $p ? "\n# $p\n" : "\n# /\n";
        if (my $s = $props->{'svn:ignore'}) {
                $s =~ s/[\r\n]+/\n/g;
@@ -1641,9 +1683,9 @@ sub find_parent_branch {
        }
        if (defined $r0 && defined $parent) {
                print STDERR "Found branch parent: ($self->{ref_id}) $parent\n";
-               $self->assert_index_clean($parent);
                my $ed;
                if ($self->ra->can_do_switch) {
+                       $self->assert_index_clean($parent);
                        print STDERR "Following parent with do_switch\n";
                        # do_switch works with svn/trunk >= r22312, but that
                        # is not included with SVN 1.4.3 (the latest version
@@ -1809,6 +1851,8 @@ sub make_log_entry {
                $full_url =~ s#^\Q$svm->{replace}\E(/|$)#$svm->{source}$1# or
                             die "Failed to replace '$svm->{replace}' with ",
                                 "'$svm->{source}' in $full_url\n";
+               # throw away username for storing in records
+               remove_username($full_url);
                $log_entry{metadata} = "$full_url\@$r $uuid";
                $log_entry{svm_revision} = $r;
                $email ||= "$author\@$uuid"
@@ -1877,12 +1921,14 @@ sub rebuild {
        my ($rev_list, $ctx) = command_output_pipe("rev-list", $self->refname);
        my $latest;
        my $full_url = $self->full_url;
+       remove_username($full_url);
        my $svn_uuid;
        while (<$rev_list>) {
                chomp;
                my $c = $_;
                die "Non-SHA1: $c\n" unless $c =~ /^$::sha1$/o;
                my ($url, $rev, $uuid) = ::cmt_metadata($c);
+               remove_username($url);
 
                # ignore merges (from set-tree)
                next if (!defined $rev || !$uuid);
@@ -2056,6 +2102,10 @@ sub uri_encode {
        $f
 }
 
+sub remove_username {
+       $_[0] =~ s{^([^:]*://)[^@]+@}{$1};
+}
+
 package Git::SVN::Prompt;
 use strict;
 use warnings;
@@ -2793,8 +2843,7 @@ package Git::SVN::Ra;
 use vars qw/@ISA $config_dir $_log_window_size/;
 use strict;
 use warnings;
-my ($can_do_switch);
-my $RA;
+my ($can_do_switch, %ignored_err, $RA);
 
 BEGIN {
        # enforce temporary pool usage for some simple functions
@@ -2837,6 +2886,7 @@ sub new {
        my ($class, $url) = @_;
        $url =~ s!/+$!!;
        return $RA if ($RA && $RA->{url} eq $url);
+       $RA->{pool}->clear if $RA;
 
        SVN::_Core::svn_config_ensure($config_dir, undef);
        my ($baton, $callbacks) = SVN::Core::auth_open_helper([
@@ -2889,6 +2939,10 @@ sub gs_do_update {
        my $new = ($rev_a == $rev_b);
        my $path = $gs->{path};
 
+       if ($new && -e $gs->{index}) {
+               unlink $gs->{index} or die
+                 "Couldn't unlink index: $gs->{index}: $!\n";
+       }
        my $pool = SVN::Pool->new;
        $editor->set_path_strip($path);
        my (@pc) = split m#/#, $path;
@@ -3161,9 +3215,16 @@ sub skip_unknown_revs {
        # 175007 - http(s):// (this repo required authorization, too...)
        #   More codes may be discovered later...
        if ($errno == 175007 || $errno == 175002 || $errno == 160013) {
-               warn "W: Ignoring error from SVN, path probably ",
-                    "does not exist: ($errno): ",
-                    $err->expanded_message,"\n";
+               my $err_key = $err->expanded_message;
+               # revision numbers change every time, filter them out
+               $err_key =~ s/\d+/\0/g;
+               $err_key = "$errno\0$err_key";
+               unless ($ignored_err{$err_key}) {
+                       warn "W: Ignoring error from SVN, path probably ",
+                            "does not exist: ($errno): ",
+                            $err->expanded_message,"\n";
+                       $ignored_err{$err_key} = 1;
+               }
                return;
        }
        die "Error from SVN, ($errno): ", $err->expanded_message,"\n";