BatchUpdate: Support chaining ReceiveCommands on the same ref
This is not natively supported by BatchRefUpdate: if multiple commands for the same ref are added to a batch, the behavior is undefined. To support this, buffer commands in a temporary object, and ensure the old and new IDs line up. Change-Id: I60a55fa3ca9106dbadc1d3a1546bf1ee5c6fe37b
This commit is contained in:
@@ -49,6 +49,7 @@ import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
@@ -146,16 +147,8 @@ public class BatchUpdate implements AutoCloseable {
|
||||
return BatchUpdate.this.getObjectInserter();
|
||||
}
|
||||
|
||||
private BatchRefUpdate getBatchRefUpdate() throws IOException {
|
||||
initRepository();
|
||||
if (batchRefUpdate == null) {
|
||||
batchRefUpdate = repo.getRefDatabase().newBatchUpdate();
|
||||
}
|
||||
return batchRefUpdate;
|
||||
}
|
||||
|
||||
public void addRefUpdate(ReceiveCommand cmd) throws IOException {
|
||||
getBatchRefUpdate().addCommand(cmd);
|
||||
public void addRefUpdate(ReceiveCommand cmd) {
|
||||
commands.add(cmd);
|
||||
}
|
||||
|
||||
public TimeZone getTimeZone() {
|
||||
@@ -213,6 +206,40 @@ public class BatchUpdate implements AutoCloseable {
|
||||
public abstract Change getChange();
|
||||
}
|
||||
|
||||
private static class ChainedReceiveCommands {
|
||||
private final Map<String, ReceiveCommand> commands = new LinkedHashMap<>();
|
||||
|
||||
private boolean isEmpty() {
|
||||
return commands.isEmpty();
|
||||
}
|
||||
|
||||
private void add(ReceiveCommand cmd) {
|
||||
checkArgument(!cmd.getOldId().equals(cmd.getNewId()),
|
||||
"ref update is a no-op: %s", cmd);
|
||||
ReceiveCommand old = commands.get(cmd.getRefName());
|
||||
if (old == null) {
|
||||
commands.put(cmd.getRefName(), cmd);
|
||||
return;
|
||||
}
|
||||
checkArgument(old.getResult() == ReceiveCommand.Result.NOT_ATTEMPTED,
|
||||
"cannot chain ref update %s after update %s with result %s",
|
||||
cmd, old, old.getResult());
|
||||
checkArgument(cmd.getOldId().equals(old.getNewId()),
|
||||
"cannot chain ref update %s after update %s with different new ID",
|
||||
cmd, old);
|
||||
commands.put(cmd.getRefName(), new ReceiveCommand(
|
||||
old.getOldId(), cmd.getNewId(), cmd.getRefName()));
|
||||
}
|
||||
|
||||
private void addTo(BatchRefUpdate bru) {
|
||||
checkState(!isEmpty(), "no commands to add");
|
||||
for (ReceiveCommand cmd : commands.values()) {
|
||||
bru.addCommand(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final ReviewDb db;
|
||||
private final GitRepositoryManager repoManager;
|
||||
private final ChangeIndexer indexer;
|
||||
@@ -233,6 +260,7 @@ public class BatchUpdate implements AutoCloseable {
|
||||
private Repository repo;
|
||||
private ObjectInserter inserter;
|
||||
private RevWalk revWalk;
|
||||
private ChainedReceiveCommands commands = new ChainedReceiveCommands();
|
||||
private BatchRefUpdate batchRefUpdate;
|
||||
private boolean closeRepo;
|
||||
private Order order;
|
||||
@@ -376,11 +404,14 @@ public class BatchUpdate implements AutoCloseable {
|
||||
throw new UpdateException(e);
|
||||
}
|
||||
|
||||
if (repo == null || batchRefUpdate == null
|
||||
|| batchRefUpdate.getCommands().isEmpty()) {
|
||||
if (commands.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// May not be opened if the caller added ref updates but no new objects.
|
||||
initRepository();
|
||||
inserter.flush();
|
||||
batchRefUpdate = repo.getRefDatabase().newBatchUpdate();
|
||||
commands.addTo(batchRefUpdate);
|
||||
batchRefUpdate.execute(revWalk, NullProgressMonitor.INSTANCE);
|
||||
boolean ok = true;
|
||||
for (ReceiveCommand cmd : batchRefUpdate.getCommands()) {
|
||||
|
||||
Reference in New Issue
Block a user