@ -44,6 +44,13 @@
package org.eclipse.jgit.treewalk ;
package org.eclipse.jgit.treewalk ;
import static org.eclipse.jgit.lib.Constants.DOT_GIT_ATTRIBUTES ;
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH ;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB ;
import static org.eclipse.jgit.lib.Constants.OBJ_TREE ;
import static org.eclipse.jgit.lib.Constants.TYPE_TREE ;
import static org.eclipse.jgit.lib.Constants.encode ;
import java.io.IOException ;
import java.io.IOException ;
import java.io.InputStream ;
import java.io.InputStream ;
import java.util.Arrays ;
import java.util.Arrays ;
@ -54,20 +61,15 @@ import org.eclipse.jgit.attributes.AttributesRule;
import org.eclipse.jgit.errors.IncorrectObjectTypeException ;
import org.eclipse.jgit.errors.IncorrectObjectTypeException ;
import org.eclipse.jgit.errors.MissingObjectException ;
import org.eclipse.jgit.errors.MissingObjectException ;
import org.eclipse.jgit.lib.AnyObjectId ;
import org.eclipse.jgit.lib.AnyObjectId ;
import org.eclipse.jgit.lib.Constants ;
import org.eclipse.jgit.lib.FileMode ;
import org.eclipse.jgit.lib.FileMode ;
import org.eclipse.jgit.lib.MutableObjectId ;
import org.eclipse.jgit.lib.MutableObjectId ;
import org.eclipse.jgit.lib.ObjectId ;
import org.eclipse.jgit.lib.ObjectId ;
import org.eclipse.jgit.lib.ObjectLoader ;
import org.eclipse.jgit.lib.ObjectReader ;
import org.eclipse.jgit.lib.ObjectReader ;
import org.eclipse.jgit.util.RawParseUtils ;
/** Parses raw Git trees from the canonical semi-text/semi-binary format. */
/** Parses raw Git trees from the canonical semi-text/semi-binary format. */
public class CanonicalTreeParser extends AbstractTreeIterator {
public class CanonicalTreeParser extends AbstractTreeIterator {
private static final byte [ ] EMPTY = { } ;
private static final byte [ ] EMPTY = { } ;
private static final byte [ ] ATTRS = encode ( DOT_GIT_ATTRIBUTES ) ;
private static final byte [ ] ATTRS = Constants
. encode ( Constants . DOT_GIT_ATTRIBUTES ) ;
private byte [ ] raw ;
private byte [ ] raw ;
@ -133,6 +135,7 @@ public class CanonicalTreeParser extends AbstractTreeIterator {
* the raw tree content .
* the raw tree content .
* /
* /
public void reset ( final byte [ ] treeData ) {
public void reset ( final byte [ ] treeData ) {
attributesNode = null ;
raw = treeData ;
raw = treeData ;
prevPtr = - 1 ;
prevPtr = - 1 ;
currPtr = 0 ;
currPtr = 0 ;
@ -208,7 +211,7 @@ public class CanonicalTreeParser extends AbstractTreeIterator {
* /
* /
public void reset ( final ObjectReader reader , final AnyObjectId id )
public void reset ( final ObjectReader reader , final AnyObjectId id )
throws IncorrectObjectTypeException , IOException {
throws IncorrectObjectTypeException , IOException {
reset ( reader . open ( id , Constants . OBJ_TREE ) . getCachedBytes ( ) ) ;
reset ( reader . open ( id , OBJ_TREE ) . getCachedBytes ( ) ) ;
}
}
@Override
@Override
@ -218,7 +221,7 @@ public class CanonicalTreeParser extends AbstractTreeIterator {
idBuffer . fromRaw ( idBuffer ( ) , idOffset ( ) ) ;
idBuffer . fromRaw ( idBuffer ( ) , idOffset ( ) ) ;
if ( ! FileMode . TREE . equals ( mode ) ) {
if ( ! FileMode . TREE . equals ( mode ) ) {
final ObjectId me = idBuffer . toObjectId ( ) ;
final ObjectId me = idBuffer . toObjectId ( ) ;
throw new IncorrectObjectTypeException ( me , Constants . TYPE_TREE ) ;
throw new IncorrectObjectTypeException ( me , TYPE_TREE ) ;
}
}
return createSubtreeIterator0 ( reader , idBuffer ) ;
return createSubtreeIterator0 ( reader , idBuffer ) ;
}
}
@ -263,7 +266,7 @@ public class CanonicalTreeParser extends AbstractTreeIterator {
@Override
@Override
public int idOffset ( ) {
public int idOffset ( ) {
return nextPtr - Constants . OBJECT_ID_LENGTH ;
return nextPtr - OBJECT_ID_LENGTH ;
}
}
@Override
@Override
@ -301,7 +304,7 @@ public class CanonicalTreeParser extends AbstractTreeIterator {
prevPtr = ptr ;
prevPtr = ptr ;
while ( raw [ ptr ] ! = 0 )
while ( raw [ ptr ] ! = 0 )
ptr + + ;
ptr + + ;
ptr + = Constants . OBJECT_ID_LENGTH + 1 ;
ptr + = OBJECT_ID_LENGTH + 1 ;
}
}
if ( delta ! = 0 )
if ( delta ! = 0 )
throw new ArrayIndexOutOfBoundsException ( delta ) ;
throw new ArrayIndexOutOfBoundsException ( delta ) ;
@ -337,7 +340,7 @@ public class CanonicalTreeParser extends AbstractTreeIterator {
trace [ delta ] = ptr ;
trace [ delta ] = ptr ;
while ( raw [ ptr ] ! = 0 )
while ( raw [ ptr ] ! = 0 )
ptr + + ;
ptr + + ;
ptr + = Constants . OBJECT_ID_LENGTH + 1 ;
ptr + = OBJECT_ID_LENGTH + 1 ;
}
}
if ( trace [ 1 ] = = - 1 )
if ( trace [ 1 ] = = - 1 )
throw new ArrayIndexOutOfBoundsException ( delta ) ;
throw new ArrayIndexOutOfBoundsException ( delta ) ;
@ -372,12 +375,7 @@ public class CanonicalTreeParser extends AbstractTreeIterator {
}
}
}
}
pathLen = tmp ;
pathLen = tmp ;
nextPtr = ptr + Constants . OBJECT_ID_LENGTH ;
nextPtr = ptr + OBJECT_ID_LENGTH ;
// Check if this entry is a .gitattributes file
if ( path [ pathOffset ] = = '.'
& & RawParseUtils . match ( path , pathOffset , ATTRS ) > 0 )
attributesNode = new LazyLoadingAttributesNode ( idOffset ( ) ) ;
}
}
/ * *
/ * *
@ -391,36 +389,32 @@ public class CanonicalTreeParser extends AbstractTreeIterator {
* /
* /
public AttributesNode getEntryAttributesNode ( ObjectReader reader )
public AttributesNode getEntryAttributesNode ( ObjectReader reader )
throws IOException {
throws IOException {
if ( attributesNode instanceof LazyLoadingAttributesNode )
if ( attributesNode = = null ) {
attributesNode = ( ( LazyLoadingAttributesNode ) attributesNode )
attributesNode = findAttributes ( reader ) ;
. load ( reader ) ;
}
return attributesNode ;
return attributesNode . getRules ( ) . isEmpty ( ) ? null : attributesNode ;
}
}
/ * *
private AttributesNode findAttributes ( ObjectReader reader )
* { @link AttributesNode } implementation that provides lazy loading
throws IOException {
* /
CanonicalTreeParser itr = new CanonicalTreeParser ( ) ;
private class LazyLoadingAttributesNode extends AttributesNode {
itr . reset ( raw ) ;
private final int idOffset ;
if ( itr . findFile ( ATTRS ) ) {
return loadAttributes ( reader , itr . getEntryObjectId ( ) ) ;
LazyLoadingAttributesNode ( int idOffset ) {
}
super ( Collections . < AttributesRule > emptyList ( ) ) ;
return noAttributes ( ) ;
this . idOffset = idOffset ;
}
}
AttributesNode load ( ObjectReader reader ) throws IOException {
private static AttributesNode loadAttributes ( ObjectReader reader ,
AnyObjectId id ) throws IOException {
AttributesNode r = new AttributesNode ( ) ;
AttributesNode r = new AttributesNode ( ) ;
ObjectId id = ObjectId . fromRaw ( raw , idOffset ) ;
try ( InputStream in = reader . open ( id , OBJ_BLOB ) . openStream ( ) ) {
ObjectLoader loader = reader . open ( id ) ;
if ( loader ! = null ) {
InputStream in = loader . openStream ( ) ;
try {
r . parse ( in ) ;
r . parse ( in ) ;
} finally {
in . close ( ) ;
}
}
}
return r . getRules ( ) . isEmpty ( ) ? null : r ;
return r . getRules ( ) . isEmpty ( ) ? noAttributes ( ) : r ;
}
}
private static AttributesNode noAttributes ( ) {
return new AttributesNode ( Collections . < AttributesRule > emptyList ( ) ) ;
}
}
}
}