Merge "Move code review notes logic to reviewnotes plugin"

This commit is contained in:
Shawn Pearce
2013-02-08 15:01:41 +00:00
committed by Gerrit Code Review
11 changed files with 7 additions and 691 deletions

View File

@@ -22,7 +22,6 @@ User Guide
* link:user-dashboards.html[Dashboards]
* link:user-notify.html[Subscribing to Email Notifications]
* link:user-submodules.html[Subscribing to Git Submodules]
* link:refs-notes-review.html[The `refs/notes/review` namespace]
* link:prolog-cookbook.html[Prolog Cookbook]
* link:prolog-change-facts.html[Prolog Facts for Gerrit Changes]

View File

@@ -1,50 +0,0 @@
ExportReviewNotes
=================
NAME
----
ExportReviewNotes - Export successful reviews to link:refs-notes-review.html[refs/notes/review]
SYNOPSIS
--------
[verse]
'java' -jar gerrit.war 'ExportReviewNotes' -d <SITE_PATH>
DESCRIPTION
-----------
Scans every submitted change and creates an initial notes
branch detailing the previous submission information for
each merged change.
This task can take quite some time, but can run in the background
concurrently to the server if the database is MySQL or PostgreSQL.
If the database is H2, this task must be run by itself.
OPTIONS
-------
-d::
\--site-path::
Location of the gerrit.config file, and all other per-site
configuration data, supporting libraries and log files.
\--threads::
Number of threads to perform the scan work with. Default: 2.
CONTEXT
-------
This command can only be run on a server which has direct
connectivity to the metadata database, and local access to the
managed Git repositories.
EXAMPLES
--------
To generate all review information:
====
$ java -jar gerrit.war ExportReviewNotes -d site_path --threads 16
====
GERRIT
------
Part of link:index.html[Gerrit Code Review]

View File

@@ -30,9 +30,6 @@ version::
Transition Utilities
--------------------
link:pgm-ExportReviewNotes.html[ExportReviewNotes]::
Export submitted review information to refs/notes/review.
link:pgm-ScanTrackingIds.html[ScanTrackingIds]::
Rescan all changes after configuring trackingids.

View File

@@ -1,111 +0,0 @@
The refs/notes/review namespace
===============================
Summary
-------
`refs/notes/review` is a special reference that Gerrit creates on repositories
to store information about code reviews.
When a repository is cloned from Gerrit, the `refs/notes/review` reference is
not included by default. It has to be manually fetched:
====
$ git fetch origin refs/notes/review:refs/notes/review
====
It is also possible to
link:http://www.kernel.org/pub/software/scm/git/docs/git-config.html[configure git]
to always fetch `refs/notes/review`:
====
$ git config --add remote.origin.fetch refs/notes/review:refs/notes/review
$ git fetch
====
When `refs/notes/review` is fetched on a repository, the Gerrit review
information can be included in the git log output:
====
$ git log --show-notes=review
====
Content of refs/notes/review
----------------------------
For each commit, Gerrit stores the following review information in
`refs/notes/review`:
[[submitted_by]]
Submitted-by
~~~~~~~~~~~~
The name and email address of the Gerrit user that submitted the change in
link:http://www.ietf.org/rfc/rfc2822.txt[RFC 2822] format.
====
Submitted-by: Random J Developer <random@developer.example.org>
====
[[submitted_at]]
Submitted-at
~~~~~~~~~~~~
The time the commit was submitted in RFC 2822 time stamp format.
====
Submitted-at: Mon, 25 Jun 2012 16:15:57 +0200
====
[[reviewed_on]]
Reviewed-on
~~~~~~~~~~~
The URL to the change on the Gerrit server.
====
Reviewed-on: http://path.to.gerrit/12345
====
[[review_scores]]
Review Labels and Scores
~~~~~~~~~~~~~~~~~~~~~~~~
Review label and score, and the name and email address of the Gerrit user that
gave it in RFC 2822 format:
====
Code-Review+2: A. N. Other <another@developer.example.org>
Verified+1: A. N. Other <another@developer.example.org>
====
Commonly used review labels are "Code-Review" and "Verified", but any label
configured in Gerrit can be included.
All review labels and scores present on the change at the time of submit are
included.
[[project]]
Project
~~~~~~~
The name of the project in which the commit was made.
====
Project: kernel/common
====
[[branch]]
Branch
~~~~~~
The name of the branch on which the commit was made.
====
Branch: refs/heads/master
====
GERRIT
------
Part of link:index.html[Gerrit Code Review]

View File

@@ -46,6 +46,12 @@ limitations under the License.
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.googlesource.gerrit.plugins.reviewnotes</groupId>
<artifactId>reviewnotes</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>

View File

@@ -1,244 +0,0 @@
// Copyright (C) 2010 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.pgm;
import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER;
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.pgm.util.SiteProgram;
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.account.AccountCacheImpl;
import com.google.gerrit.server.account.GroupCacheImpl;
import com.google.gerrit.server.cache.h2.DefaultCacheFactory;
import com.google.gerrit.server.config.ApprovalTypesProvider;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.CanonicalWebUrlProvider;
import com.google.gerrit.server.config.FactoryModule;
import com.google.gerrit.server.git.CodeReviewNoteCreationException;
import com.google.gerrit.server.git.CreateCodeReviewNotes;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
import com.google.gerrit.server.git.NotesBranchUtil;
import com.google.gerrit.server.schema.SchemaVersionCheck;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Scopes;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.lib.ThreadSafeProgressMonitor;
import org.eclipse.jgit.util.BlockList;
import org.kohsuke.args4j.Option;
import java.io.IOException;
import java.util.HashMap;
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 SiteProgram {
@Option(name = "--threads", usage = "Number of concurrent threads to run")
private int threads = 2;
private final LifecycleManager manager = new LifecycleManager();
private final TextProgressMonitor textMonitor = new TextProgressMonitor();
private final ThreadSafeProgressMonitor monitor =
new ThreadSafeProgressMonitor(textMonitor);
private Injector dbInjector;
private Injector gitInjector;
@Inject
private GitRepositoryManager gitManager;
@Inject
private SchemaFactory<ReviewDb> database;
@Inject
private CreateCodeReviewNotes.Factory codeReviewNotesFactory;
private Map<Project.NameKey, List<Change>> changes;
@Override
public int run() throws Exception {
if (threads <= 0) {
threads = 1;
}
dbInjector = createDbInjector(MULTI_USER);
gitInjector = dbInjector.createChildInjector(new AbstractModule() {
@Override
protected void configure() {
install(SchemaVersionCheck.module());
bind(ApprovalTypes.class).toProvider(ApprovalTypesProvider.class).in(
Scopes.SINGLETON);
bind(String.class).annotatedWith(CanonicalWebUrl.class)
.toProvider(CanonicalWebUrlProvider.class).in(Scopes.SINGLETON);
install(AccountCacheImpl.module());
install(GroupCacheImpl.module());
install(new DefaultCacheFactory.Module());
install(new FactoryModule() {
@Override
protected void configure() {
factory(CreateCodeReviewNotes.Factory.class);
factory(NotesBranchUtil.Factory.class);
}
});
install(new LifecycleModule() {
@Override
protected void configure() {
listener().to(LocalDiskRepositoryManager.Lifecycle.class);
}
});
}
});
manager.add(dbInjector, gitInjector);
manager.start();
gitInjector.injectMembers(this);
List<Change> allChangeList = allChanges();
monitor.beginTask("Scanning changes", allChangeList.size());
changes = cluster(allChangeList);
allChangeList = null;
monitor.startWorkers(threads);
for (int tid = 0; tid < threads; tid++) {
new Worker().start();
}
monitor.waitForCompletion();
monitor.endTask();
manager.stop();
return 0;
}
private List<Change> allChanges() throws OrmException {
final ReviewDb db = database.open();
try {
return db.changes().all().toList();
} finally {
db.close();
}
}
private Map<Project.NameKey, List<Change>> cluster(List<Change> changes) {
HashMap<Project.NameKey, List<Change>> m =
new HashMap<Project.NameKey, List<Change>>();
for (Change change : changes) {
if (change.getStatus() == Change.Status.MERGED) {
List<Change> l = m.get(change.getProject());
if (l == null) {
l = new BlockList<Change>();
m.put(change.getProject(), l);
}
l.add(change);
} else {
monitor.update(1);
}
}
return m;
}
private void export(ReviewDb db, Project.NameKey project, List<Change> changes)
throws IOException, OrmException, CodeReviewNoteCreationException,
InterruptedException {
final Repository git;
try {
git = gitManager.openRepository(project);
} catch (RepositoryNotFoundException e) {
return;
}
try {
CreateCodeReviewNotes notes = codeReviewNotesFactory.create(db, project, git);
notes.create(changes, null,
"Exported prior reviews from Gerrit Code Review\n", monitor);
} finally {
git.close();
}
}
private Map.Entry<Project.NameKey, List<Change>> next() {
synchronized (changes) {
if (changes.isEmpty()) {
return null;
}
final Project.NameKey name = changes.keySet().iterator().next();
final List<Change> list = changes.remove(name);
return new Map.Entry<Project.NameKey, List<Change>>() {
@Override
public Project.NameKey getKey() {
return name;
}
@Override
public List<Change> getValue() {
return list;
}
@Override
public List<Change> setValue(List<Change> value) {
throw new UnsupportedOperationException();
}
};
}
}
private class Worker extends Thread {
@Override
public void run() {
ReviewDb db;
try {
db = database.open();
} catch (OrmException e) {
e.printStackTrace();
return;
}
try {
for (;;) {
Entry<Project.NameKey, List<Change>> next = next();
if (next != null) {
try {
export(db, next.getKey(), next.getValue());
} catch (IOException e) {
e.printStackTrace();
} catch (OrmException e) {
e.printStackTrace();
} catch (CodeReviewNoteCreationException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
} finally {
monitor.endWorker();
db.close();
}
}
}
}

View File

@@ -24,7 +24,6 @@ import com.google.gerrit.server.changedetail.DeleteDraftPatchSet;
import com.google.gerrit.server.changedetail.PublishDraft;
import com.google.gerrit.server.git.AsyncReceiveCommits;
import com.google.gerrit.server.git.BanCommit;
import com.google.gerrit.server.git.CreateCodeReviewNotes;
import com.google.gerrit.server.git.MergeOp;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.SubmoduleOp;
@@ -60,7 +59,6 @@ public class GerritRequestModule extends FactoryModule {
factory(SubmoduleOp.Factory.class);
factory(MergeOp.Factory.class);
factory(CreateCodeReviewNotes.Factory.class);
install(new AsyncReceiveCommits.Module());
// Not really per-request, but dammit, I don't know where else to

View File

@@ -1,37 +0,0 @@
// Copyright (C) 2011 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server.git;
import org.eclipse.jgit.revwalk.RevCommit;
/**
* Thrown when creation of a code review note fails.
*/
public class CodeReviewNoteCreationException extends Exception {
private static final long serialVersionUID = 1L;
public CodeReviewNoteCreationException(final String msg) {
super(msg);
}
public CodeReviewNoteCreationException(final Throwable why) {
super(why);
}
public CodeReviewNoteCreationException(final RevCommit commit,
final Throwable cause) {
super("Couldn't create code review note for the following commit: "
+ commit.name(), cause);
}
}

View File

@@ -1,221 +0,0 @@
// Copyright (C) 2010 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server.git;
import static com.google.gerrit.server.git.GitRepositoryManager.REFS_NOTES_REVIEW;
import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.reviewdb.client.ApprovalCategory;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.FooterKey;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import java.io.IOException;
import java.util.List;
import javax.annotation.Nullable;
/**
* This class create code review notes for given {@link CodeReviewCommit}s.
* <p>
* After the {@link #create(List, PersonIdent)} method is invoked once this
* instance must not be reused. Create a new instance of this class if needed.
*/
public class CreateCodeReviewNotes {
public interface Factory {
CreateCodeReviewNotes create(ReviewDb reviewDb, Project.NameKey project,
Repository db);
}
private static final FooterKey CHANGE_ID = new FooterKey("Change-Id");
private final AccountCache accountCache;
private final ApprovalTypes approvalTypes;
private final String canonicalWebUrl;
private final String anonymousCowardName;
private final ReviewDb schema;
private final Project.NameKey project;
private final Repository db;
private PersonIdent author;
private RevWalk revWalk;
private ObjectInserter inserter;
private final NotesBranchUtil.Factory notesBranchUtilFactory;
@Inject
CreateCodeReviewNotes(
@GerritPersonIdent final PersonIdent gerritIdent,
final AccountCache accountCache,
final ApprovalTypes approvalTypes,
final @Nullable @CanonicalWebUrl String canonicalWebUrl,
final @AnonymousCowardName String anonymousCowardName,
final NotesBranchUtil.Factory notesBranchUtilFactory,
final @Assisted ReviewDb reviewDb,
final @Assisted Project.NameKey project,
final @Assisted Repository db) {
this.author = gerritIdent;
this.accountCache = accountCache;
this.approvalTypes = approvalTypes;
this.canonicalWebUrl = canonicalWebUrl;
this.anonymousCowardName = anonymousCowardName;
this.notesBranchUtilFactory = notesBranchUtilFactory;
schema = reviewDb;
this.project = project;
this.db = db;
}
public void create(List<CodeReviewCommit> commits, PersonIdent author)
throws CodeReviewNoteCreationException {
try {
revWalk = new RevWalk(db);
inserter = db.newObjectInserter();
if (author != null) {
this.author = author;
}
NoteMap notes = NoteMap.newEmptyMap();
StringBuilder message =
new StringBuilder("Update notes for submitted changes\n\n");
for (CodeReviewCommit c : commits) {
notes.set(c, createNoteContent(c.change, c));
message.append("* ").append(c.getShortMessage()).append("\n");
}
NotesBranchUtil notesBranchUtil = notesBranchUtilFactory.create(project,
db, inserter);
notesBranchUtil.commitAllNotes(notes, REFS_NOTES_REVIEW, author,
message.toString());
inserter.flush();
} catch (IOException e) {
throw new CodeReviewNoteCreationException(e);
} catch (ConcurrentRefUpdateException e) {
throw new CodeReviewNoteCreationException(e);
} finally {
revWalk.release();
inserter.release();
}
}
public void create(List<Change> changes, PersonIdent author,
String commitMessage, ProgressMonitor monitor) throws OrmException,
IOException, CodeReviewNoteCreationException {
try {
revWalk = new RevWalk(db);
inserter = db.newObjectInserter();
if (author != null) {
this.author = author;
}
if (monitor == null) {
monitor = NullProgressMonitor.INSTANCE;
}
NoteMap notes = NoteMap.newEmptyMap();
for (Change c : changes) {
monitor.update(1);
PatchSet ps = schema.patchSets().get(c.currentPatchSetId());
ObjectId commitId = ObjectId.fromString(ps.getRevision().get());
notes.set(commitId, createNoteContent(c, commitId));
}
NotesBranchUtil notesBranchUtil = notesBranchUtilFactory.create(project,
db, inserter);
notesBranchUtil.commitAllNotes(notes, REFS_NOTES_REVIEW, author,
commitMessage);
inserter.flush();
} catch (ConcurrentRefUpdateException e) {
throw new CodeReviewNoteCreationException(e);
} finally {
revWalk.release();
inserter.release();
}
}
private ObjectId createNoteContent(Change change, ObjectId commit)
throws CodeReviewNoteCreationException, IOException {
if (!(commit instanceof RevCommit)) {
commit = revWalk.parseCommit(commit);
}
return createNoteContent(change, (RevCommit) commit);
}
private ObjectId createNoteContent(Change change, RevCommit commit)
throws CodeReviewNoteCreationException, IOException {
try {
ReviewNoteHeaderFormatter formatter =
new ReviewNoteHeaderFormatter(author.getTimeZone(),
anonymousCowardName);
final List<String> idList = commit.getFooterLines(CHANGE_ID);
if (idList.isEmpty())
formatter.appendChangeId(change.getKey());
ResultSet<PatchSetApproval> approvals =
schema.patchSetApprovals().byPatchSet(change.currentPatchSetId());
PatchSetApproval submit = null;
for (PatchSetApproval a : approvals) {
if (a.getValue() == 0) {
// Ignore 0 values.
} else if (ApprovalCategory.SUBMIT.equals(a.getCategoryId())) {
submit = a;
} else {
ApprovalType type = approvalTypes.byId(a.getCategoryId());
if (type != null) {
formatter.appendApproval(
type.getCategory(),
a.getValue(),
accountCache.get(a.getAccountId()).getAccount());
}
}
}
if (submit != null) {
formatter.appendSubmittedBy(accountCache.get(submit.getAccountId()).getAccount());
formatter.appendSubmittedAt(submit.getGranted());
}
if (canonicalWebUrl != null) {
formatter.appendReviewedOn(canonicalWebUrl, change.getId());
}
formatter.appendProject(change.getProject().get());
formatter.appendBranch(change.getDest());
return inserter.insert(Constants.OBJ_BLOB, formatter.toString().getBytes("UTF-8"));
} catch (OrmException e) {
throw new CodeReviewNoteCreationException(commit, e);
}
}
}

View File

@@ -31,9 +31,6 @@ import java.util.SortedSet;
* environment.
*/
public interface GitRepositoryManager {
/** Notes branch successful reviews are written to after being merged. */
public static final String REFS_NOTES_REVIEW = "refs/notes/review";
/** Note tree listing commits we refuse {@code refs/meta/reject-commits} */
public static final String REF_REJECT_COMMITS = "refs/meta/reject-commits";

View File

@@ -14,7 +14,6 @@
package com.google.gerrit.server.git;
import static com.google.gerrit.server.git.MergeUtil.computeMergeCommitAuthor;
import static com.google.gerrit.server.git.MergeUtil.getSubmitter;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES;
@@ -39,7 +38,6 @@ import com.google.gerrit.reviewdb.client.Project.SubmitType;
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.config.AllProjectsName;
@@ -131,7 +129,6 @@ public class MergeOp {
private final ChangeControl.GenericFactory changeControlFactory;
private final MergeQueue mergeQueue;
private final PersonIdent myIdent;
private final Branch.NameKey destBranch;
private ProjectState destProject;
private final ListMultimap<SubmitType, CodeReviewCommit> toMerge;
@@ -149,7 +146,6 @@ public class MergeOp {
private final ChangeHooks hooks;
private final AccountCache accountCache;
private final TagCache tagCache;
private final CreateCodeReviewNotes.Factory codeReviewNotesFactory;
private final SubmitStrategyFactory submitStrategyFactory;
private final SubmoduleOp.Factory subOpFactory;
private final WorkQueue workQueue;
@@ -164,10 +160,9 @@ public class MergeOp {
final ApprovalTypes approvalTypes, final PatchSetInfoFactory psif,
final IdentifiedUser.GenericFactory iuf,
final ChangeControl.GenericFactory changeControlFactory,
@GerritPersonIdent final PersonIdent myIdent,
final MergeQueue mergeQueue, @Assisted final Branch.NameKey branch,
final ChangeHooks hooks, final AccountCache accountCache,
final TagCache tagCache, final CreateCodeReviewNotes.Factory crnf,
final TagCache tagCache,
final SubmitStrategyFactory submitStrategyFactory,
final SubmoduleOp.Factory subOpFactory,
final WorkQueue workQueue,
@@ -188,13 +183,11 @@ public class MergeOp {
this.hooks = hooks;
this.accountCache = accountCache;
this.tagCache = tagCache;
codeReviewNotesFactory = crnf;
this.submitStrategyFactory = submitStrategyFactory;
this.subOpFactory = subOpFactory;
this.workQueue = workQueue;
this.requestScopePropagator = requestScopePropagator;
this.allProjectsName = allProjectsName;
this.myIdent = myIdent;
destBranch = branch;
toMerge = ArrayListMultimap.create();
potentiallyStillSubmittable = new ArrayList<CodeReviewCommit>();
@@ -771,17 +764,6 @@ public class MergeOp {
break;
}
}
CreateCodeReviewNotes codeReviewNotes =
codeReviewNotesFactory.create(db, destBranch.getParentKey(), repo);
try {
codeReviewNotes.create(
merged,
computeMergeCommitAuthor(db, identifiedUserFactory, myIdent, rw,
merged));
} catch (CodeReviewNoteCreationException e) {
log.error(e.getMessage());
}
}
private void updateSubscriptions(final List<Change> submitted) {