@ -10,8 +10,14 @@
package org.eclipse.jgit.transport ;
package org.eclipse.jgit.transport ;
import static java.util.Objects.requireNonNull ;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB ;
import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT ;
import static org.eclipse.jgit.lib.Constants.OBJ_TAG ;
import static org.eclipse.jgit.lib.Constants.OBJ_TREE ;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_FILTER ;
import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_FILTER ;
import java.math.BigInteger ;
import java.text.MessageFormat ;
import java.text.MessageFormat ;
import org.eclipse.jgit.annotations.Nullable ;
import org.eclipse.jgit.annotations.Nullable ;
@ -26,11 +32,54 @@ import org.eclipse.jgit.internal.JGitText;
* /
* /
public final class FilterSpec {
public final class FilterSpec {
/** Immutable bit-set representation of a set of Git object types. */
static class ObjectTypes {
static ObjectTypes ALL = allow ( OBJ_BLOB , OBJ_TREE , OBJ_COMMIT , OBJ_TAG ) ;
private final BigInteger val ;
private ObjectTypes ( BigInteger val ) {
this . val = requireNonNull ( val ) ;
}
static ObjectTypes allow ( int . . . types ) {
BigInteger bits = BigInteger . valueOf ( 0 ) ;
for ( int type : types ) {
bits = bits . setBit ( type ) ;
}
return new ObjectTypes ( bits ) ;
}
boolean contains ( int type ) {
return val . testBit ( type ) ;
}
/** {@inheritDoc} */
@Override
public boolean equals ( Object obj ) {
if ( ! ( obj instanceof ObjectTypes ) ) {
return false ;
}
ObjectTypes other = ( ObjectTypes ) obj ;
return other . val . equals ( val ) ;
}
/** {@inheritDoc} */
@Override
public int hashCode ( ) {
return val . hashCode ( ) ;
}
}
private final ObjectTypes types ;
private final long blobLimit ;
private final long blobLimit ;
private final long treeDepthLimit ;
private final long treeDepthLimit ;
private FilterSpec ( long blobLimit , long treeDepthLimit ) {
private FilterSpec ( ObjectTypes types , long blobLimit , long treeDepthLimit ) {
this . types = requireNonNull ( types ) ;
this . blobLimit = blobLimit ;
this . blobLimit = blobLimit ;
this . treeDepthLimit = treeDepthLimit ;
this . treeDepthLimit = treeDepthLimit ;
}
}
@ -55,7 +104,8 @@ public final class FilterSpec {
public static FilterSpec fromFilterLine ( String filterLine )
public static FilterSpec fromFilterLine ( String filterLine )
throws PackProtocolException {
throws PackProtocolException {
if ( filterLine . equals ( "blob:none" ) ) { //$NON-NLS-1$
if ( filterLine . equals ( "blob:none" ) ) { //$NON-NLS-1$
return FilterSpec . withBlobLimit ( 0 ) ;
return FilterSpec . withObjectTypes (
ObjectTypes . allow ( OBJ_TREE , OBJ_COMMIT , OBJ_TAG ) ) ;
} else if ( filterLine . startsWith ( "blob:limit=" ) ) { //$NON-NLS-1$
} else if ( filterLine . startsWith ( "blob:limit=" ) ) { //$NON-NLS-1$
long blobLimit = - 1 ;
long blobLimit = - 1 ;
try {
try {
@ -87,9 +137,19 @@ public final class FilterSpec {
MessageFormat . format ( JGitText . get ( ) . invalidFilter , filterLine ) ) ;
MessageFormat . format ( JGitText . get ( ) . invalidFilter , filterLine ) ) ;
}
}
/ * *
* @param types
* set of permitted object types , for use in "blob:none" and
* "object:none" filters
* @return a filter spec which restricts to objects of the specified types
* /
static FilterSpec withObjectTypes ( ObjectTypes types ) {
return new FilterSpec ( types , - 1 , - 1 ) ;
}
/ * *
/ * *
* @param blobLimit
* @param blobLimit
* the blob limit in a "blob:[limit]" or "blob:none" filter line
* the blob limit in a "blob:[limit]" filter line
* @return a filter spec which filters blobs above a certain size
* @return a filter spec which filters blobs above a certain size
* /
* /
static FilterSpec withBlobLimit ( long blobLimit ) {
static FilterSpec withBlobLimit ( long blobLimit ) {
@ -97,7 +157,7 @@ public final class FilterSpec {
throw new IllegalArgumentException (
throw new IllegalArgumentException (
"blobLimit cannot be negative: " + blobLimit ) ; //$NON-NLS-1$
"blobLimit cannot be negative: " + blobLimit ) ; //$NON-NLS-1$
}
}
return new FilterSpec ( blobLimit , - 1 ) ;
return new FilterSpec ( ObjectTypes . ALL , blobLimit , - 1 ) ;
}
}
/ * *
/ * *
@ -111,13 +171,25 @@ public final class FilterSpec {
throw new IllegalArgumentException (
throw new IllegalArgumentException (
"treeDepthLimit cannot be negative: " + treeDepthLimit ) ; //$NON-NLS-1$
"treeDepthLimit cannot be negative: " + treeDepthLimit ) ; //$NON-NLS-1$
}
}
return new FilterSpec ( - 1 , treeDepthLimit ) ;
return new FilterSpec ( ObjectTypes . ALL , - 1 , treeDepthLimit ) ;
}
}
/ * *
/ * *
* A placeholder that indicates no filtering .
* A placeholder that indicates no filtering .
* /
* /
public static final FilterSpec NO_FILTER = new FilterSpec ( - 1 , - 1 ) ;
public static final FilterSpec NO_FILTER = new FilterSpec ( ObjectTypes . ALL , - 1 , - 1 ) ;
/ * *
* @param type
* a Git object type , such as
* { @link org . eclipse . jgit . lib . Constants # OBJ_BLOB }
* @return whether this filter allows objects of the specified type
*
* @since 5 . 9
* /
public boolean allowsType ( int type ) {
return types . contains ( type ) ;
}
/ * *
/ * *
* @return - 1 if this filter does not filter blobs based on size , or a
* @return - 1 if this filter does not filter blobs based on size , or a
@ -140,7 +212,7 @@ public final class FilterSpec {
* @return true if this filter doesn ' t filter out anything
* @return true if this filter doesn ' t filter out anything
* /
* /
public boolean isNoOp ( ) {
public boolean isNoOp ( ) {
return blobLimit = = - 1 & & treeDepthLimit = = - 1 ;
return types . equals ( ObjectTypes . ALL ) & & blobLimit = = - 1 & & treeDepthLimit = = - 1 ;
}
}
/ * *
/ * *
@ -150,11 +222,12 @@ public final class FilterSpec {
public String filterLine ( ) {
public String filterLine ( ) {
if ( isNoOp ( ) ) {
if ( isNoOp ( ) ) {
return null ;
return null ;
} else if ( blobLimit = = 0 & & treeDepthLimit = = - 1 ) {
} else if ( types . equals ( ObjectTypes . allow ( OBJ_TREE , OBJ_COMMIT , OBJ_TAG ) ) & &
blobLimit = = - 1 & & treeDepthLimit = = - 1 ) {
return OPTION_FILTER + " blob:none" ; //$NON-NLS-1$
return OPTION_FILTER + " blob:none" ; //$NON-NLS-1$
} else if ( blobLimit > 0 & & treeDepthLimit = = - 1 ) {
} else if ( types . equals ( ObjectTypes . ALL ) & & blobLimit > = 0 & & treeDepthLimit = = - 1 ) {
return OPTION_FILTER + " blob:limit=" + blobLimit ; //$NON-NLS-1$
return OPTION_FILTER + " blob:limit=" + blobLimit ; //$NON-NLS-1$
} else if ( blobLimit = = - 1 & & treeDepthLimit > = 0 ) {
} else if ( types . equals ( ObjectTypes . ALL ) & & blobLimit = = - 1 & & treeDepthLimit > = 0 ) {
return OPTION_FILTER + " tree:" + treeDepthLimit ; //$NON-NLS-1$
return OPTION_FILTER + " tree:" + treeDepthLimit ; //$NON-NLS-1$
} else {
} else {
throw new IllegalStateException ( ) ;
throw new IllegalStateException ( ) ;