@ -56,9 +56,7 @@ import java.io.IOException;
import java.io.InputStream ;
import java.io.InputStream ;
import java.nio.ByteBuffer ;
import java.nio.ByteBuffer ;
import java.nio.channels.Channels ;
import java.nio.channels.Channels ;
import java.security.MessageDigest ;
import java.text.MessageFormat ;
import java.text.MessageFormat ;
import java.util.Arrays ;
import java.util.Set ;
import java.util.Set ;
import java.util.zip.CRC32 ;
import java.util.zip.CRC32 ;
import java.util.zip.DataFormatException ;
import java.util.zip.DataFormatException ;
@ -466,55 +464,35 @@ public final class DfsPackFile {
return dstbuf ;
return dstbuf ;
}
}
void copyPackAsIs ( PackOutputStream out , boolean validate , DfsReader ctx )
void copyPackAsIs ( PackOutputStream out , DfsReader ctx )
throws IOException {
throws IOException {
MessageDigest md = initCopyPack ( out , validate , ctx ) ;
long p ;
if ( cache . shouldCopyThroughCache ( length ) )
p = copyPackThroughCache ( out , ctx , md ) ;
else
p = copyPackBypassCache ( out , ctx , md ) ;
verifyPackChecksum ( p , md , ctx ) ;
}
private MessageDigest initCopyPack ( PackOutputStream out , boolean validate ,
DfsReader ctx ) throws IOException {
// If the length hasn't been determined yet, pin to set it.
// If the length hasn't been determined yet, pin to set it.
if ( length = = - 1 )
if ( length = = - 1 ) {
ctx . pin ( this , 0 ) ;
ctx . pin ( this , 0 ) ;
if ( ! validate ) {
ctx . unpin ( ) ;
ctx . unpin ( ) ;
return null ;
}
}
if ( cache . shouldCopyThroughCache ( length ) )
int hdrlen = 12 ;
copyPackThroughCache ( out , ctx ) ;
byte [ ] buf = out . getCopyBuffer ( ) ;
else
int n = ctx . copy ( this , 0 , buf , 0 , hdrlen ) ;
copyPackBypassCache ( out , ctx ) ;
ctx . unpin ( ) ;
if ( n ! = hdrlen )
throw packfileIsTruncated ( ) ;
MessageDigest md = Constants . newMessageDigest ( ) ;
md . update ( buf , 0 , hdrlen ) ;
return md ;
}
}
private long copyPackThroughCache ( PackOutputStream out , DfsReader ctx ,
private void copyPackThroughCache ( PackOutputStream out , DfsReader ctx )
MessageDigest md ) throws IOException {
throws IOException {
long position = 12 ;
long position = 12 ;
long remaining = length - ( 12 + 20 ) ;
long remaining = length - ( 12 + 20 ) ;
while ( 0 < remaining ) {
while ( 0 < remaining ) {
DfsBlock b = cache . getOrLoad ( this , position , ctx ) ;
DfsBlock b = cache . getOrLoad ( this , position , ctx ) ;
int ptr = ( int ) ( position - b . start ) ;
int ptr = ( int ) ( position - b . start ) ;
int n = ( int ) Math . min ( b . size ( ) - ptr , remaining ) ;
int n = ( int ) Math . min ( b . size ( ) - ptr , remaining ) ;
b . write ( out , position , n , md ) ;
b . write ( out , position , n ) ;
position + = n ;
position + = n ;
remaining - = n ;
remaining - = n ;
}
}
return position ;
}
}
private long copyPackBypassCache ( PackOutputStream out , DfsReader ctx ,
private long copyPackBypassCache ( PackOutputStream out , DfsReader ctx )
MessageDigest md ) throws IOException {
throws IOException {
try ( ReadableChannel rc = ctx . db . openFile ( packDesc , PACK ) ) {
try ( ReadableChannel rc = ctx . db . openFile ( packDesc , PACK ) ) {
ByteBuffer buf = newCopyBuffer ( out , rc ) ;
ByteBuffer buf = newCopyBuffer ( out , rc ) ;
if ( ctx . getOptions ( ) . getStreamPackBufferSize ( ) > 0 )
if ( ctx . getOptions ( ) . getStreamPackBufferSize ( ) > 0 )
@ -526,7 +504,7 @@ public final class DfsPackFile {
if ( b ! = null ) {
if ( b ! = null ) {
int ptr = ( int ) ( position - b . start ) ;
int ptr = ( int ) ( position - b . start ) ;
int n = ( int ) Math . min ( b . size ( ) - ptr , remaining ) ;
int n = ( int ) Math . min ( b . size ( ) - ptr , remaining ) ;
b . write ( out , position , n , md ) ;
b . write ( out , position , n ) ;
position + = n ;
position + = n ;
remaining - = n ;
remaining - = n ;
rc . position ( position ) ;
rc . position ( position ) ;
@ -540,8 +518,6 @@ public final class DfsPackFile {
else if ( n > remaining )
else if ( n > remaining )
n = ( int ) remaining ;
n = ( int ) remaining ;
out . write ( buf . array ( ) , 0 , n ) ;
out . write ( buf . array ( ) , 0 , n ) ;
if ( md ! = null )
md . update ( buf . array ( ) , 0 , n ) ;
position + = n ;
position + = n ;
remaining - = n ;
remaining - = n ;
}
}
@ -557,22 +533,6 @@ public final class DfsPackFile {
return ByteBuffer . wrap ( copyBuf , 0 , bs ) ;
return ByteBuffer . wrap ( copyBuf , 0 , bs ) ;
}
}
private void verifyPackChecksum ( long position , MessageDigest md ,
DfsReader ctx ) throws IOException {
if ( md ! = null ) {
byte [ ] buf = new byte [ 20 ] ;
byte [ ] actHash = md . digest ( ) ;
if ( ctx . copy ( this , position , buf , 0 , 20 ) ! = 20 )
throw packfileIsTruncated ( ) ;
if ( ! Arrays . equals ( actHash , buf ) ) {
invalid = true ;
throw new IOException ( MessageFormat . format (
JGitText . get ( ) . packfileCorruptionDetected ,
getPackName ( ) ) ) ;
}
}
}
void copyAsIs ( PackOutputStream out , DfsObjectToPack src ,
void copyAsIs ( PackOutputStream out , DfsObjectToPack src ,
boolean validate , DfsReader ctx ) throws IOException ,
boolean validate , DfsReader ctx ) throws IOException ,
StoredObjectRepresentationNotAvailableException {
StoredObjectRepresentationNotAvailableException {
@ -719,7 +679,7 @@ public final class DfsPackFile {
// and we have it pinned. Write this out without copying.
// and we have it pinned. Write this out without copying.
//
//
out . writeHeader ( src , inflatedLength ) ;
out . writeHeader ( src , inflatedLength ) ;
quickCopy . write ( out , dataOffset , ( int ) dataLength , null ) ;
quickCopy . write ( out , dataOffset , ( int ) dataLength ) ;
} else if ( dataLength < = buf . length ) {
} else if ( dataLength < = buf . length ) {
// Tiny optimization: Lots of objects are very small deltas or
// Tiny optimization: Lots of objects are very small deltas or