Notedb: Store patch set push certificates in notes
Unlike other fields, push certificates have a predefined format that includes newlines, so they are not particularly appropriate to store in a single "Key: Value" footer. Moreover, we already reserve the body of the meta commit message for ChangeMessages. Sidestep any ambiguity by storing push certificates in the note for the revision. Optionally parse a push certificate as the first thing in the note file, before any inline comments. Change-Id: Ia8c0674f3b40f6ec100cc9fac8ffec671833774b
This commit is contained in:
@@ -14,27 +14,63 @@
|
||||
|
||||
package com.google.gerrit.server.notedb;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.PatchLineComment;
|
||||
|
||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectReader;
|
||||
import org.eclipse.jgit.util.MutableInteger;
|
||||
import org.eclipse.jgit.util.RawParseUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
class RevisionNote {
|
||||
static final int MAX_NOTE_SZ = 25 << 20;
|
||||
|
||||
private static final byte[] CERT_HEADER =
|
||||
"certificate version ".getBytes(UTF_8);
|
||||
// See org.eclipse.jgit.transport.PushCertificateParser.END_SIGNATURE
|
||||
private static final byte[] END_SIGNATURE =
|
||||
"-----END PGP SIGNATURE-----".getBytes(UTF_8);
|
||||
|
||||
private static void trimLeadingEmptyLines(byte[] bytes, MutableInteger p) {
|
||||
while (p.value < bytes.length && bytes[p.value] == '\n') {
|
||||
p.value++;
|
||||
}
|
||||
}
|
||||
|
||||
private static String parsePushCert(Change.Id changeId, byte[] bytes,
|
||||
MutableInteger p) throws ConfigInvalidException {
|
||||
if (RawParseUtils.match(bytes, p.value, CERT_HEADER) < 0) {
|
||||
return null;
|
||||
}
|
||||
int end = Bytes.indexOf(bytes, END_SIGNATURE);
|
||||
if (end < 0) {
|
||||
throw ChangeNotes.parseException(
|
||||
changeId, "invalid push certificate in note");
|
||||
}
|
||||
int start = p.value;
|
||||
p.value = end + END_SIGNATURE.length;
|
||||
return new String(bytes, start, p.value);
|
||||
}
|
||||
|
||||
final ImmutableList<PatchLineComment> comments;
|
||||
final String pushCert;
|
||||
|
||||
RevisionNote(Change.Id changeId, ObjectReader reader, ObjectId noteId)
|
||||
throws ConfigInvalidException, IOException {
|
||||
byte[] bytes = reader.open(noteId, OBJ_BLOB).getCachedBytes(MAX_NOTE_SZ);
|
||||
MutableInteger p = new MutableInteger();
|
||||
trimLeadingEmptyLines(bytes, p);
|
||||
pushCert = parsePushCert(changeId, bytes, p);
|
||||
trimLeadingEmptyLines(bytes, p);
|
||||
comments = ImmutableList.copyOf(CommentsInNotesUtil.parseNote(
|
||||
bytes, changeId, PatchLineComment.Status.PUBLISHED));
|
||||
bytes, p, changeId, PatchLineComment.Status.PUBLISHED));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user