ExportReviewNotes: Load changes from notedb if enabled Make sure that change notes are created only once. Change-Id: Ie9b936cbedc333c0d7697af706900187a34e7060 Signed-off-by: Edwin Kempin <ekempin@google.com>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewnotes/CreateReviewNotes.java b/src/main/java/com/googlesource/gerrit/plugins/reviewnotes/CreateReviewNotes.java index 249f9b6..9fce4c8 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/reviewnotes/CreateReviewNotes.java +++ b/src/main/java/com/googlesource/gerrit/plugins/reviewnotes/CreateReviewNotes.java
@@ -156,7 +156,10 @@ } for (RevCommit c : rw) { - ObjectId content = createNoteContent(loadPatchSet(c, branch)); + PatchSet ps = loadPatchSet(c, branch); + ChangeNotes notes = + notesFactory.create(reviewDb, project, ps.getId().getParentKey()); + ObjectId content = createNoteContent(notes, ps); if (content != null) { monitor.update(1); getNotes().set(c, content); @@ -166,19 +169,20 @@ } } - void createNotes(List<Change> changes, ProgressMonitor monitor) + void createNotes(List<ChangeNotes> notes, ProgressMonitor monitor) throws OrmException, IOException { try (RevWalk rw = new RevWalk(git)) { if (monitor == null) { monitor = NullProgressMonitor.INSTANCE; } - for (Change c : changes) { + for (ChangeNotes cn : notes) { monitor.update(1); - PatchSet ps = reviewDb.patchSets().get(c.currentPatchSetId()); + PatchSet ps = + reviewDb.patchSets().get(cn.getChange().currentPatchSetId()); ObjectId commitId = ObjectId.fromString(ps.getRevision().get()); RevCommit commit = rw.parseCommit(commitId); - getNotes().set(commitId, createNoteContent(ps)); + getNotes().set(commitId, createNoteContent(cn, ps)); getMessage().append("* ").append(commit.getShortMessage()).append("\n"); } } @@ -225,13 +229,13 @@ } } - private ObjectId createNoteContent(PatchSet ps) + private ObjectId createNoteContent(ChangeNotes notes, PatchSet ps) throws OrmException, IOException { HeaderFormatter fmt = new HeaderFormatter(gerritServerIdent.getTimeZone(), anonymousCowardName); if (ps != null) { try { - createCodeReviewNote(ps, fmt); + createCodeReviewNote(notes, ps, fmt); return getInserter().insert(Constants.OBJ_BLOB, fmt.toString().getBytes("UTF-8")); } catch (NoSuchChangeException e) { @@ -255,15 +259,13 @@ return null; // TODO: createNoCodeReviewNote(branch, c, fmt); } - private void createCodeReviewNote(PatchSet ps, HeaderFormatter fmt) - throws OrmException, NoSuchChangeException { + private void createCodeReviewNote(ChangeNotes notes, PatchSet ps, + HeaderFormatter fmt) throws OrmException, NoSuchChangeException { // This races with the label normalization/writeback done by MergeOp. It may // repeat some work, but results should be identical except in the case of // an additional race with a permissions change. // TODO(dborowitz): These will eventually be stamped in the ChangeNotes at // commit time so we will be able to skip this normalization step. - ChangeNotes notes = - notesFactory.create(reviewDb, project, ps.getId().getParentKey()); Change change = notes.getChange(); ChangeControl ctl = changeControlFactory.controlFor( notes, userFactory.create(change.getOwner()));
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewnotes/ExportReviewNotes.java b/src/main/java/com/googlesource/gerrit/plugins/reviewnotes/ExportReviewNotes.java index 80c5fa5..d1cbb9a 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/reviewnotes/ExportReviewNotes.java +++ b/src/main/java/com/googlesource/gerrit/plugins/reviewnotes/ExportReviewNotes.java
@@ -14,12 +14,14 @@ package com.googlesource.gerrit.plugins.reviewnotes; -import com.google.common.collect.ArrayListMultimap; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ListMultimap; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.server.git.GitRepositoryManager; +import com.google.gerrit.server.notedb.ChangeNotes; import com.google.gerrit.sshd.SshCommand; import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.SchemaFactory; @@ -33,10 +35,8 @@ import org.kohsuke.args4j.Option; import java.io.IOException; -import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Map.Entry; /** Export review notes for all submitted changes in all projects. */ public class ExportReviewNotes extends SshCommand { @@ -52,7 +52,10 @@ @Inject private CreateReviewNotes.Factory reviewNotesFactory; - private ListMultimap<Project.NameKey, Change> changes; + @Inject + private ChangeNotes.Factory notesFactory; + + private ListMultimap<Project.NameKey, ChangeNotes> changes; private ThreadSafeProgressMonitor monitor; @Override @@ -61,12 +64,10 @@ threads = 1; } - List<Change> allChangeList = allChanges(); - monitor = new ThreadSafeProgressMonitor(new TextProgressMonitor(stdout)); - monitor.beginTask("Scanning changes", allChangeList.size()); - changes = cluster(allChangeList); - allChangeList = null; + changes = mergedChanges(); + monitor = new ThreadSafeProgressMonitor(new TextProgressMonitor(stdout)); + monitor.beginTask("Scanning merged changes", changes.size()); monitor.startWorkers(threads); for (int tid = 0; tid < threads; tid++) { new Worker().start(); @@ -75,32 +76,25 @@ monitor.endTask(); } - private List<Change> allChanges() { - try (ReviewDb db = database.open()){ - return db.changes().all().toList(); - } catch (OrmException e) { + private ListMultimap<Project.NameKey, ChangeNotes> mergedChanges() { + try (ReviewDb db = database.open()) { + return notesFactory.create(db, new Predicate<ChangeNotes>() { + @Override + public boolean apply(ChangeNotes notes) { + return notes.getChange().getStatus() == Change.Status.MERGED; + } + }); + } catch (OrmException | IOException e) { stderr.println("Cannot read changes from database " + e.getMessage()); - return Collections.emptyList(); + return ImmutableListMultimap.of(); } } - private ListMultimap<Project.NameKey, Change> cluster(List<Change> changes) { - ListMultimap<Project.NameKey, Change> m = ArrayListMultimap.create(); - for (Change change : changes) { - if (change.getStatus() == Change.Status.MERGED) { - m.put(change.getProject(), change); - } else { - monitor.update(1); - } - } - return m; - } - - private void export(ReviewDb db, Project.NameKey project, List<Change> changes) - throws IOException, OrmException { + private void export(ReviewDb db, Project.NameKey project, + List<ChangeNotes> notes) throws IOException, OrmException { try (Repository git = gitManager.openRepository(project)) { CreateReviewNotes crn = reviewNotesFactory.create(db, project, git); - crn.createNotes(changes, monitor); + crn.createNotes(notes, monitor); crn.commitNotes(); } catch (RepositoryNotFoundException e) { stderr.println("Unable to open project: " + project.get()); @@ -109,27 +103,27 @@ } } - private Map.Entry<Project.NameKey, List<Change>> next() { + private Map.Entry<Project.NameKey, List<ChangeNotes>> next() { synchronized (changes) { if (changes.isEmpty()) { return null; } final Project.NameKey name = changes.keySet().iterator().next(); - final List<Change> list = changes.removeAll(name); - return new Map.Entry<Project.NameKey, List<Change>>() { + final List<ChangeNotes> list = changes.removeAll(name); + return new Map.Entry<Project.NameKey, List<ChangeNotes>>() { @Override public Project.NameKey getKey() { return name; } @Override - public List<Change> getValue() { + public List<ChangeNotes> getValue() { return list; } @Override - public List<Change> setValue(List<Change> value) { + public List<ChangeNotes> setValue(List<ChangeNotes> value) { throw new UnsupportedOperationException(); } }; @@ -141,7 +135,7 @@ public void run() { try (ReviewDb db = database.open()){ for (;;) { - Entry<Project.NameKey, List<Change>> next = next(); + Map.Entry<Project.NameKey, List<ChangeNotes>> next = next(); if (next != null) { try { export(db, next.getKey(), next.getValue());