Store PatchSetApprovals in a git-notes-based database
Add a new ref namespace refs/changes/*/*/meta for storing the state of a Gerrit change in Git. Information about the change is mostly stored in commit messages, the entire history of which are read at load time to populate information about the change. Eventually, information tied to a particular patch set will be stored in a git note referring to the patch set's commit. This data format only allows fast access to data on a per-change basis. Lookups by other keys (e.g. approvals by user) will depend on the secondary index. The commit message format is simple: Update patch set 1 <optional cover message> Patch-Set: 1 Label: Code-Review=+1 The subject line is machine-generated and callers should attempt to make it descriptive, but this is not strictly required. The cover message is user-provided (not implemented in this change). At least the Patch-Set footer line is required for the time being; it is likely we will want to enforce there always being at least one footer to fend off user-provided cover messages that themselves contains footers. The author of the commit is the end-user performing the update, using their full name and email address. The committer is the same user, but includes the Gerrit account ID in the email address for disambiguation. (Eventually, we may decide that the (name, email) combination is enough to uniquely identify a user, but for now we still require the account ID.) On the code side, reading and writing changes from this ref is implemented with two VersionedMetaData classes: ChangeNotes implements the read operation. When a ChangeNotes is loaded, it traverses the entire history of the ref and populates the object with all relevant information. Traversing the entire history should be a fast operation on most changes, which typically have roughly tens of operations. ChangeUpdate implements the write operation. Unlike the traditional database, where operations are organized around read-modify-write operations on various entities spread across tables, a ChangeUpdate encapsulates a set of updates that can be applied atomically. Because each commit has a single author, timestamp, and patch set, these are logically restricted to operations performed by a single user on a single patch set. This corresponds better to the typical usage of the database, where a single end-user is performing an operation on a single change via a REST endpoint. ChangeNotes and ChangeUpdate are separate VersionedMetaData subclasses for a few reasons, mostly technical. First, it should not be necessary in all cases to slurp all change data via ChangeNotes before preparing a ChangeUpdate. Second, due to subtleties like LabelType sorting, it would be tricky to make ChangeNotes mutable in such a way that the result of reading it after one or more mutations would be the same as if that change were read freshly from the git data. Keeping ChangeNotes immutable and ChangeUpdate separate makes it less tempting to assume this behavior. This change implements only reading/writing for ChangeNotes/ChangeUpdate; they are not yet used in any read/write code paths in the server. Change-Id: Id28978a92f3b197c8b5be6e2db0c1e3923f2211e
This commit is contained in:
@@ -213,7 +213,7 @@ public abstract class VersionedMetaData {
|
||||
doSave(config, commit);
|
||||
|
||||
final ObjectId res = newTree.writeTree(inserter);
|
||||
if (res.equals(srcTree)) {
|
||||
if (res.equals(srcTree) && !update.allowEmpty()) {
|
||||
// If there are no changes to the content, don't create the commit.
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user