Merge branch 'stable-5.9' into stable-5.10
* stable-5.9: Prepare 5.1.17-SNAPSHOT builds JGit v5.1.16.202106041830-r BatchRefUpdate: Skip saving conflicting ref names and prefixes in memory BatchRefUpdateTest: Accurately assert RefsChangedEvent(s) fired Optimize RefDirectory.isNameConflicting() Update bazlets and bazel version Change-Id: Ib1299564a4cfb9c01f422d7ada05fcfac29700f8
This commit is contained in:
commit
e2dc4b9c64
|
@ -190,14 +190,27 @@ public void simpleNoForce() throws IOException {
|
||||||
if (atomic) {
|
if (atomic) {
|
||||||
assertResults(cmds, TRANSACTION_ABORTED, REJECTED_NONFASTFORWARD);
|
assertResults(cmds, TRANSACTION_ABORTED, REJECTED_NONFASTFORWARD);
|
||||||
assertRefs("refs/heads/master", A, "refs/heads/masters", B);
|
assertRefs("refs/heads/master", A, "refs/heads/masters", B);
|
||||||
assertEquals(1, refsChangedEvents);
|
|
||||||
} else {
|
} else {
|
||||||
assertResults(cmds, OK, REJECTED_NONFASTFORWARD);
|
assertResults(cmds, OK, REJECTED_NONFASTFORWARD);
|
||||||
assertRefs("refs/heads/master", B, "refs/heads/masters", B);
|
assertRefs("refs/heads/master", B, "refs/heads/masters", B);
|
||||||
assertEquals(2, refsChangedEvents);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void simpleNoForceRefsChangedEvents() throws IOException {
|
||||||
|
writeLooseRefs("refs/heads/master", A, "refs/heads/masters", B);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
|
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
||||||
|
new ReceiveCommand(B, A, "refs/heads/masters",
|
||||||
|
UPDATE_NONFASTFORWARD));
|
||||||
|
execute(newBatchUpdate(cmds));
|
||||||
|
|
||||||
|
assertEquals(atomic ? initialRefsChangedEvents
|
||||||
|
: initialRefsChangedEvents + 1, refsChangedEvents);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void simpleForce() throws IOException {
|
public void simpleForce() throws IOException {
|
||||||
writeLooseRefs("refs/heads/master", A, "refs/heads/masters", B);
|
writeLooseRefs("refs/heads/master", A, "refs/heads/masters", B);
|
||||||
|
@ -210,7 +223,21 @@ public void simpleForce() throws IOException {
|
||||||
|
|
||||||
assertResults(cmds, OK, OK);
|
assertResults(cmds, OK, OK);
|
||||||
assertRefs("refs/heads/master", B, "refs/heads/masters", A);
|
assertRefs("refs/heads/master", B, "refs/heads/masters", A);
|
||||||
assertEquals(batchesRefUpdates() ? 2 : 3, refsChangedEvents);
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void simpleForceRefsChangedEvents() throws IOException {
|
||||||
|
writeLooseRefs("refs/heads/master", A, "refs/heads/masters", B);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
|
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
||||||
|
new ReceiveCommand(B, A, "refs/heads/masters",
|
||||||
|
UPDATE_NONFASTFORWARD));
|
||||||
|
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));
|
||||||
|
|
||||||
|
assertEquals(batchesRefUpdates() ? initialRefsChangedEvents + 1
|
||||||
|
: initialRefsChangedEvents + 2, refsChangedEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -232,7 +259,27 @@ public boolean isMergedInto(RevCommit base, RevCommit tip) {
|
||||||
|
|
||||||
assertResults(cmds, OK);
|
assertResults(cmds, OK);
|
||||||
assertRefs("refs/heads/master", A);
|
assertRefs("refs/heads/master", A);
|
||||||
assertEquals(2, refsChangedEvents);
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void nonFastForwardDoesNotDoExpensiveMergeCheckRefsChangedEvents()
|
||||||
|
throws IOException {
|
||||||
|
writeLooseRef("refs/heads/master", B);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
|
List<ReceiveCommand> cmds = Arrays.asList(new ReceiveCommand(B, A,
|
||||||
|
"refs/heads/master", UPDATE_NONFASTFORWARD));
|
||||||
|
try (RevWalk rw = new RevWalk(diskRepo) {
|
||||||
|
@Override
|
||||||
|
public boolean isMergedInto(RevCommit base, RevCommit tip) {
|
||||||
|
throw new AssertionError("isMergedInto() should not be called");
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
newBatchUpdate(cmds).setAllowNonFastForwards(true).execute(rw,
|
||||||
|
new StrictWorkMonitor());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(initialRefsChangedEvents + 1, refsChangedEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -251,16 +298,29 @@ public void fileDirectoryConflict() throws IOException {
|
||||||
assertResults(cmds, LOCK_FAILURE, TRANSACTION_ABORTED,
|
assertResults(cmds, LOCK_FAILURE, TRANSACTION_ABORTED,
|
||||||
TRANSACTION_ABORTED);
|
TRANSACTION_ABORTED);
|
||||||
assertRefs("refs/heads/master", A, "refs/heads/masters", B);
|
assertRefs("refs/heads/master", A, "refs/heads/masters", B);
|
||||||
assertEquals(1, refsChangedEvents);
|
|
||||||
} else {
|
} else {
|
||||||
// Non-atomic updates are applied in order: master succeeds, then
|
// Non-atomic updates are applied in order: master succeeds, then
|
||||||
// master/x fails due to conflict.
|
// master/x fails due to conflict.
|
||||||
assertResults(cmds, OK, LOCK_FAILURE, LOCK_FAILURE);
|
assertResults(cmds, OK, LOCK_FAILURE, LOCK_FAILURE);
|
||||||
assertRefs("refs/heads/master", B, "refs/heads/masters", B);
|
assertRefs("refs/heads/master", B, "refs/heads/masters", B);
|
||||||
assertEquals(2, refsChangedEvents);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fileDirectoryConflictRefsChangedEvents() throws IOException {
|
||||||
|
writeLooseRefs("refs/heads/master", A, "refs/heads/masters", B);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
|
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
||||||
|
new ReceiveCommand(zeroId(), A, "refs/heads/master/x", CREATE),
|
||||||
|
new ReceiveCommand(zeroId(), A, "refs/heads", CREATE));
|
||||||
|
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true), false);
|
||||||
|
|
||||||
|
assertEquals(atomic ? initialRefsChangedEvents
|
||||||
|
: initialRefsChangedEvents + 1, refsChangedEvents);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void conflictThanksToDelete() throws IOException {
|
public void conflictThanksToDelete() throws IOException {
|
||||||
writeLooseRefs("refs/heads/master", A, "refs/heads/masters", B);
|
writeLooseRefs("refs/heads/master", A, "refs/heads/masters", B);
|
||||||
|
@ -273,15 +333,21 @@ public void conflictThanksToDelete() throws IOException {
|
||||||
|
|
||||||
assertResults(cmds, OK, OK, OK);
|
assertResults(cmds, OK, OK, OK);
|
||||||
assertRefs("refs/heads/master", B, "refs/heads/masters/x", A);
|
assertRefs("refs/heads/master", B, "refs/heads/masters/x", A);
|
||||||
if (atomic) {
|
}
|
||||||
assertEquals(2, refsChangedEvents);
|
|
||||||
} else if (!useReftable) {
|
@Test
|
||||||
// The non-atomic case actually produces 5 events, but that's an
|
public void conflictThanksToDeleteRefsChangedEvents() throws IOException {
|
||||||
// implementation detail. We expect at least 4 events, one for the
|
writeLooseRefs("refs/heads/master", A, "refs/heads/masters", B);
|
||||||
// initial read due to writeLooseRef(), and then one for each
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
// successful ref update.
|
|
||||||
assertTrue(refsChangedEvents >= 4);
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
}
|
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
||||||
|
new ReceiveCommand(zeroId(), A, "refs/heads/masters/x", CREATE),
|
||||||
|
new ReceiveCommand(B, zeroId(), "refs/heads/masters", DELETE));
|
||||||
|
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));
|
||||||
|
|
||||||
|
assertEquals(batchesRefUpdates() ? initialRefsChangedEvents + 1
|
||||||
|
: initialRefsChangedEvents + 3, refsChangedEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -298,14 +364,28 @@ public void updateToMissingObject() throws IOException {
|
||||||
if (atomic) {
|
if (atomic) {
|
||||||
assertResults(cmds, REJECTED_MISSING_OBJECT, TRANSACTION_ABORTED);
|
assertResults(cmds, REJECTED_MISSING_OBJECT, TRANSACTION_ABORTED);
|
||||||
assertRefs("refs/heads/master", A);
|
assertRefs("refs/heads/master", A);
|
||||||
assertEquals(1, refsChangedEvents);
|
|
||||||
} else {
|
} else {
|
||||||
assertResults(cmds, REJECTED_MISSING_OBJECT, OK);
|
assertResults(cmds, REJECTED_MISSING_OBJECT, OK);
|
||||||
assertRefs("refs/heads/master", A, "refs/heads/foo2", B);
|
assertRefs("refs/heads/master", A, "refs/heads/foo2", B);
|
||||||
assertEquals(2, refsChangedEvents);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateToMissingObjectRefsChangedEvents() throws IOException {
|
||||||
|
writeLooseRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
|
ObjectId bad = ObjectId
|
||||||
|
.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
|
||||||
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
|
new ReceiveCommand(A, bad, "refs/heads/master", UPDATE),
|
||||||
|
new ReceiveCommand(zeroId(), B, "refs/heads/foo2", CREATE));
|
||||||
|
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true), false);
|
||||||
|
|
||||||
|
assertEquals(atomic ? initialRefsChangedEvents
|
||||||
|
: initialRefsChangedEvents + 1, refsChangedEvents);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void addMissingObject() throws IOException {
|
public void addMissingObject() throws IOException {
|
||||||
writeLooseRef("refs/heads/master", A);
|
writeLooseRef("refs/heads/master", A);
|
||||||
|
@ -320,14 +400,28 @@ public void addMissingObject() throws IOException {
|
||||||
if (atomic) {
|
if (atomic) {
|
||||||
assertResults(cmds, TRANSACTION_ABORTED, REJECTED_MISSING_OBJECT);
|
assertResults(cmds, TRANSACTION_ABORTED, REJECTED_MISSING_OBJECT);
|
||||||
assertRefs("refs/heads/master", A);
|
assertRefs("refs/heads/master", A);
|
||||||
assertEquals(1, refsChangedEvents);
|
|
||||||
} else {
|
} else {
|
||||||
assertResults(cmds, OK, REJECTED_MISSING_OBJECT);
|
assertResults(cmds, OK, REJECTED_MISSING_OBJECT);
|
||||||
assertRefs("refs/heads/master", B);
|
assertRefs("refs/heads/master", B);
|
||||||
assertEquals(2, refsChangedEvents);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addMissingObjectRefsChangedEvents() throws IOException {
|
||||||
|
writeLooseRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
|
ObjectId bad = ObjectId
|
||||||
|
.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
|
||||||
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
|
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
||||||
|
new ReceiveCommand(zeroId(), bad, "refs/heads/foo2", CREATE));
|
||||||
|
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true), false);
|
||||||
|
|
||||||
|
assertEquals(atomic ? initialRefsChangedEvents
|
||||||
|
: initialRefsChangedEvents + 1, refsChangedEvents);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void oneNonExistentRef() throws IOException {
|
public void oneNonExistentRef() throws IOException {
|
||||||
List<ReceiveCommand> cmds = Arrays.asList(
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
|
@ -358,14 +452,26 @@ public void oneRefWrongOldValue() throws IOException {
|
||||||
if (atomic) {
|
if (atomic) {
|
||||||
assertResults(cmds, LOCK_FAILURE, TRANSACTION_ABORTED);
|
assertResults(cmds, LOCK_FAILURE, TRANSACTION_ABORTED);
|
||||||
assertRefs("refs/heads/master", A);
|
assertRefs("refs/heads/master", A);
|
||||||
assertEquals(1, refsChangedEvents);
|
|
||||||
} else {
|
} else {
|
||||||
assertResults(cmds, LOCK_FAILURE, OK);
|
assertResults(cmds, LOCK_FAILURE, OK);
|
||||||
assertRefs("refs/heads/master", A, "refs/heads/foo2", B);
|
assertRefs("refs/heads/master", A, "refs/heads/foo2", B);
|
||||||
assertEquals(2, refsChangedEvents);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void oneRefWrongOldValueRefsChangedEvents() throws IOException {
|
||||||
|
writeLooseRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
|
new ReceiveCommand(B, B, "refs/heads/master", UPDATE),
|
||||||
|
new ReceiveCommand(zeroId(), B, "refs/heads/foo2", CREATE));
|
||||||
|
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));
|
||||||
|
|
||||||
|
assertEquals(atomic ? initialRefsChangedEvents
|
||||||
|
: initialRefsChangedEvents + 1, refsChangedEvents);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void nonExistentRef() throws IOException {
|
public void nonExistentRef() throws IOException {
|
||||||
writeLooseRef("refs/heads/master", A);
|
writeLooseRef("refs/heads/master", A);
|
||||||
|
@ -378,17 +484,31 @@ public void nonExistentRef() throws IOException {
|
||||||
if (atomic) {
|
if (atomic) {
|
||||||
assertResults(cmds, TRANSACTION_ABORTED, LOCK_FAILURE);
|
assertResults(cmds, TRANSACTION_ABORTED, LOCK_FAILURE);
|
||||||
assertRefs("refs/heads/master", A);
|
assertRefs("refs/heads/master", A);
|
||||||
assertEquals(1, refsChangedEvents);
|
|
||||||
} else {
|
} else {
|
||||||
assertResults(cmds, OK, LOCK_FAILURE);
|
assertResults(cmds, OK, LOCK_FAILURE);
|
||||||
assertRefs("refs/heads/master", B);
|
assertRefs("refs/heads/master", B);
|
||||||
assertEquals(2, refsChangedEvents);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void nonExistentRefRefsChangedEvents() throws IOException {
|
||||||
|
writeLooseRef("refs/heads/master", A);
|
||||||
|
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
|
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
||||||
|
new ReceiveCommand(A, zeroId(), "refs/heads/foo2", DELETE));
|
||||||
|
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));
|
||||||
|
|
||||||
|
assertEquals(atomic ? initialRefsChangedEvents
|
||||||
|
: initialRefsChangedEvents + 1, refsChangedEvents);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void noRefLog() throws IOException {
|
public void noRefLog() throws IOException {
|
||||||
writeRef("refs/heads/master", A);
|
writeRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
Map<String, ReflogEntry> oldLogs = getLastReflogs("refs/heads/master",
|
Map<String, ReflogEntry> oldLogs = getLastReflogs("refs/heads/master",
|
||||||
"refs/heads/branch");
|
"refs/heads/branch");
|
||||||
|
@ -402,7 +522,8 @@ public void noRefLog() throws IOException {
|
||||||
|
|
||||||
assertResults(cmds, OK, OK);
|
assertResults(cmds, OK, OK);
|
||||||
assertRefs("refs/heads/master", B, "refs/heads/branch", B);
|
assertRefs("refs/heads/master", B, "refs/heads/branch", B);
|
||||||
assertEquals(batchesRefUpdates() ? 2 : 3, refsChangedEvents);
|
assertEquals(batchesRefUpdates() ? initialRefsChangedEvents + 1
|
||||||
|
: initialRefsChangedEvents + 2, refsChangedEvents);
|
||||||
assertReflogUnchanged(oldLogs, "refs/heads/master");
|
assertReflogUnchanged(oldLogs, "refs/heads/master");
|
||||||
assertReflogUnchanged(oldLogs, "refs/heads/branch");
|
assertReflogUnchanged(oldLogs, "refs/heads/branch");
|
||||||
}
|
}
|
||||||
|
@ -411,6 +532,7 @@ public void noRefLog() throws IOException {
|
||||||
public void reflogDefaultIdent() throws IOException {
|
public void reflogDefaultIdent() throws IOException {
|
||||||
writeRef("refs/heads/master", A);
|
writeRef("refs/heads/master", A);
|
||||||
writeRef("refs/heads/branch2", A);
|
writeRef("refs/heads/branch2", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
Map<String, ReflogEntry> oldLogs = getLastReflogs("refs/heads/master",
|
Map<String, ReflogEntry> oldLogs = getLastReflogs("refs/heads/master",
|
||||||
"refs/heads/branch1", "refs/heads/branch2");
|
"refs/heads/branch1", "refs/heads/branch2");
|
||||||
|
@ -423,7 +545,8 @@ public void reflogDefaultIdent() throws IOException {
|
||||||
assertResults(cmds, OK, OK);
|
assertResults(cmds, OK, OK);
|
||||||
assertRefs("refs/heads/master", B, "refs/heads/branch1", B,
|
assertRefs("refs/heads/master", B, "refs/heads/branch1", B,
|
||||||
"refs/heads/branch2", A);
|
"refs/heads/branch2", A);
|
||||||
assertEquals(batchesRefUpdates() ? 3 : 4, refsChangedEvents);
|
assertEquals(batchesRefUpdates() ? initialRefsChangedEvents + 1
|
||||||
|
: initialRefsChangedEvents + 2, refsChangedEvents);
|
||||||
assertReflogEquals(reflog(A, B, new PersonIdent(diskRepo), "a reflog"),
|
assertReflogEquals(reflog(A, B, new PersonIdent(diskRepo), "a reflog"),
|
||||||
getLastReflog("refs/heads/master"));
|
getLastReflog("refs/heads/master"));
|
||||||
assertReflogEquals(
|
assertReflogEquals(
|
||||||
|
@ -436,6 +559,7 @@ public void reflogDefaultIdent() throws IOException {
|
||||||
public void reflogAppendStatusNoMessage() throws IOException {
|
public void reflogAppendStatusNoMessage() throws IOException {
|
||||||
writeRef("refs/heads/master", A);
|
writeRef("refs/heads/master", A);
|
||||||
writeRef("refs/heads/branch1", B);
|
writeRef("refs/heads/branch1", B);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
List<ReceiveCommand> cmds = Arrays.asList(
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
||||||
|
@ -448,7 +572,8 @@ public void reflogAppendStatusNoMessage() throws IOException {
|
||||||
assertResults(cmds, OK, OK, OK);
|
assertResults(cmds, OK, OK, OK);
|
||||||
assertRefs("refs/heads/master", B, "refs/heads/branch1", A,
|
assertRefs("refs/heads/master", B, "refs/heads/branch1", A,
|
||||||
"refs/heads/branch2", A);
|
"refs/heads/branch2", A);
|
||||||
assertEquals(batchesRefUpdates() ? 3 : 5, refsChangedEvents);
|
assertEquals(batchesRefUpdates() ? initialRefsChangedEvents + 1
|
||||||
|
: initialRefsChangedEvents + 3, refsChangedEvents);
|
||||||
assertReflogEquals(
|
assertReflogEquals(
|
||||||
// Always forced; setAllowNonFastForwards(true) bypasses the
|
// Always forced; setAllowNonFastForwards(true) bypasses the
|
||||||
// check.
|
// check.
|
||||||
|
@ -465,6 +590,7 @@ public void reflogAppendStatusNoMessage() throws IOException {
|
||||||
@Test
|
@Test
|
||||||
public void reflogAppendStatusFastForward() throws IOException {
|
public void reflogAppendStatusFastForward() throws IOException {
|
||||||
writeRef("refs/heads/master", A);
|
writeRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
List<ReceiveCommand> cmds = Arrays
|
List<ReceiveCommand> cmds = Arrays
|
||||||
.asList(new ReceiveCommand(A, B, "refs/heads/master", UPDATE));
|
.asList(new ReceiveCommand(A, B, "refs/heads/master", UPDATE));
|
||||||
|
@ -472,7 +598,7 @@ public void reflogAppendStatusFastForward() throws IOException {
|
||||||
|
|
||||||
assertResults(cmds, OK);
|
assertResults(cmds, OK);
|
||||||
assertRefs("refs/heads/master", B);
|
assertRefs("refs/heads/master", B);
|
||||||
assertEquals(2, refsChangedEvents);
|
assertEquals(initialRefsChangedEvents + 1, refsChangedEvents);
|
||||||
assertReflogEquals(
|
assertReflogEquals(
|
||||||
reflog(A, B, new PersonIdent(diskRepo), "fast-forward"),
|
reflog(A, B, new PersonIdent(diskRepo), "fast-forward"),
|
||||||
getLastReflog("refs/heads/master"));
|
getLastReflog("refs/heads/master"));
|
||||||
|
@ -481,6 +607,7 @@ public void reflogAppendStatusFastForward() throws IOException {
|
||||||
@Test
|
@Test
|
||||||
public void reflogAppendStatusWithMessage() throws IOException {
|
public void reflogAppendStatusWithMessage() throws IOException {
|
||||||
writeRef("refs/heads/master", A);
|
writeRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
List<ReceiveCommand> cmds = Arrays.asList(
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
||||||
|
@ -489,7 +616,8 @@ public void reflogAppendStatusWithMessage() throws IOException {
|
||||||
|
|
||||||
assertResults(cmds, OK, OK);
|
assertResults(cmds, OK, OK);
|
||||||
assertRefs("refs/heads/master", B, "refs/heads/branch", A);
|
assertRefs("refs/heads/master", B, "refs/heads/branch", A);
|
||||||
assertEquals(batchesRefUpdates() ? 2 : 3, refsChangedEvents);
|
assertEquals(batchesRefUpdates() ? initialRefsChangedEvents + 1
|
||||||
|
: initialRefsChangedEvents + 2, refsChangedEvents);
|
||||||
assertReflogEquals(
|
assertReflogEquals(
|
||||||
reflog(A, B, new PersonIdent(diskRepo),
|
reflog(A, B, new PersonIdent(diskRepo),
|
||||||
"a reflog: fast-forward"),
|
"a reflog: fast-forward"),
|
||||||
|
@ -503,6 +631,7 @@ public void reflogAppendStatusWithMessage() throws IOException {
|
||||||
@Test
|
@Test
|
||||||
public void reflogCustomIdent() throws IOException {
|
public void reflogCustomIdent() throws IOException {
|
||||||
writeRef("refs/heads/master", A);
|
writeRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
List<ReceiveCommand> cmds = Arrays.asList(
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
||||||
|
@ -513,7 +642,8 @@ public void reflogCustomIdent() throws IOException {
|
||||||
.setRefLogIdent(ident));
|
.setRefLogIdent(ident));
|
||||||
|
|
||||||
assertResults(cmds, OK, OK);
|
assertResults(cmds, OK, OK);
|
||||||
assertEquals(batchesRefUpdates() ? 2 : 3, refsChangedEvents);
|
assertEquals(batchesRefUpdates() ? initialRefsChangedEvents + 1
|
||||||
|
: initialRefsChangedEvents + 2, refsChangedEvents);
|
||||||
assertRefs("refs/heads/master", B, "refs/heads/branch", B);
|
assertRefs("refs/heads/master", B, "refs/heads/branch", B);
|
||||||
assertReflogEquals(reflog(A, B, ident, "a reflog"),
|
assertReflogEquals(reflog(A, B, ident, "a reflog"),
|
||||||
getLastReflog("refs/heads/master"), true);
|
getLastReflog("refs/heads/master"), true);
|
||||||
|
@ -525,6 +655,7 @@ public void reflogCustomIdent() throws IOException {
|
||||||
public void reflogDelete() throws IOException {
|
public void reflogDelete() throws IOException {
|
||||||
writeRef("refs/heads/master", A);
|
writeRef("refs/heads/master", A);
|
||||||
writeRef("refs/heads/branch", A);
|
writeRef("refs/heads/branch", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
assertEquals(2, getLastReflogs("refs/heads/master", "refs/heads/branch")
|
assertEquals(2, getLastReflogs("refs/heads/master", "refs/heads/branch")
|
||||||
.size());
|
.size());
|
||||||
|
|
||||||
|
@ -535,7 +666,8 @@ public void reflogDelete() throws IOException {
|
||||||
|
|
||||||
assertResults(cmds, OK, OK);
|
assertResults(cmds, OK, OK);
|
||||||
assertRefs("refs/heads/branch", B);
|
assertRefs("refs/heads/branch", B);
|
||||||
assertEquals(batchesRefUpdates() ? 3 : 4, refsChangedEvents);
|
assertEquals(batchesRefUpdates() ? initialRefsChangedEvents + 1
|
||||||
|
: initialRefsChangedEvents + 2, refsChangedEvents);
|
||||||
if (useReftable) {
|
if (useReftable) {
|
||||||
// reftable retains reflog entries for deleted branches.
|
// reftable retains reflog entries for deleted branches.
|
||||||
assertReflogEquals(
|
assertReflogEquals(
|
||||||
|
@ -551,6 +683,7 @@ public void reflogDelete() throws IOException {
|
||||||
@Test
|
@Test
|
||||||
public void reflogFileDirectoryConflict() throws IOException {
|
public void reflogFileDirectoryConflict() throws IOException {
|
||||||
writeRef("refs/heads/master", A);
|
writeRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
List<ReceiveCommand> cmds = Arrays.asList(
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
new ReceiveCommand(A, zeroId(), "refs/heads/master", DELETE),
|
new ReceiveCommand(A, zeroId(), "refs/heads/master", DELETE),
|
||||||
|
@ -559,7 +692,8 @@ public void reflogFileDirectoryConflict() throws IOException {
|
||||||
|
|
||||||
assertResults(cmds, OK, OK);
|
assertResults(cmds, OK, OK);
|
||||||
assertRefs("refs/heads/master/x", A);
|
assertRefs("refs/heads/master/x", A);
|
||||||
assertEquals(batchesRefUpdates() ? 2 : 3, refsChangedEvents);
|
assertEquals(batchesRefUpdates() ? initialRefsChangedEvents + 1
|
||||||
|
: initialRefsChangedEvents + 2, refsChangedEvents);
|
||||||
if (!useReftable) {
|
if (!useReftable) {
|
||||||
// reftable retains reflog entries for deleted branches.
|
// reftable retains reflog entries for deleted branches.
|
||||||
assertNull(getLastReflog("refs/heads/master"));
|
assertNull(getLastReflog("refs/heads/master"));
|
||||||
|
@ -572,6 +706,7 @@ public void reflogFileDirectoryConflict() throws IOException {
|
||||||
@Test
|
@Test
|
||||||
public void reflogOnLockFailure() throws IOException {
|
public void reflogOnLockFailure() throws IOException {
|
||||||
writeRef("refs/heads/master", A);
|
writeRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
Map<String, ReflogEntry> oldLogs = getLastReflogs("refs/heads/master",
|
Map<String, ReflogEntry> oldLogs = getLastReflogs("refs/heads/master",
|
||||||
"refs/heads/branch");
|
"refs/heads/branch");
|
||||||
|
@ -583,12 +718,12 @@ public void reflogOnLockFailure() throws IOException {
|
||||||
|
|
||||||
if (atomic) {
|
if (atomic) {
|
||||||
assertResults(cmds, TRANSACTION_ABORTED, LOCK_FAILURE);
|
assertResults(cmds, TRANSACTION_ABORTED, LOCK_FAILURE);
|
||||||
assertEquals(1, refsChangedEvents);
|
assertEquals(initialRefsChangedEvents, refsChangedEvents);
|
||||||
assertReflogUnchanged(oldLogs, "refs/heads/master");
|
assertReflogUnchanged(oldLogs, "refs/heads/master");
|
||||||
assertReflogUnchanged(oldLogs, "refs/heads/branch");
|
assertReflogUnchanged(oldLogs, "refs/heads/branch");
|
||||||
} else {
|
} else {
|
||||||
assertResults(cmds, OK, LOCK_FAILURE);
|
assertResults(cmds, OK, LOCK_FAILURE);
|
||||||
assertEquals(2, refsChangedEvents);
|
assertEquals(initialRefsChangedEvents + 1, refsChangedEvents);
|
||||||
assertReflogEquals(
|
assertReflogEquals(
|
||||||
reflog(A, B, new PersonIdent(diskRepo), "a reflog"),
|
reflog(A, B, new PersonIdent(diskRepo), "a reflog"),
|
||||||
getLastReflog("refs/heads/master"));
|
getLastReflog("refs/heads/master"));
|
||||||
|
@ -599,6 +734,7 @@ public void reflogOnLockFailure() throws IOException {
|
||||||
@Test
|
@Test
|
||||||
public void overrideRefLogMessage() throws Exception {
|
public void overrideRefLogMessage() throws Exception {
|
||||||
writeRef("refs/heads/master", A);
|
writeRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
List<ReceiveCommand> cmds = Arrays.asList(
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
||||||
|
@ -609,7 +745,8 @@ public void overrideRefLogMessage() throws Exception {
|
||||||
.setRefLogMessage("a reflog", true));
|
.setRefLogMessage("a reflog", true));
|
||||||
|
|
||||||
assertResults(cmds, OK, OK);
|
assertResults(cmds, OK, OK);
|
||||||
assertEquals(batchesRefUpdates() ? 2 : 3, refsChangedEvents);
|
assertEquals(batchesRefUpdates() ? initialRefsChangedEvents + 1
|
||||||
|
: initialRefsChangedEvents + 2, refsChangedEvents);
|
||||||
assertReflogEquals(reflog(A, B, ident, "custom log"),
|
assertReflogEquals(reflog(A, B, ident, "custom log"),
|
||||||
getLastReflog("refs/heads/master"), true);
|
getLastReflog("refs/heads/master"), true);
|
||||||
assertReflogEquals(reflog(zeroId(), B, ident, "a reflog: created"),
|
assertReflogEquals(reflog(zeroId(), B, ident, "a reflog: created"),
|
||||||
|
@ -619,6 +756,7 @@ public void overrideRefLogMessage() throws Exception {
|
||||||
@Test
|
@Test
|
||||||
public void overrideDisableRefLog() throws Exception {
|
public void overrideDisableRefLog() throws Exception {
|
||||||
writeRef("refs/heads/master", A);
|
writeRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
Map<String, ReflogEntry> oldLogs = getLastReflogs("refs/heads/master",
|
Map<String, ReflogEntry> oldLogs = getLastReflogs("refs/heads/master",
|
||||||
"refs/heads/branch");
|
"refs/heads/branch");
|
||||||
|
@ -630,7 +768,8 @@ public void overrideDisableRefLog() throws Exception {
|
||||||
execute(newBatchUpdate(cmds).setRefLogMessage("a reflog", true));
|
execute(newBatchUpdate(cmds).setRefLogMessage("a reflog", true));
|
||||||
|
|
||||||
assertResults(cmds, OK, OK);
|
assertResults(cmds, OK, OK);
|
||||||
assertEquals(batchesRefUpdates() ? 2 : 3, refsChangedEvents);
|
assertEquals(batchesRefUpdates() ? initialRefsChangedEvents + 1
|
||||||
|
: initialRefsChangedEvents + 2, refsChangedEvents);
|
||||||
assertReflogUnchanged(oldLogs, "refs/heads/master");
|
assertReflogUnchanged(oldLogs, "refs/heads/master");
|
||||||
assertReflogEquals(
|
assertReflogEquals(
|
||||||
reflog(zeroId(), B, new PersonIdent(diskRepo),
|
reflog(zeroId(), B, new PersonIdent(diskRepo),
|
||||||
|
@ -641,6 +780,7 @@ public void overrideDisableRefLog() throws Exception {
|
||||||
@Test
|
@Test
|
||||||
public void refLogNotWrittenWithoutConfigOption() throws Exception {
|
public void refLogNotWrittenWithoutConfigOption() throws Exception {
|
||||||
assumeFalse(useReftable);
|
assumeFalse(useReftable);
|
||||||
|
|
||||||
setLogAllRefUpdates(false);
|
setLogAllRefUpdates(false);
|
||||||
writeRef("refs/heads/master", A);
|
writeRef("refs/heads/master", A);
|
||||||
|
|
||||||
|
@ -661,6 +801,7 @@ public void refLogNotWrittenWithoutConfigOption() throws Exception {
|
||||||
@Test
|
@Test
|
||||||
public void forceRefLogInUpdate() throws Exception {
|
public void forceRefLogInUpdate() throws Exception {
|
||||||
assumeFalse(useReftable);
|
assumeFalse(useReftable);
|
||||||
|
|
||||||
setLogAllRefUpdates(false);
|
setLogAllRefUpdates(false);
|
||||||
writeRef("refs/heads/master", A);
|
writeRef("refs/heads/master", A);
|
||||||
assertTrue(getLastReflogs("refs/heads/master", "refs/heads/branch")
|
assertTrue(getLastReflogs("refs/heads/master", "refs/heads/branch")
|
||||||
|
@ -683,6 +824,7 @@ public void forceRefLogInUpdate() throws Exception {
|
||||||
@Test
|
@Test
|
||||||
public void forceRefLogInCommand() throws Exception {
|
public void forceRefLogInCommand() throws Exception {
|
||||||
assumeFalse(useReftable);
|
assumeFalse(useReftable);
|
||||||
|
|
||||||
setLogAllRefUpdates(false);
|
setLogAllRefUpdates(false);
|
||||||
writeRef("refs/heads/master", A);
|
writeRef("refs/heads/master", A);
|
||||||
|
|
||||||
|
@ -723,19 +865,39 @@ public void packedRefsLockFailure() throws Exception {
|
||||||
if (atomic) {
|
if (atomic) {
|
||||||
assertResults(cmds, LOCK_FAILURE, TRANSACTION_ABORTED);
|
assertResults(cmds, LOCK_FAILURE, TRANSACTION_ABORTED);
|
||||||
assertRefs("refs/heads/master", A);
|
assertRefs("refs/heads/master", A);
|
||||||
assertEquals(1, refsChangedEvents);
|
|
||||||
} else {
|
} else {
|
||||||
// Only operates on loose refs, doesn't care that packed-refs is
|
// Only operates on loose refs, doesn't care that packed-refs is
|
||||||
// locked.
|
// locked.
|
||||||
assertResults(cmds, OK, OK);
|
assertResults(cmds, OK, OK);
|
||||||
assertRefs("refs/heads/master", B, "refs/heads/branch", B);
|
assertRefs("refs/heads/master", B, "refs/heads/branch", B);
|
||||||
assertEquals(3, refsChangedEvents);
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
myLock.unlock();
|
myLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void packedRefsLockFailureRefsChangedEvents() throws Exception {
|
||||||
|
assumeFalse(useReftable);
|
||||||
|
|
||||||
|
writeLooseRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
|
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
||||||
|
new ReceiveCommand(zeroId(), B, "refs/heads/branch", CREATE));
|
||||||
|
|
||||||
|
LockFile myLock = refdir.lockPackedRefs();
|
||||||
|
try {
|
||||||
|
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));
|
||||||
|
|
||||||
|
assertEquals(atomic ? initialRefsChangedEvents
|
||||||
|
: initialRefsChangedEvents + 2, refsChangedEvents);
|
||||||
|
} finally {
|
||||||
|
myLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void oneRefLockFailure() throws Exception {
|
public void oneRefLockFailure() throws Exception {
|
||||||
assumeFalse(useReftable);
|
assumeFalse(useReftable);
|
||||||
|
@ -757,20 +919,42 @@ public void oneRefLockFailure() throws Exception {
|
||||||
if (atomic) {
|
if (atomic) {
|
||||||
assertResults(cmds, TRANSACTION_ABORTED, LOCK_FAILURE);
|
assertResults(cmds, TRANSACTION_ABORTED, LOCK_FAILURE);
|
||||||
assertRefs("refs/heads/master", A);
|
assertRefs("refs/heads/master", A);
|
||||||
assertEquals(1, refsChangedEvents);
|
|
||||||
} else {
|
} else {
|
||||||
assertResults(cmds, OK, LOCK_FAILURE);
|
assertResults(cmds, OK, LOCK_FAILURE);
|
||||||
assertRefs("refs/heads/branch", B, "refs/heads/master", A);
|
assertRefs("refs/heads/branch", B, "refs/heads/master", A);
|
||||||
assertEquals(2, refsChangedEvents);
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
myLock.unlock();
|
myLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void oneRefLockFailureRefsChangedEvents() throws Exception {
|
||||||
|
assumeFalse(useReftable);
|
||||||
|
|
||||||
|
writeLooseRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
|
new ReceiveCommand(zeroId(), B, "refs/heads/branch", CREATE),
|
||||||
|
new ReceiveCommand(A, B, "refs/heads/master", UPDATE));
|
||||||
|
|
||||||
|
LockFile myLock = new LockFile(refdir.fileFor("refs/heads/master"));
|
||||||
|
assertTrue(myLock.lock());
|
||||||
|
try {
|
||||||
|
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));
|
||||||
|
|
||||||
|
assertEquals(atomic ? initialRefsChangedEvents
|
||||||
|
: initialRefsChangedEvents + 1, refsChangedEvents);
|
||||||
|
} finally {
|
||||||
|
myLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void singleRefUpdateDoesNotRequirePackedRefsLock() throws Exception {
|
public void singleRefUpdateDoesNotRequirePackedRefsLock() throws Exception {
|
||||||
assumeFalse(useReftable);
|
assumeFalse(useReftable);
|
||||||
|
|
||||||
writeLooseRef("refs/heads/master", A);
|
writeLooseRef("refs/heads/master", A);
|
||||||
|
|
||||||
List<ReceiveCommand> cmds = Arrays
|
List<ReceiveCommand> cmds = Arrays
|
||||||
|
@ -782,13 +966,33 @@ public void singleRefUpdateDoesNotRequirePackedRefsLock() throws Exception {
|
||||||
|
|
||||||
assertFalse(getLockFile("refs/heads/master").exists());
|
assertFalse(getLockFile("refs/heads/master").exists());
|
||||||
assertResults(cmds, OK);
|
assertResults(cmds, OK);
|
||||||
assertEquals(2, refsChangedEvents);
|
|
||||||
assertRefs("refs/heads/master", B);
|
assertRefs("refs/heads/master", B);
|
||||||
} finally {
|
} finally {
|
||||||
myLock.unlock();
|
myLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void singleRefUpdateDoesNotRequirePackedRefsLockRefsChangedEvents()
|
||||||
|
throws Exception {
|
||||||
|
assumeFalse(useReftable);
|
||||||
|
|
||||||
|
writeLooseRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
|
List<ReceiveCommand> cmds = Arrays
|
||||||
|
.asList(new ReceiveCommand(A, B, "refs/heads/master", UPDATE));
|
||||||
|
|
||||||
|
LockFile myLock = refdir.lockPackedRefs();
|
||||||
|
try {
|
||||||
|
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));
|
||||||
|
|
||||||
|
assertEquals(initialRefsChangedEvents + 1, refsChangedEvents);
|
||||||
|
} finally {
|
||||||
|
myLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void atomicUpdateRespectsInProcessLock() throws Exception {
|
public void atomicUpdateRespectsInProcessLock() throws Exception {
|
||||||
assumeTrue(atomic);
|
assumeTrue(atomic);
|
||||||
|
@ -838,10 +1042,56 @@ public void atomicUpdateRespectsInProcessLock() throws Exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
assertResults(cmds, OK, OK);
|
assertResults(cmds, OK, OK);
|
||||||
assertEquals(2, refsChangedEvents);
|
|
||||||
assertRefs("refs/heads/master", B, "refs/heads/branch", B);
|
assertRefs("refs/heads/master", B, "refs/heads/branch", B);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void atomicUpdateRespectsInProcessLockRefsChangedEvents()
|
||||||
|
throws Exception {
|
||||||
|
assumeTrue(atomic);
|
||||||
|
assumeFalse(useReftable);
|
||||||
|
|
||||||
|
writeLooseRef("refs/heads/master", A);
|
||||||
|
int initialRefsChangedEvents = refsChangedEvents;
|
||||||
|
|
||||||
|
List<ReceiveCommand> cmds = Arrays.asList(
|
||||||
|
new ReceiveCommand(A, B, "refs/heads/master", UPDATE),
|
||||||
|
new ReceiveCommand(zeroId(), B, "refs/heads/branch", CREATE));
|
||||||
|
|
||||||
|
Thread t = new Thread(() -> {
|
||||||
|
try {
|
||||||
|
execute(newBatchUpdate(cmds).setAllowNonFastForwards(true));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ReentrantLock l = refdir.inProcessPackedRefsLock;
|
||||||
|
l.lock();
|
||||||
|
try {
|
||||||
|
t.start();
|
||||||
|
long timeoutSecs = 10;
|
||||||
|
|
||||||
|
// Hold onto the lock until we observe the worker thread has
|
||||||
|
// attempted to
|
||||||
|
// acquire it.
|
||||||
|
while (l.getQueueLength() == 0) {
|
||||||
|
Thread.sleep(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once we unlock, the worker thread should finish the update
|
||||||
|
// promptly.
|
||||||
|
l.unlock();
|
||||||
|
t.join(SECONDS.toMillis(timeoutSecs));
|
||||||
|
} finally {
|
||||||
|
if (l.isHeldByCurrentThread()) {
|
||||||
|
l.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(initialRefsChangedEvents + 1, refsChangedEvents);
|
||||||
|
}
|
||||||
|
|
||||||
private void setLogAllRefUpdates(boolean enable) throws Exception {
|
private void setLogAllRefUpdates(boolean enable) throws Exception {
|
||||||
StoredConfig cfg = diskRepo.getConfig();
|
StoredConfig cfg = diskRepo.getConfig();
|
||||||
cfg.load();
|
cfg.load();
|
||||||
|
@ -855,6 +1105,11 @@ private void writeLooseRef(String name, AnyObjectId id) throws IOException {
|
||||||
writeRef(name, id);
|
writeRef(name, id);
|
||||||
} else {
|
} else {
|
||||||
write(new File(diskRepo.getDirectory(), name), id.name() + "\n");
|
write(new File(diskRepo.getDirectory(), name), id.name() + "\n");
|
||||||
|
// force the refs-changed event to be fired for the loose ref that
|
||||||
|
// was created. We do this to get the events fired during the test
|
||||||
|
// 'setup' out of the way and this allows us to now accurately
|
||||||
|
// assert only for the new events fired during the BatchRefUpdate.
|
||||||
|
refdir.exactRef(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -957,11 +1212,11 @@ private void assertRefs(Object... args) throws IOException {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Result {
|
enum Result {
|
||||||
OK(ReceiveCommand.Result.OK), LOCK_FAILURE(
|
OK(ReceiveCommand.Result.OK),
|
||||||
ReceiveCommand.Result.LOCK_FAILURE), REJECTED_NONFASTFORWARD(
|
LOCK_FAILURE(ReceiveCommand.Result.LOCK_FAILURE),
|
||||||
ReceiveCommand.Result.REJECTED_NONFASTFORWARD), REJECTED_MISSING_OBJECT(
|
REJECTED_NONFASTFORWARD(ReceiveCommand.Result.REJECTED_NONFASTFORWARD),
|
||||||
ReceiveCommand.Result.REJECTED_MISSING_OBJECT), TRANSACTION_ABORTED(
|
REJECTED_MISSING_OBJECT(ReceiveCommand.Result.REJECTED_MISSING_OBJECT),
|
||||||
ReceiveCommand::isTransactionAborted);
|
TRANSACTION_ABORTED(ReceiveCommand::isTransactionAborted);
|
||||||
|
|
||||||
@SuppressWarnings("ImmutableEnumChecker")
|
@SuppressWarnings("ImmutableEnumChecker")
|
||||||
final Predicate<? super ReceiveCommand> p;
|
final Predicate<? super ReceiveCommand> p;
|
||||||
|
|
|
@ -244,47 +244,18 @@ public void refresh() {
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public boolean isNameConflicting(String name) throws IOException {
|
public boolean isNameConflicting(String name) throws IOException {
|
||||||
RefList<Ref> packed = getPackedRefs();
|
|
||||||
RefList<LooseRef> loose = getLooseRefs();
|
|
||||||
|
|
||||||
// Cannot be nested within an existing reference.
|
// Cannot be nested within an existing reference.
|
||||||
int lastSlash = name.lastIndexOf('/');
|
int lastSlash = name.lastIndexOf('/');
|
||||||
while (0 < lastSlash) {
|
while (0 < lastSlash) {
|
||||||
String needle = name.substring(0, lastSlash);
|
String needle = name.substring(0, lastSlash);
|
||||||
if (loose.contains(needle) || packed.contains(needle))
|
if (exactRef(needle) != null) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
lastSlash = name.lastIndexOf('/', lastSlash - 1);
|
lastSlash = name.lastIndexOf('/', lastSlash - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cannot be the container of an existing reference.
|
// Cannot be the container of an existing reference.
|
||||||
String prefix = name + '/';
|
return !getRefsByPrefix(name + '/').isEmpty();
|
||||||
int idx;
|
|
||||||
|
|
||||||
idx = -(packed.find(prefix) + 1);
|
|
||||||
if (idx < packed.size() && packed.get(idx).getName().startsWith(prefix))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
idx = -(loose.find(prefix) + 1);
|
|
||||||
if (idx < loose.size() && loose.get(idx).getName().startsWith(prefix))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private RefList<LooseRef> getLooseRefs() {
|
|
||||||
final RefList<LooseRef> oldLoose = looseRefs.get();
|
|
||||||
|
|
||||||
LooseScanner scan = new LooseScanner(oldLoose);
|
|
||||||
scan.scan(ALL);
|
|
||||||
|
|
||||||
RefList<LooseRef> loose;
|
|
||||||
if (scan.newLoose != null) {
|
|
||||||
loose = scan.newLoose.toRefList();
|
|
||||||
if (looseRefs.compareAndSet(oldLoose, loose))
|
|
||||||
modCnt.incrementAndGet();
|
|
||||||
} else
|
|
||||||
loose = oldLoose;
|
|
||||||
return loose;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
|
|
||||||
import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED;
|
import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED;
|
||||||
import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_OTHER_REASON;
|
import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_OTHER_REASON;
|
||||||
import static java.util.stream.Collectors.toCollection;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
@ -29,7 +28,6 @@
|
||||||
import org.eclipse.jgit.annotations.Nullable;
|
import org.eclipse.jgit.annotations.Nullable;
|
||||||
import org.eclipse.jgit.errors.MissingObjectException;
|
import org.eclipse.jgit.errors.MissingObjectException;
|
||||||
import org.eclipse.jgit.internal.JGitText;
|
import org.eclipse.jgit.internal.JGitText;
|
||||||
import org.eclipse.jgit.lib.RefUpdate.Result;
|
|
||||||
import org.eclipse.jgit.revwalk.RevWalk;
|
import org.eclipse.jgit.revwalk.RevWalk;
|
||||||
import org.eclipse.jgit.transport.PushCertificate;
|
import org.eclipse.jgit.transport.PushCertificate;
|
||||||
import org.eclipse.jgit.transport.ReceiveCommand;
|
import org.eclipse.jgit.transport.ReceiveCommand;
|
||||||
|
@ -495,42 +493,24 @@ public void execute(RevWalk walk, ProgressMonitor monitor,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!commands2.isEmpty()) {
|
if (!commands2.isEmpty()) {
|
||||||
// What part of the name space is already taken
|
// Perform updates that may require more room in the name space
|
||||||
Collection<String> takenNames = refdb.getRefs().stream()
|
|
||||||
.map(Ref::getName)
|
|
||||||
.collect(toCollection(HashSet::new));
|
|
||||||
Collection<String> takenPrefixes = getTakenPrefixes(takenNames);
|
|
||||||
|
|
||||||
// Now to the update that may require more room in the name space
|
|
||||||
for (ReceiveCommand cmd : commands2) {
|
for (ReceiveCommand cmd : commands2) {
|
||||||
try {
|
try {
|
||||||
if (cmd.getResult() == NOT_ATTEMPTED) {
|
if (cmd.getResult() == NOT_ATTEMPTED) {
|
||||||
cmd.updateType(walk);
|
cmd.updateType(walk);
|
||||||
RefUpdate ru = newUpdate(cmd);
|
RefUpdate ru = newUpdate(cmd);
|
||||||
SWITCH: switch (cmd.getType()) {
|
switch (cmd.getType()) {
|
||||||
case DELETE:
|
case DELETE:
|
||||||
// Performed in the first phase
|
// Performed in the first phase
|
||||||
break;
|
break;
|
||||||
case UPDATE:
|
case UPDATE:
|
||||||
case UPDATE_NONFASTFORWARD:
|
case UPDATE_NONFASTFORWARD:
|
||||||
RefUpdate ruu = newUpdate(cmd);
|
RefUpdate ruu = newUpdate(cmd);
|
||||||
cmd.setResult(ruu.update(walk));
|
cmd.setResult(ruu.update(walk));
|
||||||
break;
|
break;
|
||||||
case CREATE:
|
case CREATE:
|
||||||
for (String prefix : getPrefixes(cmd.getRefName())) {
|
cmd.setResult(ru.update(walk));
|
||||||
if (takenNames.contains(prefix)) {
|
break;
|
||||||
cmd.setResult(Result.LOCK_FAILURE);
|
|
||||||
break SWITCH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (takenPrefixes.contains(cmd.getRefName())) {
|
|
||||||
cmd.setResult(Result.LOCK_FAILURE);
|
|
||||||
break SWITCH;
|
|
||||||
}
|
|
||||||
ru.setCheckConflicting(false);
|
|
||||||
takenPrefixes.addAll(getPrefixes(cmd.getRefName()));
|
|
||||||
takenNames.add(cmd.getRefName());
|
|
||||||
cmd.setResult(ru.update(walk));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException err) {
|
} catch (IOException err) {
|
||||||
|
@ -602,14 +582,6 @@ public void execute(RevWalk walk, ProgressMonitor monitor)
|
||||||
execute(walk, monitor, null);
|
execute(walk, monitor, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Collection<String> getTakenPrefixes(Collection<String> names) {
|
|
||||||
Collection<String> ref = new HashSet<>();
|
|
||||||
for (String name : names) {
|
|
||||||
addPrefixesTo(name, ref);
|
|
||||||
}
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all path prefixes of a ref name.
|
* Get all path prefixes of a ref name.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue