@ -787,74 +787,23 @@ public class UploadPack {
preUploadHook . onBeginNegotiateRound ( this , wantIds , peerHas . size ( ) ) ;
preUploadHook . onBeginNegotiateRound ( this , wantIds , peerHas . size ( ) ) ;
if ( peerHas . isEmpty ( ) )
if ( peerHas . isEmpty ( ) )
return last ;
return last ;
if ( wantAll . isEmpty ( ) & & ! wantIds . isEmpty ( ) )
parseWants ( ) ;
List < ObjectId > toParse = peerHas ;
HashSet < ObjectId > peerHasSet = null ;
boolean needMissing = false ;
sentReady = false ;
sentReady = false ;
if ( wantAll . isEmpty ( ) & & ! wantIds . isEmpty ( ) ) {
// We have not yet parsed the want list. Parse it now.
peerHasSet = new HashSet < ObjectId > ( peerHas ) ;
int cnt = wantIds . size ( ) + peerHasSet . size ( ) ;
toParse = new ArrayList < ObjectId > ( cnt ) ;
toParse . addAll ( wantIds ) ;
toParse . addAll ( peerHasSet ) ;
needMissing = true ;
}
Set < RevObject > notAdvertisedWants = null ;
int haveCnt = 0 ;
int haveCnt = 0 ;
AsyncRevObjectQueue q = walk . parseAny ( toParse , needMissing ) ;
AsyncRevObjectQueue q = walk . parseAny ( peerHas , false ) ;
try {
try {
for ( ; ; ) {
for ( ; ; ) {
RevObject obj ;
RevObject obj ;
try {
try {
obj = q . next ( ) ;
obj = q . next ( ) ;
} catch ( MissingObjectException notFound ) {
} catch ( MissingObjectException notFound ) {
ObjectId id = notFound . getObjectId ( ) ;
if ( wantIds . contains ( id ) ) {
String msg = MessageFormat . format (
JGitText . get ( ) . wantNotValid , id . name ( ) ) ;
throw new PackProtocolException ( msg , notFound ) ;
}
continue ;
continue ;
}
}
if ( obj = = null )
if ( obj = = null )
break ;
break ;
// If the object is still found in wantIds, the want
// list wasn't parsed earlier, and was done in this batch.
//
if ( wantIds . remove ( obj ) ) {
if ( ! advertised . contains ( obj ) & & requestPolicy ! = RequestPolicy . ANY ) {
if ( notAdvertisedWants = = null )
notAdvertisedWants = new HashSet < RevObject > ( ) ;
notAdvertisedWants . add ( obj ) ;
}
if ( ! obj . has ( WANT ) ) {
obj . add ( WANT ) ;
wantAll . add ( obj ) ;
}
if ( ! ( obj instanceof RevCommit ) )
obj . add ( SATISFIED ) ;
if ( obj instanceof RevTag ) {
RevObject target = walk . peel ( obj ) ;
if ( target instanceof RevCommit ) {
if ( ! target . has ( WANT ) ) {
target . add ( WANT ) ;
wantAll . add ( target ) ;
}
}
}
if ( ! peerHasSet . contains ( obj ) )
continue ;
}
last = obj ;
last = obj ;
haveCnt + + ;
haveCnt + + ;
@ -891,25 +840,6 @@ public class UploadPack {
q . release ( ) ;
q . release ( ) ;
}
}
// If the client asked for non advertised object, check our policy.
if ( notAdvertisedWants ! = null & & ! notAdvertisedWants . isEmpty ( ) ) {
switch ( requestPolicy ) {
case ADVERTISED :
default :
throw new PackProtocolException ( MessageFormat . format (
JGitText . get ( ) . wantNotValid ,
notAdvertisedWants . iterator ( ) . next ( ) . name ( ) ) ) ;
case REACHABLE_COMMIT :
checkNotAdvertisedWants ( notAdvertisedWants ) ;
break ;
case ANY :
// Allow whatever was asked for.
break ;
}
}
int missCnt = peerHas . size ( ) - haveCnt ;
int missCnt = peerHas . size ( ) - haveCnt ;
// If we don't have one of the objects but we're also willing to
// If we don't have one of the objects but we're also willing to
@ -952,7 +882,61 @@ public class UploadPack {
return last ;
return last ;
}
}
private void checkNotAdvertisedWants ( Set < RevObject > notAdvertisedWants )
private void parseWants ( ) throws IOException {
AsyncRevObjectQueue q = walk . parseAny ( wantIds , true ) ;
try {
List < RevCommit > checkReachable = null ;
RevObject obj ;
while ( ( obj = q . next ( ) ) ! = null ) {
if ( ! advertised . contains ( obj ) ) {
switch ( requestPolicy ) {
case ADVERTISED :
default :
throw new PackProtocolException ( MessageFormat . format (
JGitText . get ( ) . wantNotValid , obj ) ) ;
case REACHABLE_COMMIT :
if ( ! ( obj instanceof RevCommit ) ) {
throw new PackProtocolException ( MessageFormat . format (
JGitText . get ( ) . wantNotValid , obj ) ) ;
}
if ( checkReachable = = null )
checkReachable = new ArrayList < RevCommit > ( ) ;
checkReachable . add ( ( RevCommit ) obj ) ;
break ;
case ANY :
break ;
}
}
want ( obj ) ;
if ( ! ( obj instanceof RevCommit ) )
obj . add ( SATISFIED ) ;
if ( obj instanceof RevTag ) {
obj = walk . peel ( obj ) ;
if ( obj instanceof RevCommit )
want ( obj ) ;
}
}
if ( checkReachable ! = null )
checkNotAdvertisedWants ( checkReachable ) ;
wantIds . clear ( ) ;
} catch ( MissingObjectException notFound ) {
ObjectId id = notFound . getObjectId ( ) ;
throw new PackProtocolException ( MessageFormat . format (
JGitText . get ( ) . wantNotValid , id . name ( ) ) , notFound ) ;
} finally {
q . release ( ) ;
}
}
private void want ( RevObject obj ) {
if ( ! obj . has ( WANT ) ) {
obj . add ( WANT ) ;
wantAll . add ( obj ) ;
}
}
private void checkNotAdvertisedWants ( List < RevCommit > notAdvertisedWants )
throws MissingObjectException , IncorrectObjectTypeException , IOException {
throws MissingObjectException , IncorrectObjectTypeException , IOException {
// Walk the requested commits back to the advertised commits.
// Walk the requested commits back to the advertised commits.
// If any commit exists, a branch was deleted or rewound and
// If any commit exists, a branch was deleted or rewound and
@ -960,15 +944,8 @@ public class UploadPack {
// If the requested commit is merged into an advertised branch
// If the requested commit is merged into an advertised branch
// it will be marked UNINTERESTING and no commits return.
// it will be marked UNINTERESTING and no commits return.
for ( RevObject o : notAdvertisedWants ) {
for ( RevCommit c : notAdvertisedWants )
if ( ! ( o instanceof RevCommit ) ) {
walk . markStart ( c ) ;
throw new PackProtocolException ( MessageFormat . format (
JGitText . get ( ) . wantNotValid ,
notAdvertisedWants . iterator ( ) . next ( ) . name ( ) ) ) ;
}
walk . markStart ( ( RevCommit ) o ) ;
}
for ( ObjectId id : advertised ) {
for ( ObjectId id : advertised ) {
try {
try {
walk . markUninteresting ( walk . parseCommit ( id ) ) ;
walk . markUninteresting ( walk . parseCommit ( id ) ) ;