Merge changes from topic "gr-apply-fix-dialog-to-ts" * changes: Replace ChangeNum with NumericChangeId Convert files to typescript Rename files to preserve history
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java index d615204..00571b8 100644 --- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java +++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -719,6 +719,7 @@ parseRegularCommand(cmd); } + Map<BranchNameKey, ReceiveCommand> branches; try (BatchUpdate bu = batchUpdateFactory.create( project.getNameKey(), user.materializedCopy(), TimeUtil.nowTs()); @@ -737,41 +738,40 @@ } logger.atFine().log("Added %d additional ref updates", added); bu.execute(); + branches = bu.getSuccessfullyUpdatedBranches(/* dryrun=*/ false); } catch (UpdateException | RestApiException e) { throw new StorageException(e); } - Set<BranchNameKey> branches = new HashSet<>(); - for (ReceiveCommand c : cmds) { - // Most post-update steps should happen in UpdateOneRefOp#postUpdate. The only steps that - // should happen in this loops are things that can't happen within one BatchUpdate because - // they involve kicking off an additional BatchUpdate. - if (c.getResult() != OK) { - continue; - } - if (isHead(c) || isConfig(c)) { - switch (c.getType()) { - case CREATE: - case UPDATE: - case UPDATE_NONFASTFORWARD: - Task closeProgress = progress.beginSubTask("closed", UNKNOWN); - autoCloseChanges(c, closeProgress); - closeProgress.end(); - branches.add(BranchNameKey.create(project.getNameKey(), c.getRefName())); - break; + branches.values().stream() + .filter(c -> isHead(c) || isConfig(c)) + .forEach( + c -> { + // Most post-update steps should happen in UpdateOneRefOp#postUpdate. The only steps + // that + // should happen in this loops are things that can't happen within one BatchUpdate + // because + // they involve kicking off an additional BatchUpdate. + switch (c.getType()) { + case CREATE: + case UPDATE: + case UPDATE_NONFASTFORWARD: + Task closeProgress = progress.beginSubTask("closed", UNKNOWN); + autoCloseChanges(c, closeProgress); + closeProgress.end(); + break; - case DELETE: - break; - } - } - } + case DELETE: + break; + } + }); // Update superproject gitlinks if required. if (!branches.isEmpty()) { try (MergeOpRepoManager orm = ormProvider.get()) { orm.setContext(TimeUtil.nowTs(), user, NotifyResolver.Result.none()); SubmoduleOp op = subOpFactory.create(branches, orm); - op.updateSuperProjects(); + op.updateSuperProjects(false); } catch (RestApiException e) { logger.atWarning().withCause(e).log("Can't update the superprojects"); }
diff --git a/java/com/google/gerrit/server/submit/MergeOp.java b/java/com/google/gerrit/server/submit/MergeOp.java index 8d3324f..5ce7c03 100644 --- a/java/com/google/gerrit/server/submit/MergeOp.java +++ b/java/com/google/gerrit/server/submit/MergeOp.java
@@ -615,9 +615,10 @@ getSubmitStrategies( toSubmit, updateOrderCalculator, submoduleCommits, subscriptionGraph, dryrun); this.allProjects = updateOrderCalculator.getProjectsInOrder(); + List<BatchUpdate> batchUpdates = orm.batchUpdates(allProjects); try { BatchUpdate.execute( - orm.batchUpdates(allProjects), + batchUpdates, new SubmitStrategyListener(submitInput, strategies, commitStatus), dryrun); } finally { @@ -625,6 +626,11 @@ // successful. This is why we must to collect the updated changes also when an exception was // thrown. strategies.forEach(s -> updatedChanges.putAll(s.getUpdatedChanges())); + + // Do not leave executed BatchUpdates in the OpenRepos + if (!dryrun) { + orm.resetUpdates(ImmutableSet.copyOf(this.allProjects)); + } } } catch (NoSuchProjectException e) { throw new ResourceNotFoundException(e.getMessage());
diff --git a/java/com/google/gerrit/server/submit/MergeOpRepoManager.java b/java/com/google/gerrit/server/submit/MergeOpRepoManager.java index b32c712..e31a841 100644 --- a/java/com/google/gerrit/server/submit/MergeOpRepoManager.java +++ b/java/com/google/gerrit/server/submit/MergeOpRepoManager.java
@@ -18,6 +18,7 @@ import static com.google.gerrit.server.project.ProjectCache.noSuchProject; import static java.util.Objects.requireNonNull; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.google.gerrit.entities.BranchNameKey; import com.google.gerrit.entities.Project; @@ -119,6 +120,14 @@ return update; } + // We want to reuse the open repo BUT not the BatchUpdate (because they are already executed) + public void resetUpdate() { + if (update != null) { + update.close(); + update = null; + } + } + private void close() { if (update != null) { update.close(); @@ -206,6 +215,13 @@ return updates; } + public void resetUpdates(ImmutableSet<Project.NameKey> projects) + throws NoSuchProjectException, IOException { + for (Project.NameKey project : projects) { + getRepo(project).resetUpdate(); + } + } + @Override public void close() { for (OpenRepo repo : openRepos.values()) {
diff --git a/java/com/google/gerrit/server/submit/SubmoduleOp.java b/java/com/google/gerrit/server/submit/SubmoduleOp.java index e6f2247..64710c3 100644 --- a/java/com/google/gerrit/server/submit/SubmoduleOp.java +++ b/java/com/google/gerrit/server/submit/SubmoduleOp.java
@@ -19,6 +19,7 @@ import com.google.gerrit.entities.Project; import com.google.gerrit.exceptions.StorageException; import com.google.gerrit.extensions.restapi.RestApiException; +import com.google.gerrit.server.git.CodeReviewCommit; import com.google.gerrit.server.project.NoSuchProjectException; import com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo; import com.google.gerrit.server.update.BatchUpdate; @@ -28,7 +29,8 @@ import com.google.inject.Singleton; import java.io.IOException; import java.util.LinkedHashSet; -import java.util.Set; +import java.util.Map; +import org.eclipse.jgit.transport.ReceiveCommand; public class SubmoduleOp { @@ -45,36 +47,47 @@ this.submoduleCommitsFactory = submoduleCommitsFactory; } - public SubmoduleOp create(Set<BranchNameKey> updatedBranches, MergeOpRepoManager orm) + public SubmoduleOp create( + Map<BranchNameKey, ReceiveCommand> updatedBranches, MergeOpRepoManager orm) throws SubmoduleConflictException { return new SubmoduleOp( + updatedBranches, orm, - subscriptionGraphFactory.compute(updatedBranches, orm), + subscriptionGraphFactory.compute(updatedBranches.keySet(), orm), submoduleCommitsFactory.create(orm)); } } + private final Map<BranchNameKey, ReceiveCommand> updatedBranches; private final MergeOpRepoManager orm; private final SubscriptionGraph subscriptionGraph; private final SubmoduleCommits submoduleCommits; private final UpdateOrderCalculator updateOrderCalculator; private SubmoduleOp( + Map<BranchNameKey, ReceiveCommand> updatedBranches, MergeOpRepoManager orm, SubscriptionGraph subscriptionGraph, SubmoduleCommits submoduleCommits) { + this.updatedBranches = updatedBranches; this.orm = orm; this.subscriptionGraph = subscriptionGraph; this.submoduleCommits = submoduleCommits; this.updateOrderCalculator = new UpdateOrderCalculator(subscriptionGraph); } - public void updateSuperProjects() throws RestApiException { + public void updateSuperProjects(boolean dryrun) throws RestApiException { ImmutableSet<Project.NameKey> projects = updateOrderCalculator.getProjectsInOrder(); if (projects == null) { return; } + if (dryrun) { + // On dryrun, the refs hasn't been updated. + // force the new tips on submoduleCommits + forceRefTips(updatedBranches, submoduleCommits); + } + LinkedHashSet<Project.NameKey> superProjects = new LinkedHashSet<>(); try { GitlinkOp.Factory gitlinkOpFactory = @@ -90,9 +103,29 @@ } } } - BatchUpdate.execute(orm.batchUpdates(superProjects), BatchUpdateListener.NONE, false); + BatchUpdate.execute(orm.batchUpdates(superProjects), BatchUpdateListener.NONE, dryrun); } catch (UpdateException | IOException | NoSuchProjectException e) { throw new StorageException("Cannot update gitlinks", e); } } + + private void forceRefTips( + Map<BranchNameKey, ReceiveCommand> updatedBranches, SubmoduleCommits submoduleCommits) { + // This is dryrun, all commands succeeded (no need to filter success). + for (Map.Entry<BranchNameKey, ReceiveCommand> updateBranch : updatedBranches.entrySet()) { + try { + ReceiveCommand command = updateBranch.getValue(); + if (command.getType() == ReceiveCommand.Type.DELETE) { + continue; + } + + BranchNameKey branchNameKey = updateBranch.getKey(); + OpenRepo openRepo = orm.getRepo(branchNameKey.project()); + CodeReviewCommit fakeTip = openRepo.rw.parseCommit(command.getNewId()); + submoduleCommits.addBranchTip(branchNameKey, fakeTip); + } catch (NoSuchProjectException | IOException e) { + throw new StorageException("Cannot find branch tip target in dryrun", e); + } + } + } }
diff --git a/java/com/google/gerrit/server/update/BatchUpdate.java b/java/com/google/gerrit/server/update/BatchUpdate.java index 166e88d..eb4962d 100644 --- a/java/com/google/gerrit/server/update/BatchUpdate.java +++ b/java/com/google/gerrit/server/update/BatchUpdate.java
@@ -20,6 +20,7 @@ import static com.google.common.flogger.LazyArgs.lazy; import static java.util.Comparator.comparing; import static java.util.Objects.requireNonNull; +import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toSet; import com.google.common.base.Throwables; @@ -33,6 +34,7 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.gerrit.common.Nullable; +import com.google.gerrit.entities.BranchNameKey; import com.google.gerrit.entities.Change; import com.google.gerrit.entities.PatchSet; import com.google.gerrit.entities.PatchSet.Id; @@ -82,6 +84,7 @@ import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.transport.PushCertificate; import org.eclipse.jgit.transport.ReceiveCommand; +import org.eclipse.jgit.transport.ReceiveCommand.Result; /** * Helper for a set of change updates that should be applied to the NoteDb database. @@ -462,6 +465,17 @@ return repoView != null ? repoView.getCommands().getCommands() : ImmutableMap.of(); } + /** + * Return the references successfully updated by this BatchUpdate with their command. In dryrun, + * we assume all updates were successful. + */ + public Map<BranchNameKey, ReceiveCommand> getSuccessfullyUpdatedBranches(boolean dryrun) { + return getRefUpdates().entrySet().stream() + .filter(entry -> dryrun || entry.getValue().getResult() == Result.OK) + .collect( + toMap(entry -> BranchNameKey.create(project, entry.getKey()), Map.Entry::getValue)); + } + public BatchUpdate addOp(Change.Id id, BatchUpdateOp op) { checkArgument(!(op instanceof InsertChangeOp), "use insertChange"); requireNonNull(op);