@ -73,6 +73,8 @@ import java.util.Map;
import java.util.concurrent.locks.ReentrantLock ;
import java.util.function.Predicate ;
import org.eclipse.jgit.events.ListenerHandle ;
import org.eclipse.jgit.events.RefsChangedListener ;
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase ;
import org.eclipse.jgit.junit.StrictWorkMonitor ;
import org.eclipse.jgit.junit.TestRepository ;
@ -94,6 +96,7 @@ import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevCommit ;
import org.eclipse.jgit.revwalk.RevWalk ;
import org.eclipse.jgit.transport.ReceiveCommand ;
import org.junit.After ;
import org.junit.Before ;
import org.junit.Test ;
import org.junit.runner.RunWith ;
@ -118,6 +121,21 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
private RevCommit A ;
private RevCommit B ;
/ * *
* When asserting the number of RefsChangedEvents you must account for one
* additional event due to the initial ref setup via a number of calls to
* { @link # writeLooseRef ( String , AnyObjectId ) } ( will be fired in execute ( )
* when it is detected that the on - disk loose refs have changed ) , or for one
* additional event per { @link # writeRef ( String , AnyObjectId ) } .
* /
private int refsChangedEvents ;
private ListenerHandle handle ;
private RefsChangedListener refsChangedListener = event - > {
refsChangedEvents + + ;
} ;
@Override
@Before
public void setUp ( ) throws Exception {
@ -136,6 +154,15 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
repo = new TestRepository < > ( diskRepo ) ;
A = repo . commit ( ) . create ( ) ;
B = repo . commit ( repo . getRevWalk ( ) . parseCommit ( A ) ) ;
refsChangedEvents = 0 ;
handle = diskRepo . getListenerList ( )
. addRefsChangedListener ( refsChangedListener ) ;
}
@After
public void removeListener ( ) {
handle . remove ( ) ;
refsChangedEvents = 0 ;
}
@Test
@ -153,11 +180,13 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
assertRefs (
"refs/heads/master" , A ,
"refs/heads/masters" , B ) ;
assertEquals ( 1 , refsChangedEvents ) ;
} else {
assertResults ( cmds , OK , REJECTED_NONFASTFORWARD ) ;
assertRefs (
"refs/heads/master" , B ,
"refs/heads/masters" , B ) ;
assertEquals ( 2 , refsChangedEvents ) ;
}
}
@ -175,6 +204,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
assertRefs (
"refs/heads/master" , B ,
"refs/heads/masters" , A ) ;
assertEquals ( atomic ? 2 : 3 , refsChangedEvents ) ;
}
@Test
@ -196,6 +226,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
assertResults ( cmds , OK ) ;
assertRefs ( "refs/heads/master" , A ) ;
assertEquals ( 2 , refsChangedEvents ) ;
}
@Test
@ -217,6 +248,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
assertRefs (
"refs/heads/master" , A ,
"refs/heads/masters" , B ) ;
assertEquals ( 1 , refsChangedEvents ) ;
} else {
// Non-atomic updates are applied in order: master succeeds, then master/x
// fails due to conflict.
@ -224,6 +256,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
assertRefs (
"refs/heads/master" , B ,
"refs/heads/masters" , B ) ;
assertEquals ( 2 , refsChangedEvents ) ;
}
}
@ -242,6 +275,15 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
assertRefs (
"refs/heads/master" , B ,
"refs/heads/masters/x" , A ) ;
if ( atomic ) {
assertEquals ( 2 , refsChangedEvents ) ;
} else {
// The non-atomic case actually produces 5 events, but that's an
// implementation detail. We expect at least 4 events, one for the
// initial read due to writeLooseRef(), and then one for each
// successful ref update.
assertTrue ( refsChangedEvents > = 4 ) ;
}
}
@Test
@ -258,11 +300,13 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
if ( atomic ) {
assertResults ( cmds , REJECTED_MISSING_OBJECT , TRANSACTION_ABORTED ) ;
assertRefs ( "refs/heads/master" , A ) ;
assertEquals ( 1 , refsChangedEvents ) ;
} else {
assertResults ( cmds , REJECTED_MISSING_OBJECT , OK ) ;
assertRefs (
"refs/heads/master" , A ,
"refs/heads/foo2" , B ) ;
assertEquals ( 2 , refsChangedEvents ) ;
}
}
@ -280,9 +324,11 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
if ( atomic ) {
assertResults ( cmds , TRANSACTION_ABORTED , REJECTED_MISSING_OBJECT ) ;
assertRefs ( "refs/heads/master" , A ) ;
assertEquals ( 1 , refsChangedEvents ) ;
} else {
assertResults ( cmds , OK , REJECTED_MISSING_OBJECT ) ;
assertRefs ( "refs/heads/master" , B ) ;
assertEquals ( 2 , refsChangedEvents ) ;
}
}
@ -296,9 +342,11 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
if ( atomic ) {
assertResults ( cmds , LOCK_FAILURE , TRANSACTION_ABORTED ) ;
assertRefs ( ) ;
assertEquals ( 0 , refsChangedEvents ) ;
} else {
assertResults ( cmds , LOCK_FAILURE , OK ) ;
assertRefs ( "refs/heads/foo2" , B ) ;
assertEquals ( 1 , refsChangedEvents ) ;
}
}
@ -314,11 +362,13 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
if ( atomic ) {
assertResults ( cmds , LOCK_FAILURE , TRANSACTION_ABORTED ) ;
assertRefs ( "refs/heads/master" , A ) ;
assertEquals ( 1 , refsChangedEvents ) ;
} else {
assertResults ( cmds , LOCK_FAILURE , OK ) ;
assertRefs (
"refs/heads/master" , A ,
"refs/heads/foo2" , B ) ;
assertEquals ( 2 , refsChangedEvents ) ;
}
}
@ -334,9 +384,11 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
if ( atomic ) {
assertResults ( cmds , TRANSACTION_ABORTED , LOCK_FAILURE ) ;
assertRefs ( "refs/heads/master" , A ) ;
assertEquals ( 1 , refsChangedEvents ) ;
} else {
assertResults ( cmds , OK , LOCK_FAILURE ) ;
assertRefs ( "refs/heads/master" , B ) ;
assertEquals ( 2 , refsChangedEvents ) ;
}
}
@ -357,6 +409,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
assertRefs (
"refs/heads/master" , B ,
"refs/heads/branch" , B ) ;
assertEquals ( atomic ? 2 : 3 , refsChangedEvents ) ;
assertReflogUnchanged ( oldLogs , "refs/heads/master" ) ;
assertReflogUnchanged ( oldLogs , "refs/heads/branch" ) ;
}
@ -381,6 +434,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
"refs/heads/master" , B ,
"refs/heads/branch1" , B ,
"refs/heads/branch2" , A ) ;
assertEquals ( atomic ? 3 : 4 , refsChangedEvents ) ;
assertReflogEquals (
reflog ( A , B , new PersonIdent ( diskRepo ) , "a reflog" ) ,
getLastReflog ( "refs/heads/master" ) ) ;
@ -409,6 +463,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
"refs/heads/master" , B ,
"refs/heads/branch1" , A ,
"refs/heads/branch2" , A ) ;
assertEquals ( atomic ? 3 : 5 , refsChangedEvents ) ;
assertReflogEquals (
// Always forced; setAllowNonFastForwards(true) bypasses the check.
reflog ( A , B , new PersonIdent ( diskRepo ) , "forced-update" ) ,
@ -431,6 +486,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
assertResults ( cmds , OK ) ;
assertRefs ( "refs/heads/master" , B ) ;
assertEquals ( 2 , refsChangedEvents ) ;
assertReflogEquals (
reflog ( A , B , new PersonIdent ( diskRepo ) , "fast-forward" ) ,
getLastReflog ( "refs/heads/master" ) ) ;
@ -449,6 +505,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
assertRefs (
"refs/heads/master" , B ,
"refs/heads/branch" , A ) ;
assertEquals ( atomic ? 2 : 3 , refsChangedEvents ) ;
assertReflogEquals (
reflog ( A , B , new PersonIdent ( diskRepo ) , "a reflog: fast-forward" ) ,
getLastReflog ( "refs/heads/master" ) ) ;
@ -471,6 +528,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
. setRefLogIdent ( ident ) ) ;
assertResults ( cmds , OK , OK ) ;
assertEquals ( atomic ? 2 : 3 , refsChangedEvents ) ;
assertRefs (
"refs/heads/master" , B ,
"refs/heads/branch" , B ) ;
@ -498,6 +556,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
assertResults ( cmds , OK , OK ) ;
assertRefs ( "refs/heads/branch" , B ) ;
assertEquals ( atomic ? 3 : 4 , refsChangedEvents ) ;
assertNull ( getLastReflog ( "refs/heads/master" ) ) ;
assertReflogEquals (
reflog ( A , B , new PersonIdent ( diskRepo ) , "a reflog" ) ,
@ -515,6 +574,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
assertResults ( cmds , OK , OK ) ;
assertRefs ( "refs/heads/master/x" , A ) ;
assertEquals ( atomic ? 2 : 3 , refsChangedEvents ) ;
assertNull ( getLastReflog ( "refs/heads/master" ) ) ;
assertReflogEquals (
reflog ( zeroId ( ) , A , new PersonIdent ( diskRepo ) , "a reflog" ) ,
@ -535,10 +595,12 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
if ( atomic ) {
assertResults ( cmds , TRANSACTION_ABORTED , LOCK_FAILURE ) ;
assertEquals ( 1 , refsChangedEvents ) ;
assertReflogUnchanged ( oldLogs , "refs/heads/master" ) ;
assertReflogUnchanged ( oldLogs , "refs/heads/branch" ) ;
} else {
assertResults ( cmds , OK , LOCK_FAILURE ) ;
assertEquals ( 2 , refsChangedEvents ) ;
assertReflogEquals (
reflog ( A , B , new PersonIdent ( diskRepo ) , "a reflog" ) ,
getLastReflog ( "refs/heads/master" ) ) ;
@ -561,6 +623,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
. setRefLogMessage ( "a reflog" , true ) ) ;
assertResults ( cmds , OK , OK ) ;
assertEquals ( atomic ? 2 : 3 , refsChangedEvents ) ;
assertReflogEquals (
reflog ( A , B , ident , "custom log" ) ,
getLastReflog ( "refs/heads/master" ) ,
@ -585,6 +648,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
execute ( newBatchUpdate ( cmds ) . setRefLogMessage ( "a reflog" , true ) ) ;
assertResults ( cmds , OK , OK ) ;
assertEquals ( atomic ? 2 : 3 , refsChangedEvents ) ;
assertReflogUnchanged ( oldLogs , "refs/heads/master" ) ;
assertReflogEquals (
reflog ( zeroId ( ) , B , new PersonIdent ( diskRepo ) , "a reflog: created" ) ,
@ -609,12 +673,14 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
if ( atomic ) {
assertResults ( cmds , LOCK_FAILURE , TRANSACTION_ABORTED ) ;
assertRefs ( "refs/heads/master" , A ) ;
assertEquals ( 1 , refsChangedEvents ) ;
} else {
// Only operates on loose refs, doesn't care that packed-refs is locked.
assertResults ( cmds , OK , OK ) ;
assertRefs (
"refs/heads/master" , B ,
"refs/heads/branch" , B ) ;
assertEquals ( 3 , refsChangedEvents ) ;
}
} finally {
myLock . unlock ( ) ;
@ -640,11 +706,13 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
if ( atomic ) {
assertResults ( cmds , TRANSACTION_ABORTED , LOCK_FAILURE ) ;
assertRefs ( "refs/heads/master" , A ) ;
assertEquals ( 1 , refsChangedEvents ) ;
} else {
assertResults ( cmds , OK , LOCK_FAILURE ) ;
assertRefs (
"refs/heads/branch" , B ,
"refs/heads/master" , A ) ;
assertEquals ( 2 , refsChangedEvents ) ;
}
} finally {
myLock . unlock ( ) ;
@ -664,6 +732,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
assertFalse ( getLockFile ( "refs/heads/master" ) . exists ( ) ) ;
assertResults ( cmds , OK ) ;
assertEquals ( 2 , refsChangedEvents ) ;
assertRefs ( "refs/heads/master" , B ) ;
} finally {
myLock . unlock ( ) ;
@ -716,6 +785,7 @@ public class BatchRefUpdateTest extends LocalDiskRepositoryTestCase {
}
assertResults ( cmds , OK , OK ) ;
assertEquals ( 2 , refsChangedEvents ) ;
assertRefs (
"refs/heads/master" , B ,
"refs/heads/branch" , B ) ;