Inject ChangeUtil, making most methods non-static

Change-Id: I14c49cb4a0b9829d751ea96cd2d909f234654508
This commit is contained in:
Dave Borowitz 2013-12-03 14:26:31 -08:00
parent 4f47ab7468
commit ef6cca84cb
8 changed files with 374 additions and 466 deletions

View File

@ -19,9 +19,6 @@ import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.index.ChangeIndexer;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gwtjsonrpc.common.VoidResult;
@ -38,39 +35,28 @@ class DeleteDraftChange extends Handler<VoidResult> {
private final ChangeControl.Factory changeControlFactory;
private final ReviewDb db;
private final GitRepositoryManager gitManager;
private final GitReferenceUpdated gitRefUpdated;
private final ChangeIndexer indexer;
private final ChangeUtil changeUtil;
private final PatchSet.Id patchSetId;
@Inject
DeleteDraftChange(final ReviewDb db,
final ChangeControl.Factory changeControlFactory,
final GitRepositoryManager gitManager,
final GitReferenceUpdated gitRefUpdated,
final ChangeIndexer indexer,
@Assisted final PatchSet.Id patchSetId) {
DeleteDraftChange(ReviewDb db,
ChangeControl.Factory changeControlFactory,
ChangeUtil changeUtil,
@Assisted PatchSet.Id patchSetId) {
this.changeControlFactory = changeControlFactory;
this.db = db;
this.gitManager = gitManager;
this.gitRefUpdated = gitRefUpdated;
this.indexer = indexer;
this.changeUtil = changeUtil;
this.patchSetId = patchSetId;
}
@Override
public VoidResult call() throws NoSuchChangeException, OrmException, IOException {
final Change.Id changeId = patchSetId.getParentKey();
final ChangeControl control = changeControlFactory.validateFor(changeId);
Change.Id changeId = patchSetId.getParentKey();
ChangeControl control = changeControlFactory.validateFor(changeId);
if (!control.canDeleteDraft(db)) {
throw new NoSuchChangeException(changeId);
}
ChangeUtil.deleteDraftChange(patchSetId, gitManager, gitRefUpdated, db,
indexer);
changeUtil.deleteDraftChange(patchSetId);
return VoidResult.INSTANCE;
}
}

View File

@ -21,12 +21,9 @@ import com.google.gerrit.common.errors.NoSuchEntityException;
import com.google.gerrit.httpd.rpc.Handler;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
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.change.PatchSetInserter;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.mail.CommitMessageEditedSender;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
import com.google.gerrit.server.project.ChangeControl;
@ -39,9 +36,7 @@ import com.google.inject.assistedinject.Assisted;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;
@ -51,37 +46,28 @@ class EditCommitMessageHandler extends Handler<ChangeDetail> {
}
private final ChangeControl.Factory changeControlFactory;
private final ReviewDb db;
private final IdentifiedUser currentUser;
private final ChangeDetailFactory.Factory changeDetailFactory;
private final CommitMessageEditedSender.Factory commitMessageEditedSenderFactory;
private final ChangeUtil changeUtil;
private final PatchSet.Id patchSetId;
@Nullable
private final String message;
private final GitRepositoryManager gitManager;
private final PersonIdent myIdent;
private final PatchSetInserter.Factory patchSetInserterFactory;
@Inject
EditCommitMessageHandler(final ChangeControl.Factory changeControlFactory,
final ReviewDb db, final IdentifiedUser currentUser,
final ChangeDetailFactory.Factory changeDetailFactory,
final CommitMessageEditedSender.Factory commitMessageEditedSenderFactory,
@Assisted final PatchSet.Id patchSetId,
@Assisted @Nullable final String message,
final GitRepositoryManager gitManager,
@GerritPersonIdent final PersonIdent myIdent,
final PatchSetInserter.Factory patchSetInserterFactory) {
EditCommitMessageHandler(ChangeControl.Factory changeControlFactory,
ChangeDetailFactory.Factory changeDetailFactory,
CommitMessageEditedSender.Factory commitMessageEditedSenderFactory,
@Assisted PatchSet.Id patchSetId,
@Assisted @Nullable String message,
ChangeUtil changeUtil,
@GerritPersonIdent PersonIdent myIdent,
PatchSetInserter.Factory patchSetInserterFactory) {
this.changeControlFactory = changeControlFactory;
this.db = db;
this.currentUser = currentUser;
this.changeDetailFactory = changeDetailFactory;
this.commitMessageEditedSenderFactory = commitMessageEditedSenderFactory;
this.changeUtil = changeUtil;
this.patchSetId = patchSetId;
this.message = message;
this.gitManager = gitManager;
this.myIdent = myIdent;
this.patchSetInserterFactory = patchSetInserterFactory;
}
@Override
@ -89,27 +75,13 @@ class EditCommitMessageHandler extends Handler<ChangeDetail> {
EmailException, NoSuchEntityException, PatchSetInfoNotAvailableException,
MissingObjectException, IncorrectObjectTypeException, IOException,
InvalidChangeOperationException, NoSuchProjectException {
final Change.Id changeId = patchSetId.getParentKey();
final ChangeControl control = changeControlFactory.validateFor(changeId);
Change.Id changeId = patchSetId.getParentKey();
ChangeControl control = changeControlFactory.validateFor(changeId);
if (!control.canAddPatchSet()) {
throw new InvalidChangeOperationException(
"Not allowed to add new Patch Sets to: " + changeId.toString());
}
final Repository git;
try {
git = gitManager.openRepository(db.changes().get(changeId).getProject());
} catch (RepositoryNotFoundException e) {
throw new NoSuchChangeException(changeId, e);
}
try {
ChangeUtil.editCommitMessage(patchSetId, control.getRefControl(),
currentUser, message, db, commitMessageEditedSenderFactory, git,
myIdent, patchSetInserterFactory);
return changeDetailFactory.create(changeId).call();
} finally {
git.close();
}
changeUtil.editCommitMessage(control, patchSetId, message, myIdent);
return changeDetailFactory.create(changeId).call();
}
}

View File

@ -21,7 +21,6 @@ import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.primitives.Ints;
import com.google.gerrit.common.ChangeHooks;
import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
@ -38,21 +37,24 @@ import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.validators.CommitValidationException;
import com.google.gerrit.server.git.validators.CommitValidators;
import com.google.gerrit.server.index.ChangeIndexer;
import com.google.gerrit.server.mail.CommitMessageEditedSender;
import com.google.gerrit.server.mail.RevertedSender;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.RefControl;
import com.google.gerrit.server.ssh.SshInfo;
import com.google.gerrit.server.util.IdGenerator;
import com.google.gerrit.server.util.MagicBranch;
import com.google.gerrit.server.util.TimeUtil;
import com.google.gwtorm.server.OrmConcurrencyException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
@ -118,7 +120,7 @@ public class ChangeUtil {
return u + '_' + l;
}
public static void touch(final Change change, ReviewDb db)
public static void touch(Change change, ReviewDb db)
throws OrmException {
try {
updated(change);
@ -137,14 +139,14 @@ public class ChangeUtil {
}
}
public static void updated(final Change c) {
public static void updated(Change c) {
c.setLastUpdatedOn(TimeUtil.nowTs());
computeSortKey(c);
}
public static void insertAncestors(ReviewDb db, PatchSet.Id id, RevCommit src)
throws OrmException {
final int cnt = src.getParentCount();
int cnt = src.getParentCount();
List<PatchSetAncestor> toInsert = new ArrayList<PatchSetAncestor>(cnt);
for (int p = 0; p < cnt; p++) {
PatchSetAncestor a =
@ -155,268 +157,7 @@ public class ChangeUtil {
db.patchSetAncestors().insert(toInsert);
}
public static Change.Id revert(RefControl refControl, PatchSet.Id patchSetId,
IdentifiedUser user, CommitValidators commitValidators, String message,
ReviewDb db, RevertedSender.Factory revertedSenderFactory,
ChangeHooks hooks, Repository git,
PatchSetInfoFactory patchSetInfoFactory, PersonIdent myIdent,
ChangeInserter.Factory changeInserterFactory)
throws NoSuchChangeException, EmailException,
OrmException, MissingObjectException, IncorrectObjectTypeException,
IOException, InvalidChangeOperationException {
final Change.Id changeId = patchSetId.getParentKey();
final PatchSet patch = db.patchSets().get(patchSetId);
if (patch == null) {
throw new NoSuchChangeException(changeId);
}
final Change changeToRevert = db.changes().get(changeId);
final RevWalk revWalk = new RevWalk(git);
try {
RevCommit commitToRevert =
revWalk.parseCommit(ObjectId.fromString(patch.getRevision().get()));
PersonIdent authorIdent =
user.newCommitterIdent(myIdent.getWhen(), myIdent.getTimeZone());
RevCommit parentToCommitToRevert = commitToRevert.getParent(0);
revWalk.parseHeaders(parentToCommitToRevert);
CommitBuilder revertCommitBuilder = new CommitBuilder();
revertCommitBuilder.addParentId(commitToRevert);
revertCommitBuilder.setTreeId(parentToCommitToRevert.getTree());
revertCommitBuilder.setAuthor(authorIdent);
revertCommitBuilder.setCommitter(authorIdent);
if (message == null) {
message = MessageFormat.format(
ChangeMessages.get().revertChangeDefaultMessage,
changeToRevert.getSubject(), patch.getRevision().get());
}
final ObjectId computedChangeId =
ChangeIdUtil.computeChangeId(parentToCommitToRevert.getTree(),
commitToRevert, authorIdent, myIdent, message);
revertCommitBuilder.setMessage(ChangeIdUtil.insertId(message, computedChangeId, true));
RevCommit revertCommit;
final ObjectInserter oi = git.newObjectInserter();
try {
ObjectId id = oi.insert(revertCommitBuilder);
oi.flush();
revertCommit = revWalk.parseCommit(id);
} finally {
oi.release();
}
final Change change = new Change(
new Change.Key("I" + computedChangeId.name()),
new Change.Id(db.nextChangeId()),
user.getAccountId(),
changeToRevert.getDest(),
TimeUtil.nowTs());
change.setTopic(changeToRevert.getTopic());
ChangeInserter ins =
changeInserterFactory.create(refControl, change, revertCommit);
PatchSet ps = ins.getPatchSet();
String ref = refControl.getRefName();
final String cmdRef =
MagicBranch.NEW_PUBLISH_CHANGE
+ ref.substring(ref.lastIndexOf('/') + 1);
CommitReceivedEvent commitReceivedEvent =
new CommitReceivedEvent(new ReceiveCommand(ObjectId.zeroId(),
revertCommit.getId(), cmdRef), refControl.getProjectControl()
.getProject(), refControl.getRefName(), revertCommit, user);
try {
commitValidators.validateForGerritCommits(commitReceivedEvent);
} catch (CommitValidationException e) {
throw new InvalidChangeOperationException(e.getMessage());
}
final RefUpdate ru = git.updateRef(ps.getRefName());
ru.setExpectedOldObjectId(ObjectId.zeroId());
ru.setNewObjectId(revertCommit);
ru.disableRefLog();
if (ru.update(revWalk) != RefUpdate.Result.NEW) {
throw new IOException(String.format(
"Failed to create ref %s in %s: %s", ps.getRefName(),
change.getDest().getParentKey().get(), ru.getResult()));
}
final ChangeMessage cmsg = new ChangeMessage(
new ChangeMessage.Key(changeId, ChangeUtil.messageUUID(db)),
user.getAccountId(), TimeUtil.nowTs(), patchSetId);
final StringBuilder msgBuf =
new StringBuilder("Patch Set " + patchSetId.get() + ": Reverted");
msgBuf.append("\n\n");
msgBuf.append("This patchset was reverted in change: " + change.getKey().get());
cmsg.setMessage(msgBuf.toString());
ins.setMessage(cmsg).insert();
try {
final RevertedSender cm = revertedSenderFactory.create(change);
cm.setFrom(user.getAccountId());
cm.setChangeMessage(cmsg);
cm.send();
} catch (Exception err) {
log.error("Cannot send email for revert change " + change.getId(),
err);
}
return change.getId();
} finally {
revWalk.release();
}
}
public static Change.Id editCommitMessage(final PatchSet.Id patchSetId,
final RefControl refControl, final IdentifiedUser user,
final String message, final ReviewDb db,
final CommitMessageEditedSender.Factory commitMessageEditedSenderFactory,
Repository git, PersonIdent myIdent,
PatchSetInserter.Factory patchSetInserterFactory)
throws NoSuchChangeException, EmailException, OrmException,
MissingObjectException, IncorrectObjectTypeException, IOException,
InvalidChangeOperationException, PatchSetInfoNotAvailableException {
final Change.Id changeId = patchSetId.getParentKey();
final PatchSet originalPS = db.patchSets().get(patchSetId);
if (originalPS == null) {
throw new NoSuchChangeException(changeId);
}
if (message == null || message.length() == 0) {
throw new InvalidChangeOperationException(
"The commit message cannot be empty");
}
final RevWalk revWalk = new RevWalk(git);
try {
RevCommit commit =
revWalk.parseCommit(ObjectId.fromString(originalPS.getRevision()
.get()));
if (commit.getFullMessage().equals(message)) {
throw new InvalidChangeOperationException(
"New commit message cannot be same as existing commit message");
}
Date now = myIdent.getWhen();
Change change = db.changes().get(changeId);
PersonIdent authorIdent =
user.newCommitterIdent(now, myIdent.getTimeZone());
CommitBuilder commitBuilder = new CommitBuilder();
commitBuilder.setTreeId(commit.getTree());
commitBuilder.setParentIds(commit.getParents());
commitBuilder.setAuthor(commit.getAuthorIdent());
commitBuilder.setCommitter(authorIdent);
commitBuilder.setMessage(message);
RevCommit newCommit;
final ObjectInserter oi = git.newObjectInserter();
try {
ObjectId id = oi.insert(commitBuilder);
oi.flush();
newCommit = revWalk.parseCommit(id);
} finally {
oi.release();
}
PatchSet.Id id = nextPatchSetId(git, change.currentPatchSetId());
final PatchSet newPatchSet = new PatchSet(id);
newPatchSet.setCreatedOn(new Timestamp(now.getTime()));
newPatchSet.setUploader(user.getAccountId());
newPatchSet.setRevision(new RevId(newCommit.name()));
final String msg =
"Patch Set " + newPatchSet.getPatchSetId()
+ ": Commit message was updated";
change = patchSetInserterFactory
.create(git, revWalk, refControl, user, change, newCommit)
.setPatchSet(newPatchSet)
.setMessage(msg)
.setCopyLabels(true)
.setValidatePolicy(RECEIVE_COMMITS)
.setDraft(originalPS.isDraft())
.insert();
return change.getId();
} finally {
revWalk.release();
}
}
public static void deleteDraftChange(PatchSet.Id patchSetId,
GitRepositoryManager gitManager,
GitReferenceUpdated gitRefUpdated, ReviewDb db, ChangeIndexer indexer)
throws NoSuchChangeException, OrmException, IOException {
final Change.Id changeId = patchSetId.getParentKey();
deleteDraftChange(changeId, gitManager, gitRefUpdated, db, indexer);
}
public static void deleteDraftChange(Change.Id changeId,
GitRepositoryManager gitManager,
GitReferenceUpdated gitRefUpdated, ReviewDb db, ChangeIndexer indexer)
throws NoSuchChangeException, OrmException, IOException {
Change change = db.changes().get(changeId);
if (change == null || change.getStatus() != Change.Status.DRAFT) {
throw new NoSuchChangeException(changeId);
}
for (PatchSet ps : db.patchSets().byChange(changeId)) {
// These should all be draft patch sets.
deleteOnlyDraftPatchSet(ps, change, gitManager, gitRefUpdated, db);
}
db.changeMessages().delete(db.changeMessages().byChange(changeId));
db.starredChanges().delete(db.starredChanges().byChange(changeId));
db.changes().delete(Collections.singleton(change));
indexer.delete(change);
}
public static void deleteOnlyDraftPatchSet(final PatchSet patch,
final Change change, GitRepositoryManager gitManager,
final GitReferenceUpdated gitRefUpdated, final ReviewDb db)
throws NoSuchChangeException, OrmException, IOException {
final PatchSet.Id patchSetId = patch.getId();
if (!patch.isDraft()) {
throw new NoSuchChangeException(patchSetId.getParentKey());
}
Repository repo = gitManager.openRepository(change.getProject());
try {
RefUpdate update = repo.updateRef(patch.getRefName());
update.setForceUpdate(true);
update.disableRefLog();
switch (update.delete()) {
case NEW:
case FAST_FORWARD:
case FORCED:
case NO_CHANGE:
// Successful deletion.
break;
default:
throw new IOException("Failed to delete ref " + patch.getRefName() +
" in " + repo.getDirectory() + ": " + update.getResult());
}
gitRefUpdated.fire(change.getProject(), update);
} finally {
repo.close();
}
db.accountPatchReviews().delete(db.accountPatchReviews().byPatchSet(patchSetId));
db.changeMessages().delete(db.changeMessages().byPatchSet(patchSetId));
db.patchComments().delete(db.patchComments().byPatchSet(patchSetId));
db.patchSetApprovals().delete(db.patchSetApprovals().byPatchSet(patchSetId));
db.patchSetAncestors().delete(db.patchSetAncestors().byPatchSet(patchSetId));
db.patchSets().delete(Collections.singleton(patch));
}
public static String sortKey(long lastUpdatedMs, int id){
public static String sortKey(long lastUpdatedMs, int id) {
long lastUpdatedMins = MINUTES.convert(lastUpdatedMs, MILLISECONDS);
long minsSinceEpoch = lastUpdatedMins - SORT_KEY_EPOCH_MINS;
StringBuilder r = new StringBuilder(16);
@ -453,6 +194,310 @@ public class ChangeUtil {
return nextPatchSetId(git.getRefDatabase().getRefs(RefDatabase.ALL), id);
}
private final Provider<CurrentUser> userProvider;
private final CommitValidators.Factory commitValidatorsFactory;
private final Provider<ReviewDb> db;
private final RevertedSender.Factory revertedSenderFactory;
private final ChangeInserter.Factory changeInserterFactory;
private final PatchSetInserter.Factory patchSetInserterFactory;
private final GitRepositoryManager gitManager;
private final GitReferenceUpdated gitRefUpdated;
private final ChangeIndexer indexer;
@Inject
ChangeUtil(Provider<CurrentUser> userProvider,
CommitValidators.Factory commitValidatorsFactory,
Provider<ReviewDb> db,
RevertedSender.Factory revertedSenderFactory,
ChangeInserter.Factory changeInserterFactory,
PatchSetInserter.Factory patchSetInserterFactory,
GitRepositoryManager gitManager,
GitReferenceUpdated gitRefUpdated,
ChangeIndexer indexer) {
this.userProvider = userProvider;
this.commitValidatorsFactory = commitValidatorsFactory;
this.db = db;
this.revertedSenderFactory = revertedSenderFactory;
this.changeInserterFactory = changeInserterFactory;
this.patchSetInserterFactory = patchSetInserterFactory;
this.gitManager = gitManager;
this.gitRefUpdated = gitRefUpdated;
this.indexer = indexer;
}
public Change.Id revert(ChangeControl ctl, PatchSet.Id patchSetId,
String message, PersonIdent myIdent, SshInfo sshInfo)
throws NoSuchChangeException, EmailException, OrmException,
MissingObjectException, IncorrectObjectTypeException, IOException,
InvalidChangeOperationException {
Change.Id changeId = patchSetId.getParentKey();
PatchSet patch = db.get().patchSets().get(patchSetId);
if (patch == null) {
throw new NoSuchChangeException(changeId);
}
Change changeToRevert = db.get().changes().get(changeId);
Repository git;
try {
git = gitManager.openRepository(ctl.getChange().getProject());
} catch (RepositoryNotFoundException e) {
throw new NoSuchChangeException(changeId, e);
}
try {
RevWalk revWalk = new RevWalk(git);
try {
RevCommit commitToRevert =
revWalk.parseCommit(ObjectId.fromString(patch.getRevision().get()));
PersonIdent authorIdent =
user().newCommitterIdent(myIdent.getWhen(), myIdent.getTimeZone());
RevCommit parentToCommitToRevert = commitToRevert.getParent(0);
revWalk.parseHeaders(parentToCommitToRevert);
CommitBuilder revertCommitBuilder = new CommitBuilder();
revertCommitBuilder.addParentId(commitToRevert);
revertCommitBuilder.setTreeId(parentToCommitToRevert.getTree());
revertCommitBuilder.setAuthor(authorIdent);
revertCommitBuilder.setCommitter(authorIdent);
if (message == null) {
message = MessageFormat.format(
ChangeMessages.get().revertChangeDefaultMessage,
changeToRevert.getSubject(), patch.getRevision().get());
}
ObjectId computedChangeId =
ChangeIdUtil.computeChangeId(parentToCommitToRevert.getTree(),
commitToRevert, authorIdent, myIdent, message);
revertCommitBuilder.setMessage(
ChangeIdUtil.insertId(message, computedChangeId, true));
RevCommit revertCommit;
ObjectInserter oi = git.newObjectInserter();
try {
ObjectId id = oi.insert(revertCommitBuilder);
oi.flush();
revertCommit = revWalk.parseCommit(id);
} finally {
oi.release();
}
RefControl refControl = ctl.getRefControl();
Change change = new Change(
new Change.Key("I" + computedChangeId.name()),
new Change.Id(db.get().nextChangeId()),
user().getAccountId(),
changeToRevert.getDest(),
TimeUtil.nowTs());
change.setTopic(changeToRevert.getTopic());
ChangeInserter ins =
changeInserterFactory.create(refControl, change, revertCommit);
PatchSet ps = ins.getPatchSet();
String ref = refControl.getRefName();
String cmdRef = MagicBranch.NEW_PUBLISH_CHANGE
+ ref.substring(ref.lastIndexOf('/') + 1);
CommitReceivedEvent commitReceivedEvent = new CommitReceivedEvent(
new ReceiveCommand(ObjectId.zeroId(), revertCommit.getId(), cmdRef),
refControl.getProjectControl().getProject(),
refControl.getRefName(), revertCommit, user());
try {
commitValidatorsFactory.create(refControl, sshInfo, git)
.validateForGerritCommits(commitReceivedEvent);
} catch (CommitValidationException e) {
throw new InvalidChangeOperationException(e.getMessage());
}
RefUpdate ru = git.updateRef(ps.getRefName());
ru.setExpectedOldObjectId(ObjectId.zeroId());
ru.setNewObjectId(revertCommit);
ru.disableRefLog();
if (ru.update(revWalk) != RefUpdate.Result.NEW) {
throw new IOException(String.format(
"Failed to create ref %s in %s: %s", ps.getRefName(),
change.getDest().getParentKey().get(), ru.getResult()));
}
ChangeMessage cmsg = new ChangeMessage(
new ChangeMessage.Key(changeId, messageUUID(db.get())),
user().getAccountId(), TimeUtil.nowTs(), patchSetId);
StringBuilder msgBuf =
new StringBuilder("Patch Set " + patchSetId.get() + ": Reverted");
msgBuf.append("\n\n");
msgBuf.append("This patchset was reverted in change: " + change.getKey().get());
cmsg.setMessage(msgBuf.toString());
ins.setMessage(cmsg).insert();
try {
RevertedSender cm = revertedSenderFactory.create(change);
cm.setFrom(user().getAccountId());
cm.setChangeMessage(cmsg);
cm.send();
} catch (Exception err) {
log.error("Cannot send email for revert change " + change.getId(),
err);
}
return change.getId();
} finally {
revWalk.release();
}
} finally {
git.close();
}
}
public Change.Id editCommitMessage(ChangeControl ctl, PatchSet.Id patchSetId,
String message, PersonIdent myIdent)
throws NoSuchChangeException, EmailException, OrmException,
MissingObjectException, IncorrectObjectTypeException, IOException,
InvalidChangeOperationException, PatchSetInfoNotAvailableException {
Change.Id changeId = patchSetId.getParentKey();
PatchSet originalPS = db.get().patchSets().get(patchSetId);
if (originalPS == null) {
throw new NoSuchChangeException(changeId);
}
if (message == null || message.length() == 0) {
throw new InvalidChangeOperationException(
"The commit message cannot be empty");
}
Repository git;
try {
git = gitManager.openRepository(ctl.getChange().getProject());
} catch (RepositoryNotFoundException e) {
throw new NoSuchChangeException(changeId, e);
}
try {
RevWalk revWalk = new RevWalk(git);
try {
RevCommit commit =
revWalk.parseCommit(ObjectId.fromString(originalPS.getRevision()
.get()));
if (commit.getFullMessage().equals(message)) {
throw new InvalidChangeOperationException(
"New commit message cannot be same as existing commit message");
}
Date now = myIdent.getWhen();
Change change = db.get().changes().get(changeId);
PersonIdent authorIdent =
user().newCommitterIdent(now, myIdent.getTimeZone());
CommitBuilder commitBuilder = new CommitBuilder();
commitBuilder.setTreeId(commit.getTree());
commitBuilder.setParentIds(commit.getParents());
commitBuilder.setAuthor(commit.getAuthorIdent());
commitBuilder.setCommitter(authorIdent);
commitBuilder.setMessage(message);
RevCommit newCommit;
ObjectInserter oi = git.newObjectInserter();
try {
ObjectId id = oi.insert(commitBuilder);
oi.flush();
newCommit = revWalk.parseCommit(id);
} finally {
oi.release();
}
PatchSet.Id id = nextPatchSetId(git, change.currentPatchSetId());
PatchSet newPatchSet = new PatchSet(id);
newPatchSet.setCreatedOn(new Timestamp(now.getTime()));
newPatchSet.setUploader(user().getAccountId());
newPatchSet.setRevision(new RevId(newCommit.name()));
String msg = "Patch Set " + newPatchSet.getPatchSetId()
+ ": Commit message was updated";
change = patchSetInserterFactory
.create(git, revWalk, ctl.getRefControl(), user(), change, newCommit)
.setPatchSet(newPatchSet)
.setMessage(msg)
.setCopyLabels(true)
.setValidatePolicy(RECEIVE_COMMITS)
.setDraft(originalPS.isDraft())
.insert();
return change.getId();
} finally {
revWalk.release();
}
} finally {
git.close();
}
}
public void deleteDraftChange(PatchSet.Id patchSetId)
throws NoSuchChangeException, OrmException, IOException {
deleteDraftChange(patchSetId.getParentKey());
}
public void deleteDraftChange(Change.Id changeId)
throws NoSuchChangeException, OrmException, IOException {
ReviewDb db = this.db.get();
Change change = db.changes().get(changeId);
if (change == null || change.getStatus() != Change.Status.DRAFT) {
throw new NoSuchChangeException(changeId);
}
for (PatchSet ps : db.patchSets().byChange(changeId)) {
// These should all be draft patch sets.
deleteOnlyDraftPatchSet(ps, change);
}
db.changeMessages().delete(db.changeMessages().byChange(changeId));
db.starredChanges().delete(db.starredChanges().byChange(changeId));
db.changes().delete(Collections.singleton(change));
indexer.delete(change);
}
public void deleteOnlyDraftPatchSet(PatchSet patch, Change change)
throws NoSuchChangeException, OrmException, IOException {
PatchSet.Id patchSetId = patch.getId();
if (!patch.isDraft()) {
throw new NoSuchChangeException(patchSetId.getParentKey());
}
Repository repo = gitManager.openRepository(change.getProject());
try {
RefUpdate update = repo.updateRef(patch.getRefName());
update.setForceUpdate(true);
update.disableRefLog();
switch (update.delete()) {
case NEW:
case FAST_FORWARD:
case FORCED:
case NO_CHANGE:
// Successful deletion.
break;
default:
throw new IOException("Failed to delete ref " + patch.getRefName() +
" in " + repo.getDirectory() + ": " + update.getResult());
}
gitRefUpdated.fire(change.getProject(), update);
} finally {
repo.close();
}
ReviewDb db = this.db.get();
db.accountPatchReviews().delete(db.accountPatchReviews().byPatchSet(patchSetId));
db.changeMessages().delete(db.changeMessages().byPatchSet(patchSetId));
db.patchComments().delete(db.patchComments().byPatchSet(patchSetId));
db.patchSetApprovals().delete(db.patchSetApprovals().byPatchSet(patchSetId));
db.patchSetAncestors().delete(db.patchSetAncestors().byPatchSet(patchSetId));
db.patchSets().delete(Collections.singleton(patch));
}
private IdentifiedUser user() {
return (IdentifiedUser) userProvider.get();
}
private static PatchSet.Id nextPatchSetId(PatchSet.Id id) {
return new PatchSet.Id(id.getParentKey(), id.get() + 1);
}

View File

@ -24,9 +24,6 @@ import com.google.gerrit.reviewdb.client.Change.Status;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.change.DeleteDraftChange.Input;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.index.ChangeIndexer;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gwtorm.server.OrmException;
@ -41,20 +38,14 @@ public class DeleteDraftChange implements
}
protected final Provider<ReviewDb> dbProvider;
private final GitRepositoryManager gitManager;
private final GitReferenceUpdated gitRefUpdated;
private final ChangeIndexer indexer;
private final ChangeUtil changeUtil;
@Inject
public DeleteDraftChange(Provider<ReviewDb> dbProvider,
GitRepositoryManager gitManager,
GitReferenceUpdated gitRefUpdated,
PatchSetInfoFactory patchSetInfoFactory,
ChangeIndexer indexer) {
ChangeUtil changeUtil) {
this.dbProvider = dbProvider;
this.gitManager = gitManager;
this.gitRefUpdated = gitRefUpdated;
this.indexer = indexer;
this.changeUtil = changeUtil;
}
@Override
@ -70,8 +61,7 @@ public class DeleteDraftChange implements
}
try {
ChangeUtil.deleteDraftChange(rsrc.getChange().getId(),
gitManager, gitRefUpdated, dbProvider.get(), indexer);
changeUtil.deleteDraftChange(rsrc.getChange().getId());
} catch (NoSuchChangeException e) {
throw new ResourceNotFoundException(e.getMessage());
}

View File

@ -26,9 +26,6 @@ import com.google.gerrit.reviewdb.client.PatchSetInfo;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.change.DeleteDraftPatchSet.Input;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.index.ChangeIndexer;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
import com.google.gerrit.server.project.NoSuchChangeException;
@ -45,22 +42,16 @@ public class DeleteDraftPatchSet implements RestModifyView<RevisionResource, Inp
}
protected final Provider<ReviewDb> dbProvider;
private final GitRepositoryManager gitManager;
private final GitReferenceUpdated gitRefUpdated;
private final PatchSetInfoFactory patchSetInfoFactory;
private final ChangeIndexer indexer;
private final ChangeUtil changeUtil;
@Inject
public DeleteDraftPatchSet(Provider<ReviewDb> dbProvider,
GitRepositoryManager gitManager,
GitReferenceUpdated gitRefUpdated,
PatchSetInfoFactory patchSetInfoFactory,
ChangeIndexer indexer) {
ChangeUtil changeUtil) {
this.dbProvider = dbProvider;
this.gitManager = gitManager;
this.gitRefUpdated = gitRefUpdated;
this.patchSetInfoFactory = patchSetInfoFactory;
this.indexer = indexer;
this.changeUtil = changeUtil;
}
@Override
@ -104,8 +95,7 @@ public class DeleteDraftPatchSet implements RestModifyView<RevisionResource, Inp
private void deleteDraftPatchSet(PatchSet patchSet, Change change)
throws ResourceNotFoundException, OrmException, IOException {
try {
ChangeUtil.deleteOnlyDraftPatchSet(patchSet,
change, gitManager, gitRefUpdated, dbProvider.get());
changeUtil.deleteOnlyDraftPatchSet(patchSet, change);
} catch (NoSuchChangeException e) {
throw new ResourceNotFoundException(e.getMessage());
}
@ -130,8 +120,7 @@ public class DeleteDraftPatchSet implements RestModifyView<RevisionResource, Inp
private void deleteDraftChange(PatchSet.Id patchSetId)
throws OrmException, IOException, ResourceNotFoundException {
try {
ChangeUtil.deleteDraftChange(patchSetId,
gitManager, gitRefUpdated, dbProvider.get(), indexer);
changeUtil.deleteDraftChange(patchSetId);
} catch (NoSuchChangeException e) {
throw new ResourceNotFoundException(e.getMessage());
}

View File

@ -23,37 +23,26 @@ import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.PatchSet;
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.change.ChangeJson.ChangeInfo;
import com.google.gerrit.server.change.EditMessage.Input;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.mail.CommitMessageEditedSender;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;
class EditMessage implements RestModifyView<RevisionResource, Input>,
UiAction<RevisionResource> {
private final Provider<ReviewDb> dbProvider;
private final CommitMessageEditedSender.Factory commitMessageEditedSenderFactory;
private final GitRepositoryManager gitManager;
private final ChangeUtil changeUtil;
private final PersonIdent myIdent;
private final PatchSetInserter.Factory patchSetInserterFactory;
private final ChangeJson json;
static class Input {
@ -62,17 +51,11 @@ class EditMessage implements RestModifyView<RevisionResource, Input>,
}
@Inject
EditMessage(final Provider<ReviewDb> dbProvider,
final CommitMessageEditedSender.Factory commitMessageEditedSenderFactory,
final GitRepositoryManager gitManager,
final PatchSetInserter.Factory patchSetInserterFactory,
@GerritPersonIdent final PersonIdent myIdent,
EditMessage(ChangeUtil changeUtil,
@GerritPersonIdent PersonIdent myIdent,
ChangeJson json) {
this.dbProvider = dbProvider;
this.commitMessageEditedSenderFactory = commitMessageEditedSenderFactory;
this.gitManager = gitManager;
this.changeUtil = changeUtil;
this.myIdent = myIdent;
this.patchSetInserterFactory = patchSetInserterFactory;
this.json = json;
}
@ -83,22 +66,12 @@ class EditMessage implements RestModifyView<RevisionResource, Input>,
if (Strings.isNullOrEmpty(input.message)) {
throw new BadRequestException("message must be non-empty");
}
final Repository git;
try {
git = gitManager.openRepository(rsrc.getChange().getProject());
} catch (RepositoryNotFoundException e) {
throw new ResourceNotFoundException(e.getMessage());
}
try {
return json.format(ChangeUtil.editCommitMessage(
return json.format(changeUtil.editCommitMessage(
rsrc.getControl(),
rsrc.getPatchSet().getId(),
rsrc.getControl().getRefControl(),
(IdentifiedUser) rsrc.getControl().getCurrentUser(),
input.message, dbProvider.get(),
commitMessageEditedSenderFactory, git, myIdent,
patchSetInserterFactory));
input.message,
myIdent));
} catch (InvalidChangeOperationException e) {
throw new BadRequestException(e.getMessage());
} catch (NoSuchChangeException e) {
@ -106,8 +79,6 @@ class EditMessage implements RestModifyView<RevisionResource, Input>,
} catch (MissingObjectException | IncorrectObjectTypeException
| PatchSetInfoNotAvailableException e) {
throw new ResourceConflictException(e.getMessage());
} finally {
git.close();
}
}

View File

@ -15,7 +15,6 @@
package com.google.gerrit.server.change;
import com.google.common.base.Strings;
import com.google.gerrit.common.ChangeHooks;
import com.google.gerrit.common.errors.EmailException;
import com.google.gerrit.extensions.api.changes.RevertInput;
import com.google.gerrit.extensions.restapi.AuthException;
@ -26,59 +25,33 @@ import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Status;
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.change.ChangeJson.ChangeInfo;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.validators.CommitValidators;
import com.google.gerrit.server.mail.RevertedSender;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.ssh.NoSshInfo;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import java.io.IOException;
public class Revert implements RestModifyView<ChangeResource, RevertInput>,
UiAction<ChangeResource> {
private final ChangeHooks hooks;
private final RevertedSender.Factory revertedSenderFactory;
private final CommitValidators.Factory commitValidatorsFactory;
private final Provider<ReviewDb> dbProvider;
private final ChangeJson json;
private final GitRepositoryManager gitManager;
private final ChangeUtil changeUtil;
private final PersonIdent myIdent;
private final PatchSetInfoFactory patchSetInfoFactory;
private final ChangeInserter.Factory changeInserterFactory;
@Inject
Revert(ChangeHooks hooks,
RevertedSender.Factory revertedSenderFactory,
final CommitValidators.Factory commitValidatorsFactory,
Provider<ReviewDb> dbProvider,
ChangeJson json,
GitRepositoryManager gitManager,
final PatchSetInfoFactory patchSetInfoFactory,
@GerritPersonIdent final PersonIdent myIdent,
final ChangeInserter.Factory changeInserterFactory) {
this.hooks = hooks;
this.revertedSenderFactory = revertedSenderFactory;
this.commitValidatorsFactory = commitValidatorsFactory;
this.dbProvider = dbProvider;
Revert(ChangeJson json,
ChangeUtil changeUtil,
@GerritPersonIdent PersonIdent myIdent) {
this.json = json;
this.gitManager = gitManager;
this.changeUtil = changeUtil;
this.myIdent = myIdent;
this.changeInserterFactory = changeInserterFactory;
this.patchSetInfoFactory = patchSetInfoFactory;
}
@Override
@ -93,26 +66,17 @@ public class Revert implements RestModifyView<ChangeResource, RevertInput>,
throw new ResourceConflictException("change is " + status(change));
}
final Repository git = gitManager.openRepository(control.getProject().getNameKey());
try {
CommitValidators commitValidators =
commitValidatorsFactory.create(control.getRefControl(), new NoSshInfo(), git);
Change.Id revertedChangeId =
ChangeUtil.revert(control.getRefControl(), change.currentPatchSetId(),
(IdentifiedUser) control.getCurrentUser(),
commitValidators,
Strings.emptyToNull(input.message), dbProvider.get(),
revertedSenderFactory, hooks, git, patchSetInfoFactory,
myIdent, changeInserterFactory);
changeUtil.revert(control, change.currentPatchSetId(),
Strings.emptyToNull(input.message),
myIdent, new NoSshInfo());
return json.format(revertedChangeId);
} catch (InvalidChangeOperationException e) {
throw new BadRequestException(e.getMessage());
} catch (NoSuchChangeException e) {
throw new ResourceNotFoundException(e.getMessage());
} finally {
git.close();
}
}

View File

@ -20,8 +20,6 @@ import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.index.ChangeIndexer;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
@ -37,44 +35,38 @@ import java.util.List;
import java.util.concurrent.Callable;
public class DeleteDraftPatchSet implements Callable<ReviewResult> {
public interface Factory {
DeleteDraftPatchSet create(PatchSet.Id patchSetId);
}
private final ChangeControl.Factory changeControlFactory;
private final ReviewDb db;
private final GitRepositoryManager gitManager;
private final GitReferenceUpdated gitRefUpdated;
private final PatchSetInfoFactory patchSetInfoFactory;
private final ChangeIndexer indexer;
private final ChangeUtil changeUtil;
private final PatchSet.Id patchSetId;
@Inject
DeleteDraftPatchSet(ChangeControl.Factory changeControlFactory,
ReviewDb db, GitRepositoryManager gitManager,
GitReferenceUpdated gitRefUpdated, PatchSetInfoFactory patchSetInfoFactory,
ReviewDb db,
PatchSetInfoFactory patchSetInfoFactory,
ChangeIndexer indexer,
@Assisted final PatchSet.Id patchSetId) {
ChangeUtil changeUtil,
@Assisted PatchSet.Id patchSetId) {
this.changeControlFactory = changeControlFactory;
this.db = db;
this.gitManager = gitManager;
this.gitRefUpdated = gitRefUpdated;
this.patchSetInfoFactory = patchSetInfoFactory;
this.indexer = indexer;
this.changeUtil = changeUtil;
this.patchSetId = patchSetId;
}
@Override
public ReviewResult call() throws NoSuchChangeException, OrmException {
final ReviewResult result = new ReviewResult();
ReviewResult result = new ReviewResult();
final Change.Id changeId = patchSetId.getParentKey();
Change.Id changeId = patchSetId.getParentKey();
result.setChangeId(changeId);
final ChangeControl control = changeControlFactory.validateFor(changeId);
final PatchSet patch = db.patchSets().get(patchSetId);
ChangeControl control = changeControlFactory.validateFor(changeId);
PatchSet patch = db.patchSets().get(patchSetId);
if (patch == null) {
throw new NoSuchChangeException(changeId);
}
@ -89,10 +81,10 @@ public class DeleteDraftPatchSet implements Callable<ReviewResult> {
ReviewResult.Error.Type.DELETE_NOT_PERMITTED));
return result;
}
final Change change = control.getChange();
Change change = control.getChange();
try {
ChangeUtil.deleteOnlyDraftPatchSet(patch, change, gitManager, gitRefUpdated, db);
changeUtil.deleteOnlyDraftPatchSet(patch, change);
} catch (IOException e) {
result.addError(new ReviewResult.Error(
ReviewResult.Error.Type.GIT_ERROR, e.getMessage()));
@ -101,8 +93,7 @@ public class DeleteDraftPatchSet implements Callable<ReviewResult> {
List<PatchSet> restOfPatches = db.patchSets().byChange(changeId).toList();
if (restOfPatches.size() == 0) {
try {
ChangeUtil.deleteDraftChange(patchSetId, gitManager, gitRefUpdated, db,
indexer);
changeUtil.deleteDraftChange(patchSetId);
result.setChangeId(null);
} catch (IOException e) {
result.addError(new ReviewResult.Error(