git-cvsimport-script: typo head -> heads
[git.git] / git-cvsimport-script
index 9b23d1f..f05fe10 100755 (executable)
@@ -26,34 +26,53 @@ use POSIX qw(strftime dup2);
 $SIG{'PIPE'}="IGNORE";
 $ENV{'TZ'}="UTC";
 
-our($opt_h,$opt_o,$opt_v,$opt_d);
+our($opt_h,$opt_o,$opt_v,$opt_d,$opt_p,$opt_C);
 
 sub usage() {
        print STDERR <<END;
 Usage: ${\basename $0}     # fetch/update GIT from CVS
           [ -o branch-for-HEAD ] [ -h ] [ -v ] [ -d CVSROOT ]
-       CVS_module [ GIT_repository ]
+       [ -p opts-for-cvsps ] [ -C GIT_repository ]
+       [ CVS_module ]
 END
        exit(1);
 }
 
-getopts("hqvo:d:") or usage();
+getopts("hqvo:d:p:C:") or usage();
 usage if $opt_h;
 
-@ARGV == 1 or @ARGV == 2 or usage();
-
-my($cvs_tree, $git_tree) = @ARGV;
+@ARGV <= 1 or usage();
 
 if($opt_d) {
        $ENV{"CVSROOT"} = $opt_d;
+} elsif(-f 'CVS/Root') {
+       open my $f, '<', 'CVS/Root' or die 'Failed to open CVS/Root';
+       $opt_d = <$f>;
+       chomp $opt_d;
+       close $f;
+       $ENV{"CVSROOT"} = $opt_d;
 } elsif($ENV{"CVSROOT"}) {
        $opt_d = $ENV{"CVSROOT"};
 } else {
        die "CVSROOT needs to be set";
 }
 $opt_o ||= "origin";
+my $git_tree = $opt_C;
 $git_tree ||= ".";
 
+my $cvs_tree;
+if ($#ARGV == 0) {
+       $cvs_tree = $ARGV[0];
+} elsif (-f 'CVS/Repository') {
+       open my $f, '<', 'CVS/Repository' or 
+           die 'Failed to open CVS/Repository';
+       $cvs_tree = <$f>;
+       chomp $cvs_tree;
+       close $f
+} else {
+       usage();
+}
+
 select(STDERR); $|=1; select(STDOUT);
 
 
@@ -124,11 +143,32 @@ sub conn {
                }
                $self->{'socketo'} = $s;
                $self->{'socketi'} = $s;
-       } else { # local: Fork off our own cvs server.
+       } else { # local or ext: Fork off our own cvs server.
                my $pr = IO::Pipe->new();
                my $pw = IO::Pipe->new();
                my $pid = fork();
                die "Fork: $!\n" unless defined $pid;
+               my $cvs = 'cvs';
+               $cvs = $ENV{CVS_SERVER} if exists $ENV{CVS_SERVER};
+               my $rsh = 'rsh';
+               $rsh = $ENV{CVS_RSH} if exists $ENV{CVS_RSH};
+
+               my @cvs = ($cvs, 'server');
+               my ($local, $user, $host);
+               $local = $repo =~ s/:local://;
+               if (!$local) {
+                   $repo =~ s/:ext://;
+                   $local = !($repo =~ s/^(?:([^\@:]+)\@)?([^:]+)://);
+                   ($user, $host) = ($1, $2);
+               }
+               if (!$local) {
+                   if ($user) {
+                       unshift @cvs, $rsh, '-l', $user, $host;
+                   } else {
+                       unshift @cvs, $rsh, $host;
+                   }
+               }
+
                unless($pid) {
                        $pr->writer();
                        $pw->reader();
@@ -136,7 +176,7 @@ sub conn {
                        dup2($pr->fileno(),1);
                        $pr->close();
                        $pw->close();
-                       exec("cvs","server");
+                       exec(@cvs);
                }
                $pw->writer();
                $pr->reader();
@@ -338,6 +378,11 @@ unless(-d $git_dir) {
        $last_branch = $opt_o;
        $orig_branch = "";
 } else {
+       -f "$git_dir/refs/heads/$opt_o"
+               or die "Branch '$opt_o' does not exist.\n".
+                      "Either use the correct '-o branch' option,\n".
+                      "or import to a new repository.\n";
+
        $last_branch = basename(readlink("$git_dir/HEAD"));
        unless($last_branch) {
                warn "Cannot read the last branch name: $! -- assuming 'master'\n";
@@ -370,7 +415,9 @@ unless(-d $git_dir) {
 my $pid = open(CVS,"-|");
 die "Cannot fork: $!\n" unless defined $pid;
 unless($pid) {
-       exec("cvsps","-A","--cvs-direct",$cvs_tree);
+       my @opt;
+       @opt = split(/,/,$opt_p) if defined $opt_p;
+       exec("cvsps",@opt,"-x","-A","--cvs-direct",'--root',$opt_d,$cvs_tree);
        die "Could not start cvsps: $!\n";
 }
 
@@ -468,7 +515,12 @@ my $commit = sub {
        }
        $pw->writer();
        $pr->reader();
-       print $pw $logmsg
+
+       # compatibility with git2cvs
+       substr($logmsg,32767) = "" if length($logmsg) > 32767;
+       $logmsg =~ s/[\s\n]+\z//;
+
+       print $pw "$logmsg\n"
                or die "Error writing to git-commit-tree: $!\n";
        $pw->close();
 
@@ -498,9 +550,6 @@ my $commit = sub {
                        or die "Cannot write tag $branch: $!\n";
                print "Created tag '$tag' on '$branch'\n" if $opt_v;
        }
-
-       @old = ();
-       @new = ();
 };
 
 while(<CVS>) {
@@ -532,7 +581,7 @@ while(<CVS>) {
        } elsif($state == 5 and s/^Ancestor branch:\s+//) {
                s/\s+$//;
                $ancestor = $_;
-               $ancestor = $opt_o if $ancestor == "HEAD";
+               $ancestor = $opt_o if $ancestor eq "HEAD";
                $state = 6;
        } elsif($state == 5) {
                $ancestor = undef;
@@ -553,7 +602,7 @@ while(<CVS>) {
                $branch = $opt_o if $branch eq "HEAD";
                if(defined $branch_date{$branch} and $branch_date{$branch} >= $date) {
                        # skip
-                       print "skip patchset $patchset: $date before $branch_date{$branch}\n";
+                       print "skip patchset $patchset: $date before $branch_date{$branch}\n" if $opt_v;
                        $state = 11;
                        next;
                }
@@ -600,7 +649,7 @@ while(<CVS>) {
                my $rev = $3;
                $fn =~ s#^/+##;
                my $data = $cvs->file($fn,$rev);
-               print "".($init ? "New" : "Update")." $fn: ".length($data)." bytes.\n";
+               print "".($init ? "New" : "Update")." $fn: ".length($data)." bytes.\n" if $opt_v;
                mkpath(dirname($fn),$opt_v);
                open(F,"> ./$fn")
                        or die "Cannot create '$fn': $!\n";