PushCertificateStore: Add method to save in batch
Change-Id: I8bfaee1a52d368ffe2cd7e8af1754a5261569078
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateStoreTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateStoreTest.java
index d2faaa7..77a0708 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateStoreTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushCertificateStoreTest.java
@@ -60,7 +60,9 @@
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -271,6 +273,26 @@ public void lockFailure() throws Exception {
assertCerts(store2, "refs/heads/branch", addBranch);
}
+ @Test
+ public void saveInBatch() throws Exception {
+ BatchRefUpdate batch = repo.getRefDatabase().newBatchUpdate();
+ PushCertificate addMaster = newCert(
+ command(zeroId(), ID1, "refs/heads/master"));
+ store.put(addMaster, newIdent());
+ store.save(batch);
+
+ List<ReceiveCommand> commands = batch.getCommands();
+ assertEquals(1, commands.size());
+ ReceiveCommand cmd = commands.get(0);
+
+ try (RevWalk rw = new RevWalk(repo)) {
+ assertEquals("refs/meta/push-certs", cmd.getRefName());
+ assertEquals(ReceiveCommand.Result.NOT_ATTEMPTED, cmd.getResult());
+ batch.execute(rw, NullProgressMonitor.INSTANCE);
+ assertEquals(ReceiveCommand.Result.OK, cmd.getResult());
+ }
+ }
+
private PersonIdent newIdent() {
return new PersonIdent(
"A U. Thor", "author@example.com", ts.getAndIncrement(), 0);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateStore.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateStore.java
index 94677f9..4334620 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateStore.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PushCertificateStore.java
@@ -67,6 +67,7 @@
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
@@ -326,9 +327,64 @@ public void put(PushCertificate cert, PersonIdent ident) {
* repository.
*/
public RefUpdate.Result save() throws IOException {
- if (pending.isEmpty()) {
+ ObjectId newId = write();
+ if (newId == null) {
return RefUpdate.Result.NO_CHANGE;
}
+ try (ObjectInserter inserter = db.newObjectInserter()) {
+ RefUpdate.Result result = updateRef(newId);
+ switch (result) {
+ case FAST_FORWARD:
+ case NEW:
+ case NO_CHANGE:
+ pending.clear();
+ break;
+ default:
+ break;
+ }
+ return result;
+ } finally {
+ close();
+ }
+ }
+
+ /**
+ * Save pending certificates to the store in an existing batch ref update.
+ * <p>
+ * One commit is created per certificate added with {@link
+ * #put(PushCertificate, PersonIdent)}, in order of identity timestamps, all
+ * commits are flushed, and a single command is added to the batch.
+ * <p>
+ * The pending list is <em>not</em> cleared. If the ref update succeeds, the
+ * caller is responsible for calling {@link #clear()}.
+ *
+ * @param batch
+ * update to save to.
+ * @throws IOException
+ * if there was an error reading from or writing to the
+ * repository.
+ */
+ public void save(BatchRefUpdate batch) throws IOException {
+ ObjectId newId = write();
+ if (newId == null) {
+ return;
+ }
+ batch.addCommand(new ReceiveCommand(
+ commit != null ? commit : ObjectId.zeroId(), newId, REF_NAME));
+ }
+
+ /**
+ * Clear pending certificates added with {@link #put(PushCertificate,
+ * PersonIdent)}.
+ */
+ public void clear() {
+ pending.clear();
+ }
+
+ private ObjectId write() throws IOException {
+ if (pending.isEmpty()) {
+ return null;
+ }
if (reader == null) {
load();
}
@@ -341,19 +397,7 @@ public RefUpdate.Result save() throws IOException {
curr = saveCert(inserter, dc, pc, curr);
}
inserter.flush();
- RefUpdate.Result result = updateRef(curr);
- switch (result) {
- case FAST_FORWARD:
- case NEW:
- case NO_CHANGE:
- pending.clear();
- break;
- default:
- break;
- }
- return result;
- } finally {
- close();
+ return curr;
}
}