@ -70,6 +70,7 @@ import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants ;
import org.eclipse.jgit.lib.NullProgressMonitor ;
import org.eclipse.jgit.lib.ObjectId ;
import org.eclipse.jgit.lib.ObjectIdSubclassMap ;
import org.eclipse.jgit.lib.PackLock ;
import org.eclipse.jgit.lib.PersonIdent ;
import org.eclipse.jgit.lib.Ref ;
@ -77,6 +78,7 @@ import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository ;
import org.eclipse.jgit.lib.Config.SectionParser ;
import org.eclipse.jgit.revwalk.ObjectWalk ;
import org.eclipse.jgit.revwalk.RevBlob ;
import org.eclipse.jgit.revwalk.RevCommit ;
import org.eclipse.jgit.revwalk.RevFlag ;
import org.eclipse.jgit.revwalk.RevObject ;
@ -184,6 +186,8 @@ public class ReceivePack {
private boolean needBaseObjectIds ;
private boolean ensureObjectsProvidedVisible ;
/ * *
* Create a new pack receive for an open repository .
*
@ -288,6 +292,26 @@ public class ReceivePack {
return ip . getNewObjectIds ( ) ;
}
/ * *
* Configure this receive pack instance to ensure that the provided
* objects are visible to the user .
* < p >
* By default , a receive pack assumes that its user will only provide
* references to objects that it can see . Setting this flag to { @code true }
* will add an additional check that verifies that the objects that were
* provided are reachable by a tree or a commit that the user can see .
* < p >
* This option is useful when the code doesn ' t trust the client not to
* provide a forged SHA - 1 reference to an object in an attempt to access
* parts of the DAG that they aren ' t allowed to see , via the configured
* { @link RefFilter } .
*
* @param b { @code true } to enable the additional check .
* /
public void setEnsureProvidedObjectsVisible ( boolean b ) {
this . ensureObjectsProvidedVisible = b ;
}
/ * *
* @return true if this class expects a bi - directional pipe opened between
* the client and itself . The default is true .
@ -777,8 +801,9 @@ public class ReceivePack {
ip = IndexPack . create ( db , rawIn ) ;
ip . setFixThin ( true ) ;
ip . setNeedNewObjectIds ( needNewObjectIds ) ;
ip . setNeedBaseObjectIds ( needBaseObjectIds ) ;
ip . setNeedNewObjectIds ( needNewObjectIds | | ensureObjectsProvidedVisible ) ;
ip . setNeedBaseObjectIds ( needBaseObjectIds
| | ensureObjectsProvidedVisible ) ;
ip . setObjectChecking ( isCheckReceivedObjects ( ) ) ;
ip . index ( NullProgressMonitor . INSTANCE ) ;
@ -802,7 +827,34 @@ public class ReceivePack {
}
for ( final Ref ref : refs . values ( ) )
ow . markUninteresting ( ow . parseAny ( ref . getObjectId ( ) ) ) ;
ow . checkConnectivity ( ) ;
ObjectIdSubclassMap < ObjectId > provided =
new ObjectIdSubclassMap < ObjectId > ( ) ;
if ( ensureObjectsProvidedVisible ) {
for ( ObjectId id : getBaseObjectIds ( ) ) {
RevObject b = ow . lookupAny ( id , Constants . OBJ_BLOB ) ;
if ( ! b . has ( RevFlag . UNINTERESTING ) )
throw new MissingObjectException ( b , b . getType ( ) ) ;
}
for ( ObjectId id : getNewObjectIds ( ) ) {
provided . add ( id ) ;
}
}
RevCommit c ;
while ( ( c = ow . next ( ) ) ! = null ) {
if ( ensureObjectsProvidedVisible & & ! provided . contains ( c ) )
throw new MissingObjectException ( c , Constants . TYPE_COMMIT ) ;
}
RevObject o ;
while ( ( o = ow . nextObject ( ) ) ! = null ) {
if ( o instanceof RevBlob & & ! db . hasObject ( o ) )
throw new MissingObjectException ( o , Constants . TYPE_BLOB ) ;
if ( ensureObjectsProvidedVisible & & ! provided . contains ( o ) )
throw new MissingObjectException ( o , Constants . TYPE_BLOB ) ;
}
}
private void validateCommands ( ) {