combine-diff: better hunk splitting.
[gitweb.git] / git-svnimport.perl
index e97f47059fda6cf058e43f2b77ff784ed2b5ee13..6e3a44a2bc9fbf170db45a7e390d6ac8ffbb6f02 100755 (executable)
@@ -25,7 +25,7 @@
 use SVN::Core;
 use SVN::Ra;
 
-die "Need CVN:Core 1.2.1 or better" if $SVN::Core::VERSION lt "1.2.1";
+die "Need SVN:Core 1.2.1 or better" if $SVN::Core::VERSION lt "1.2.1";
 
 $SIG{'PIPE'}="IGNORE";
 $ENV{'TZ'}="UTC";
@@ -34,8 +34,8 @@
 
 sub usage() {
        print STDERR <<END;
-Usage: ${\basename $0}     # fetch/update GIT from CVS
-       [-o branch-for-HEAD] [-h] [-v] [-l max_num_changes]
+Usage: ${\basename $0}     # fetch/update GIT from SVN
+       [-o branch-for-HEAD] [-h] [-v] [-l max_rev]
        [-C GIT_repository] [-t tagname] [-T trunkname] [-b branchname]
        [-d|-D] [-i] [-u] [-s start_chg] [-m] [-M regex] [SVN_URL]
 END
@@ -53,7 +53,6 @@ END
 
 $opt_o ||= "origin";
 $opt_s ||= 1;
-$opt_l = 100 unless defined $opt_l;
 my $git_tree = $opt_C;
 $git_tree ||= ".";
 
@@ -97,8 +96,10 @@ sub new {
 sub conn {
        my $self = shift;
        my $repo = $self->{'fullrep'};
-       my $s = SVN::Ra->new($repo);
-
+       my $auth = SVN::Core::auth_open ([SVN::Client::get_simple_provider,
+                         SVN::Client::get_ssl_server_trust_file_provider,
+                         SVN::Client::get_username_provider]);
+       my $s = SVN::Ra->new(url => $repo, auth => $auth);
        die "SVN connection to $repo: $!\n" unless defined $s;
        $self->{'svn'} = $s;
        $self->{'repo'} = $repo;
@@ -127,8 +128,9 @@ sub file {
 package main;
 use URI;
 
-my $svn = $svn_url;
+our $svn = $svn_url;
 $svn .= "/$svn_dir" if defined $svn_dir;
+my $svn2 = SVNconn->new($svn);
 $svn = SVNconn->new($svn);
 
 my $lwp_ua;
@@ -199,7 +201,7 @@ ($$)
 my $maxnum = 0;
 my $last_rev = "";
 my $last_branch;
-my $current_rev = $opt_s-1;
+my $current_rev = $opt_s || 1;
 unless(-d $git_dir) {
        system("git-init-db");
        die "Cannot init the GIT db at $git_tree: $?\n" if $?;
@@ -217,7 +219,11 @@ ($$)
        -f "$git_dir/svn2git"
                or die "'$git_dir/svn2git' does not exist.\n".
                       "You need that file for incremental imports.\n";
-       $last_branch = basename(readlink("$git_dir/HEAD"));
+       open(F, "git-symbolic-ref HEAD |") or
+               die "Cannot run git-symbolic-ref: $!\n";
+       chomp ($last_branch = <F>);
+       $last_branch = basename($last_branch);
+       close(F);
        unless($last_branch) {
                warn "Cannot read the last branch name: $! -- assuming 'master'\n";
                $last_branch = "master";
@@ -251,7 +257,7 @@ ($$)
                my($num,$branch,$ref) = split;
                $branches{$branch}{$num} = $ref;
                $branches{$branch}{"LAST"} = $ref;
-               $current_rev = $num if $current_rev < $num;
+               $current_rev = $num+1 if $current_rev <= $num;
        }
        close($B);
 }
@@ -281,7 +287,8 @@ ($$)
                $svnpath = "$branch_name/$branch/$path";
        }
 
-       return $svnpath
+       $svnpath =~ s#/+$##;
+       return $svnpath;
 }
 
 sub get_file($$$) {
@@ -373,6 +380,10 @@ ($$$$$$$$)
        my($newrev,$newbranch,$path,$oldpath,$rev,$node_kind,$new,$parents) = @_;
 
        my($srcbranch,$srcpath) = split_path($rev,$oldpath);
+       unless(defined $srcbranch) {
+               print "Path not found when copying from $oldpath @ $rev\n";
+               return;
+       }
        my $therev = branch_rev($srcbranch, $rev);
        my $gitrev = $branches{$srcbranch}{$therev};
        unless($gitrev) {
@@ -700,17 +711,17 @@ sub commit {
        print "DONE: $revision $dest $cid\n" if $opt_v;
 }
 
-my ($changed_paths, $revision, $author, $date, $message, $pool) = @_;
-sub _commit_all {
-       ($changed_paths, $revision, $author, $date, $message, $pool) = @_;
+sub commit_all {
+       # Recursive use of the SVN connection does not work
+       local $svn = $svn2;
+
+       my ($changed_paths, $revision, $author, $date, $message, $pool) = @_;
        my %p;
        while(my($path,$action) = each %$changed_paths) {
                $p{$path} = [ $action->action,$action->copyfrom_path, $action->copyfrom_rev, $path ];
        }
        $changed_paths = \%p;
-}
 
-sub commit_all {
        my %done;
        my @col;
        my $pref;
@@ -726,18 +737,20 @@ sub commit_all {
        }
 }
 
-while(++$current_rev <= $svn->{'maxrev'}) {
-       my $pool=SVN::Pool->new;
-       $svn->{'svn'}->get_log("/",$current_rev,$current_rev,1,1,1,\&_commit_all,$pool);
-       $pool->clear;
-       commit_all();
-       if($opt_l and not --$opt_l) {
-               print STDERR "Stopping, because there is a memory leak (in the SVN library).\n";
-               print STDERR "Please repeat this command; it will continue safely\n";
-               last;
-       }
+$opt_l = $svn->{'maxrev'} if not defined $opt_l or $opt_l > $svn->{'maxrev'};
+
+if ($svn->{'maxrev'} < $current_rev) {
+    print "Up to date: no new revisions to fetch!\n" if $opt_v;
+    unlink("$git_dir/SVN2GIT_HEAD");
+    exit;
 }
 
+print "Fetching from $current_rev to $opt_l ...\n" if $opt_v;
+
+my $pool=SVN::Pool->new;
+$svn->{'svn'}->get_log("/",$current_rev,$opt_l,0,1,1,\&commit_all,$pool);
+$pool->clear;
+
 
 unlink($git_index);
 
@@ -761,8 +774,7 @@ sub commit_all {
        print "DONE; creating $orig_branch branch\n" if $opt_v and (not defined $opt_l or $opt_l > 0);
        system("cp","$git_dir/refs/heads/$opt_o","$git_dir/refs/heads/master")
                unless -f "$git_dir/refs/heads/master";
-       unlink("$git_dir/HEAD");
-       symlink("refs/heads/$orig_branch","$git_dir/HEAD");
+       system('git-update-ref', 'HEAD', "$orig_branch");
        unless ($opt_i) {
                system('git checkout');
                die "checkout failed: $?\n" if $?;