@matheusbsbs / matheus-bagliano / commits / e78f69a3f2
Fork 0

cvsserver: Implement update -p (print to stdout)

Cvs update -p -r <rev> <path> is the documented way to retrieve a specific revision of a file (similar to git show <rev>:<path>). Without this patch, the -p flag is ignored and status output is produced, causing clients to interpret it as the contents of the file. TkCVS uses update -p as a basis for implementing its various "View" and "Diff" commands. Signed-off-by: Damien Diederen <dash@foobox.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Damien Diederen committed Mar 27, 2008 at 23:18 UTC e78f69a3f2e580e71a44b91fa99185bc6f92db29
1 file changed +35 -12
git-cvsserver.perl
+35 -12
@@ -963,6 +963,17 @@ sub req_update
963 $meta = $updater->getmeta($filename);
964 }
965
966 + # If -p was given, "print" the contents of the requested revision.
967 + if ( exists ( $state->{opt}{p} ) ) {
968 + if ( defined ( $meta->{revision} ) ) {
969 + $log->info("Printing '$filename' revision " . $meta->{revision});
970 +
971 + transmitfile($meta->{filehash}, { print => 1 });
972 + }
973 +
974 + next;
975 + }
976 +
977 if ( ! defined $meta )
978 {
979 $meta = {
@@ -1096,9 +1107,9 @@ sub req_update
1107 my $file_local = $filepart . ".mine";
1108 system("ln","-s",$state->{entries}{$filename}{modified_filename}, $file_local);
1109 my $file_old = $filepart . "." . $oldmeta->{revision};
1099 - transmitfile($oldmeta->{filehash}, $file_old);
1110 + transmitfile($oldmeta->{filehash}, { targetfile => $file_old });
1111 my $file_new = $filepart . "." . $meta->{revision};
1101 - transmitfile($meta->{filehash}, $file_new);
1112 + transmitfile($meta->{filehash}, { targetfile => $file_new });
1113
1114 # we need to merge with the local changes ( M=successful merge, C=conflict merge )
1115 $log->info("Merging $file_local, $file_old, $file_new");
@@ -1550,14 +1561,14 @@ sub req_diff
1561 print "E File $filename at revision 1.$revision1 doesn't exist\n";
1562 next;
1563 }
1553 - transmitfile($meta1->{filehash}, $file1);
1564 + transmitfile($meta1->{filehash}, { targetfile => $file1 });
1565 }
1566 # otherwise we just use the working copy revision
1567 else
1568 {
1569 ( undef, $file1 ) = tempfile( DIR => $TEMP_DIR, OPEN => 0 );
1570 $meta1 = $updater->getmeta($filename, $wrev);
1560 - transmitfile($meta1->{filehash}, $file1);
1571 + transmitfile($meta1->{filehash}, { targetfile => $file1 });
1572 }
1573
1574 # if we have a second -r switch, use it too
@@ -1572,7 +1583,7 @@ sub req_diff
1583 next;
1584 }
1585
1575 - transmitfile($meta2->{filehash}, $file2);
1586 + transmitfile($meta2->{filehash}, { targetfile => $file2 });
1587 }
1588 # otherwise we just use the working copy
1589 else
@@ -1585,7 +1596,7 @@ sub req_diff
1596 {
1597 ( undef, $file2 ) = tempfile( DIR => $TEMP_DIR, OPEN => 0 );
1598 $meta2 = $updater->getmeta($filename, $wrev);
1588 - transmitfile($meta2->{filehash}, $file2);
1599 + transmitfile($meta2->{filehash}, { targetfile => $file2 });
1600 }
1601
1602 # We need to have retrieved something useful
@@ -2014,14 +2025,17 @@ sub revparse
2025 return undef;
2026 }
2027
2017 -# This method takes a file hash and does a CVS "file transfer" which transmits the
2018 -# size of the file, and then the file contents.
2019 -# If a second argument $targetfile is given, the file is instead written out to
2020 -# a file by the name of $targetfile
2028 +# This method takes a file hash and does a CVS "file transfer". Its
2029 +# exact behaviour depends on a second, optional hash table argument:
2030 +# - If $options->{targetfile}, dump the contents to that file;
2031 +# - If $options->{print}, use M/MT to transmit the contents one line
2032 +# at a time;
2033 +# - Otherwise, transmit the size of the file, followed by the file
2034 +# contents.
2035 sub transmitfile
2036 {
2037 my $filehash = shift;
2024 - my $targetfile = shift;
2038 + my $options = shift;
2039
2040 if ( defined ( $filehash ) and $filehash eq "deleted" )
2041 {
@@ -2043,11 +2057,20 @@ sub transmitfile
2057
2058 if ( open my $fh, '-|', "git-cat-file", "blob", $filehash )
2059 {
2046 - if ( defined ( $targetfile ) )
2060 + if ( defined ( $options->{targetfile} ) )
2061 {
2062 + my $targetfile = $options->{targetfile};
2063 open NEWFILE, ">", $targetfile or die("Couldn't open '$targetfile' for writing : $!");
2064 print NEWFILE $_ while ( <$fh> );
2065 close NEWFILE or die("Failed to write '$targetfile': $!");
2066 + } elsif ( defined ( $options->{print} ) && $options->{print} ) {
2067 + while ( <$fh> ) {
2068 + if( /\n\z/ ) {
2069 + print 'M ', $_;
2070 + } else {
2071 + print 'MT text ', $_, "\n";
2072 + }
2073 + }
2074 } else {
2075 print "$size\n";
2076 print while ( <$fh> );