annotate: Support annotation of files on other revisions.
[gitweb.git] / git-cvsimport.perl
index 8d493c2a4fb057aa650cc34858253838d408660e..b46469ab32fa5707c8056c5a32db61d7c268e50b 100755 (executable)
@@ -29,7 +29,7 @@
 $SIG{'PIPE'}="IGNORE";
 $ENV{'TZ'}="UTC";
 
-our($opt_h,$opt_o,$opt_v,$opt_k,$opt_u,$opt_d,$opt_p,$opt_C,$opt_z,$opt_i,$opt_P, $opt_s,$opt_m,$opt_M,$opt_A);
+our($opt_h,$opt_o,$opt_v,$opt_k,$opt_u,$opt_d,$opt_p,$opt_C,$opt_z,$opt_i,$opt_P, $opt_s,$opt_m,$opt_M,$opt_A,$opt_S);
 my (%conv_author_name, %conv_author_email);
 
 sub usage() {
@@ -37,7 +37,7 @@ ()
 Usage: ${\basename $0}     # fetch/update GIT from CVS
        [-o branch-for-HEAD] [-h] [-v] [-d CVSROOT] [-A author-conv-file]
        [-p opts-for-cvsps] [-C GIT_repository] [-z fuzz] [-i] [-k] [-u]
-       [-s subst] [-m] [-M regex] [CVS_module]
+       [-s subst] [-m] [-M regex] [-S regex] [CVS_module]
 END
        exit(1);
 }
@@ -48,16 +48,28 @@ ($)
        open my $f, '<', "$file" or die("Failed to open $file: $!\n");
 
        while (<$f>) {
-               chomp;
-               # Expected format is this;
+               # Expected format is this:
                #   exon=Andreas Ericsson <ae@op5.se>
-               if (m/^([^ \t=]*)[ \t=]*([^<]*)(<.*$)\s*/) {
+               if (m/^(\S+?)\s*=\s*(.+?)\s*<(.+)>\s*$/) {
                        $user = $1;
-                       $conv_author_name{$1} = $2;
-                       $conv_author_email{$1} = $3;
-                       # strip trailing whitespace from author name
-                       $conv_author_name{$1} =~ s/\s*$//;
+                       $conv_author_name{$user} = $2;
+                       $conv_author_email{$user} = $3;
                }
+               # However, we also read from CVSROOT/users format
+               # to ease migration.
+               elsif (/^(\w+):(['"]?)(.+?)\2\s*$/) {
+                       my $mapped;
+                       ($user, $mapped) = ($1, $3);
+                       if ($mapped =~ /^\s*(.*?)\s*<(.*)>\s*$/) {
+                               $conv_author_name{$user} = $1;
+                               $conv_author_email{$user} = $2;
+                       }
+                       elsif ($mapped =~ /^<?(.*)>?$/) {
+                               $conv_author_name{$user} = $user;
+                               $conv_author_email{$user} = $1;
+                       }
+               }
+               # NEEDSWORK: Maybe warn on unrecognized lines?
        }
        close ($f);
 }
@@ -68,13 +80,12 @@ ($)
          die("Failed to open $file for writing: $!");
 
        foreach (keys %conv_author_name) {
-               print $f "$_=" . $conv_author_name{$_} .
-                 " " . $conv_author_email{$_} . "\n";
+               print $f "$_=$conv_author_name{$_} <$conv_author_email{$_}>\n";
        }
        close ($f);
 }
 
-getopts("hivmkuo:d:p:C:z:s:M:P:A:") or usage();
+getopts("hivmkuo:d:p:C:z:s:M:P:A:S:") or usage();
 usage if $opt_h;
 
 @ARGV <= 1 or usage();
@@ -350,6 +361,7 @@ sub _line {
                        }
                }
        }
+       return undef;
 }
 sub file {
        my($self,$fn,$rev) = @_;
@@ -361,19 +373,15 @@ sub file {
        $self->_file($fn,$rev) and $res = $self->_line($fh);
 
        if (!defined $res) {
-           # retry
+           print STDERR "Server has gone away while fetching $fn $rev, retrying...\n";
+           truncate $fh, 0;
            $self->conn();
-           $self->_file($fn,$rev)
-                   or die "No file command send\n";
+           $self->_file($fn,$rev) or die "No file command send";
            $res = $self->_line($fh);
-           die "No input: $fn $rev\n" unless defined $res;
+           die "Retry failed" unless defined $res;
        }
        close ($fh);
 
-       if ($res eq '') {
-           die "Looks like the server has gone away while fetching $fn $rev -- exiting!";
-       }
-
        return ($name, $res);
 }
 
@@ -568,7 +576,7 @@ ($$)
 my $state = 0;
 
 my($patchset,$date,$author_name,$author_email,$branch,$ancestor,$tag,$logmsg);
-my(@old,@new);
+my(@old,@new,@skipped);
 my $commit = sub {
        my $pid;
        while(@old) {
@@ -664,6 +672,11 @@ ($$)
        substr($logmsg,32767) = "" if length($logmsg) > 32767;
        $logmsg =~ s/[\s\n]+\z//;
 
+       if (@skipped) {
+           $logmsg .= "\n\n\nSKIPPED:\n\t";
+           $logmsg .= join("\n\t", @skipped) . "\n";
+       }
+
        print $pw "$logmsg\n"
                or die "Error writing to git-commit-tree: $!\n";
        $pw->close();
@@ -821,14 +834,24 @@ ($$)
                my $fn = $1;
                my $rev = $3;
                $fn =~ s#^/+##;
+               if ($opt_S && $fn =~ m/$opt_S/) {
+                   print "SKIPPING $fn v $rev\n";
+                   push(@skipped, $fn);
+                   next;
+               }
+               print "Fetching $fn   v $rev\n" if $opt_v;
                my ($tmpname, $size) = $cvs->file($fn,$rev);
                if($size == -1) {
                        push(@old,$fn);
                        print "Drop $fn\n" if $opt_v;
                } else {
                        print "".($init ? "New" : "Update")." $fn: $size bytes\n" if $opt_v;
-                       open my $F, '-|', "git-hash-object -w $tmpname"
+                       my $pid = open(my $F, '-|');
+                       die $! unless defined $pid;
+                       if (!$pid) {
+                           exec("git-hash-object", "-w", $tmpname)
                                or die "Cannot create object: $!\n";
+                       }
                        my $sha = <$F>;
                        chomp $sha;
                        close $F;