Search in sources :

Example 11 with LockFailureException

use of com.google.gerrit.git.LockFailureException in project gerrit by GerritCodeReview.

the class DeleteRef method deleteSingleRef.

/**
 * Deletes a single ref from the repository.
 *
 * @param projectState the {@code ProjectState} of the project containing the target ref.
 * @param ref the ref to be deleted.
 * @param prefix the prefix of the ref.
 */
public void deleteSingleRef(ProjectState projectState, String ref, @Nullable String prefix) throws IOException, ResourceConflictException, AuthException, PermissionBackendException {
    if (prefix != null && !ref.startsWith(R_REFS)) {
        ref = prefix + ref;
    }
    projectState.checkStatePermitsWrite();
    permissionBackend.currentUser().project(projectState.getNameKey()).ref(ref).check(RefPermission.DELETE);
    try (Repository repository = repoManager.openRepository(projectState.getNameKey())) {
        RefUpdate.Result result;
        RefUpdate u = repository.updateRef(ref);
        u.setExpectedOldObjectId(repository.exactRef(ref).getObjectId());
        u.setNewObjectId(ObjectId.zeroId());
        u.setForceUpdate(true);
        refDeletionValidator.validateRefOperation(projectState.getName(), identifiedUser.get(), u, /* pushOptions */
        ImmutableListMultimap.of());
        result = u.delete();
        switch(result) {
            case NEW:
            case NO_CHANGE:
            case FAST_FORWARD:
            case FORCED:
                referenceUpdated.fire(projectState.getNameKey(), u, ReceiveCommand.Type.DELETE, identifiedUser.get().state());
                break;
            case REJECTED_CURRENT_BRANCH:
                logger.atFine().log("Cannot delete current branch %s: %s", ref, result.name());
                throw new ResourceConflictException("cannot delete current branch");
            case LOCK_FAILURE:
                throw new LockFailureException(String.format("Cannot delete %s", ref), u);
            case IO_FAILURE:
            case NOT_ATTEMPTED:
            case REJECTED:
            case RENAMED:
            case REJECTED_MISSING_OBJECT:
            case REJECTED_OTHER_REASON:
            default:
                throw new StorageException(String.format("Cannot delete %s: %s", ref, result.name()));
        }
    }
}
Also used : Repository(org.eclipse.jgit.lib.Repository) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) StorageException(com.google.gerrit.exceptions.StorageException) LockFailureException(com.google.gerrit.git.LockFailureException) RefUpdate(org.eclipse.jgit.lib.RefUpdate) BatchRefUpdate(org.eclipse.jgit.lib.BatchRefUpdate)

Example 12 with LockFailureException

use of com.google.gerrit.git.LockFailureException in project gerrit by GerritCodeReview.

the class VersionedMetaData method openUpdate.

/**
 * Open a batch of updates to the same metadata ref.
 *
 * <p>This allows making multiple commits to a single metadata ref, at the end of which is a
 * single ref update. For batching together updates to multiple refs (each consisting of one or
 * more commits against their respective refs), create the {@link MetaDataUpdate} with a {@link
 * BatchRefUpdate}.
 *
 * <p>A ref update produced by this {@link BatchMetaDataUpdate} is only committed if there is no
 * associated {@link BatchRefUpdate}. As a result, the configured ref updated event is not fired
 * if there is an associated batch.
 *
 * <p>If object inserter, reader and revwalk are provided, then the updates are not flushed,
 * allowing callers the flexibility to flush only once after several updates.
 *
 * @param update helper info about the update.
 * @param objInserter Shared object inserter.
 * @param objReader Shared object reader.
 * @param revWalk Shared rev walk.
 * @throws IOException if the update failed.
 */
public BatchMetaDataUpdate openUpdate(MetaDataUpdate update, ObjectInserter objInserter, ObjectReader objReader, RevWalk revWalk) throws IOException {
    final Repository db = update.getRepository();
    inserter = objInserter == null ? db.newObjectInserter() : objInserter;
    reader = objReader == null ? inserter.newReader() : objReader;
    final RevWalk rw = revWalk == null ? new RevWalk(reader) : revWalk;
    final RevTree tree = revision != null ? rw.parseTree(revision) : null;
    newTree = readTree(tree);
    return new BatchMetaDataUpdate() {

        RevCommit src = revision;

        AnyObjectId srcTree = tree;

        @Override
        public void write(CommitBuilder commit) throws IOException {
            write(VersionedMetaData.this, commit);
        }

        private boolean doSave(VersionedMetaData config, CommitBuilder commit) throws IOException {
            DirCache nt = config.newTree;
            ObjectReader r = config.reader;
            ObjectInserter i = config.inserter;
            RevCommit c = config.revision;
            try {
                config.newTree = newTree;
                config.reader = reader;
                config.inserter = inserter;
                config.revision = src;
                return config.onSave(commit);
            } catch (ConfigInvalidException e) {
                throw new IOException("Cannot update " + getRefName() + " in " + db.getDirectory() + ": " + e.getMessage(), e);
            } finally {
                config.newTree = nt;
                config.reader = r;
                config.inserter = i;
                config.revision = c;
            }
        }

        @Override
        public void write(VersionedMetaData config, CommitBuilder commit) throws IOException {
            checkSameRef(config);
            if (!doSave(config, commit)) {
                return;
            }
            ObjectId res = newTree.writeTree(inserter);
            if (res.equals(srcTree) && !update.allowEmpty() && (commit.getTreeId() == null)) {
                // If there are no changes to the content, don't create the commit.
                return;
            }
            // the tree for the updated DirCache.
            if (commit.getTreeId() == null) {
                commit.setTreeId(res);
            } else {
                // In this case, the caller populated the tree without using DirCache.
                res = commit.getTreeId();
            }
            if (src != null) {
                commit.addParentId(src);
            }
            if (update.insertChangeId()) {
                commit.setMessage(ChangeIdUtil.insertId(commit.getMessage(), CommitMessageUtil.generateChangeId()));
            }
            src = rw.parseCommit(inserter.insert(commit));
            srcTree = res;
        }

        private void checkSameRef(VersionedMetaData other) {
            String thisRef = VersionedMetaData.this.getRefName();
            String otherRef = other.getRefName();
            checkArgument(otherRef.equals(thisRef), "cannot add %s for %s to %s on %s", other.getClass().getSimpleName(), otherRef, BatchMetaDataUpdate.class.getSimpleName(), thisRef);
        }

        @Override
        public RevCommit createRef(String refName) throws IOException {
            if (Objects.equals(src, revision)) {
                return revision;
            }
            return updateRef(ObjectId.zeroId(), src, refName);
        }

        @Override
        public RevCommit commit() throws IOException {
            return commitAt(revision);
        }

        @Override
        public RevCommit commitAt(ObjectId expected) throws IOException {
            if (Objects.equals(src, expected)) {
                return revision;
            }
            return updateRef(MoreObjects.firstNonNull(expected, ObjectId.zeroId()), src, getRefName());
        }

        @Override
        public void close() {
            newTree = null;
            if (revWalk == null) {
                rw.close();
            }
            if (objInserter == null && inserter != null) {
                inserter.close();
                inserter = null;
            }
            if (objReader == null && reader != null) {
                reader.close();
                reader = null;
            }
        }

        private RevCommit updateRef(AnyObjectId oldId, AnyObjectId newId, String refName) throws IOException {
            BatchRefUpdate bru = update.getBatch();
            if (bru != null) {
                bru.addCommand(new ReceiveCommand(oldId.toObjectId(), newId.toObjectId(), refName));
                if (objInserter == null) {
                    inserter.flush();
                }
                revision = rw.parseCommit(newId);
                return revision;
            }
            RefUpdate ru = db.updateRef(refName);
            ru.setExpectedOldObjectId(oldId);
            ru.setNewObjectId(newId);
            ru.setRefLogIdent(update.getCommitBuilder().getAuthor());
            String message = update.getCommitBuilder().getMessage();
            if (message == null) {
                message = "meta data update";
            }
            try (BufferedReader reader = new BufferedReader(new StringReader(message))) {
                // read the subject line and use it as reflog message
                ru.setRefLogMessage("commit: " + reader.readLine(), true);
            }
            logger.atFine().log("Saving commit '%s' on project '%s'", message.trim(), projectName);
            inserter.flush();
            RefUpdate.Result result = ru.update();
            switch(result) {
                case NEW:
                case FAST_FORWARD:
                    revision = rw.parseCommit(ru.getNewObjectId());
                    update.fireGitRefUpdatedEvent(ru);
                    logger.atFine().log("Saved commit '%s' as revision '%s' on project '%s'", message.trim(), revision.name(), projectName);
                    return revision;
                case LOCK_FAILURE:
                    throw new LockFailureException(errorMsg(ru, db.getDirectory()), ru);
                case FORCED:
                case IO_FAILURE:
                case NOT_ATTEMPTED:
                case NO_CHANGE:
                case REJECTED:
                case REJECTED_CURRENT_BRANCH:
                case RENAMED:
                case REJECTED_MISSING_OBJECT:
                case REJECTED_OTHER_REASON:
                default:
                    throw new GitUpdateFailureException(errorMsg(ru, db.getDirectory()), ru);
            }
        }
    };
}
Also used : ReceiveCommand(org.eclipse.jgit.transport.ReceiveCommand) GitUpdateFailureException(com.google.gerrit.git.GitUpdateFailureException) ConfigInvalidException(org.eclipse.jgit.errors.ConfigInvalidException) AnyObjectId(org.eclipse.jgit.lib.AnyObjectId) ObjectId(org.eclipse.jgit.lib.ObjectId) CommitBuilder(org.eclipse.jgit.lib.CommitBuilder) IOException(java.io.IOException) RevWalk(org.eclipse.jgit.revwalk.RevWalk) LockFailureException(com.google.gerrit.git.LockFailureException) AnyObjectId(org.eclipse.jgit.lib.AnyObjectId) DirCache(org.eclipse.jgit.dircache.DirCache) Repository(org.eclipse.jgit.lib.Repository) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) BufferedReader(java.io.BufferedReader) StringReader(java.io.StringReader) ObjectReader(org.eclipse.jgit.lib.ObjectReader) RevTree(org.eclipse.jgit.revwalk.RevTree) BatchRefUpdate(org.eclipse.jgit.lib.BatchRefUpdate) RevCommit(org.eclipse.jgit.revwalk.RevCommit) RefUpdate(org.eclipse.jgit.lib.RefUpdate) BatchRefUpdate(org.eclipse.jgit.lib.BatchRefUpdate)

Example 13 with LockFailureException

use of com.google.gerrit.git.LockFailureException in project gerrit by GerritCodeReview.

the class MergeOp method integrateIntoHistory.

private void integrateIntoHistory(ChangeSet cs, SubmissionExecutor submissionExecutor) throws RestApiException, UpdateException {
    checkArgument(!cs.furtherHiddenChanges(), "cannot integrate hidden changes into history");
    logger.atFine().log("Beginning merge attempt on %s", cs);
    Map<BranchNameKey, BranchBatch> toSubmit = new HashMap<>();
    ListMultimap<BranchNameKey, ChangeData> cbb;
    try {
        cbb = cs.changesByBranch();
    } catch (StorageException e) {
        throw new StorageException("Error reading changes to submit", e);
    }
    Set<BranchNameKey> branches = cbb.keySet();
    for (BranchNameKey branch : branches) {
        OpenRepo or = openRepo(branch.project());
        if (or != null) {
            toSubmit.put(branch, validateChangeList(or, cbb.get(branch)));
        }
    }
    // Done checks that don't involve running submit strategies.
    commitStatus.maybeFailVerbose();
    try {
        SubscriptionGraph subscriptionGraph = subscriptionGraphFactory.compute(branches, orm);
        SubmoduleCommits submoduleCommits = submoduleCommitsFactory.create(orm);
        UpdateOrderCalculator updateOrderCalculator = new UpdateOrderCalculator(subscriptionGraph);
        List<SubmitStrategy> strategies = getSubmitStrategies(toSubmit, updateOrderCalculator, submoduleCommits, subscriptionGraph, dryrun);
        this.allProjects = updateOrderCalculator.getProjectsInOrder();
        List<BatchUpdate> batchUpdates = orm.batchUpdates(allProjects);
        // Group batch updates by project
        Map<Project.NameKey, BatchUpdate> batchUpdatesByProject = batchUpdates.stream().collect(Collectors.toMap(b -> b.getProject(), Function.identity()));
        for (Map.Entry<Change.Id, ChangeData> entry : cs.changesById().entrySet()) {
            Project.NameKey project = entry.getValue().project();
            Change.Id changeId = entry.getKey();
            ChangeData cd = entry.getValue();
            batchUpdatesByProject.get(project).addOp(changeId, storeSubmitRequirementsOpFactory.create(cd.submitRequirementsIncludingLegacy().values(), cd));
        }
        try {
            submissionExecutor.setAdditionalBatchUpdateListeners(ImmutableList.of(new SubmitStrategyListener(submitInput, strategies, commitStatus)));
            submissionExecutor.execute(batchUpdates);
        } finally {
            // If the BatchUpdate fails it can be that merging some of the changes was actually
            // 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());
    } catch (IOException e) {
        throw new StorageException(e);
    } catch (SubmoduleConflictException e) {
        throw new IntegrationConflictException(e.getMessage(), e);
    } catch (UpdateException e) {
        if (e.getCause() instanceof LockFailureException) {
            // as to be unnoticeable, assuming RetryHelper is retrying sufficiently.
            throw e;
        }
        // inner IntegrationConflictException to a ResourceConflictException.
        if (e.getCause() instanceof IntegrationConflictException) {
            throw (IntegrationConflictException) e.getCause();
        }
        throw new MergeUpdateException(genericMergeError(cs), e);
    }
}
Also used : ResourceNotFoundException(com.google.gerrit.extensions.restapi.ResourceNotFoundException) SuperprojectUpdateOnSubmission(com.google.gerrit.server.update.SuperprojectUpdateOnSubmission) ListMultimap(com.google.common.collect.ListMultimap) MultimapBuilder(com.google.common.collect.MultimapBuilder) InternalUser(com.google.gerrit.server.InternalUser) Inject(com.google.inject.Inject) SubmissionId(com.google.gerrit.entities.SubmissionId) UpdateException(com.google.gerrit.server.update.UpdateException) SubmitRequirementResult(com.google.gerrit.entities.SubmitRequirementResult) MergeUpdateException(com.google.gerrit.exceptions.MergeUpdateException) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) BatchUpdate(com.google.gerrit.server.update.BatchUpdate) SubmitInput(com.google.gerrit.extensions.api.changes.SubmitInput) Map(java.util.Map) AuthException(com.google.gerrit.extensions.restapi.AuthException) StoreSubmitRequirementsOp(com.google.gerrit.server.notedb.StoreSubmitRequirementsOp) RetryHelper(com.google.gerrit.server.update.RetryHelper) MergeTip(com.google.gerrit.server.git.MergeTip) Collectors.toSet(java.util.stream.Collectors.toSet) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) ImmutableSet(com.google.common.collect.ImmutableSet) Status(com.google.gerrit.entities.Change.Status) ImmutableMap(com.google.common.collect.ImmutableMap) TraceContext(com.google.gerrit.server.logging.TraceContext) SubmitType(com.google.gerrit.extensions.client.SubmitType) Collection(java.util.Collection) Set(java.util.Set) Constants(org.eclipse.jgit.lib.Constants) CodeReviewCommit(com.google.gerrit.server.git.CodeReviewCommit) Instant(java.time.Instant) RetryListener(com.github.rholder.retry.RetryListener) SubmitRecord(com.google.gerrit.entities.SubmitRecord) Collectors(java.util.stream.Collectors) BranchNameKey(com.google.gerrit.entities.BranchNameKey) NotifyHandling(com.google.gerrit.extensions.api.changes.NotifyHandling) SubmitTypeRecord(com.google.gerrit.entities.SubmitTypeRecord) ChangeData(com.google.gerrit.server.query.change.ChangeData) List(java.util.List) Nullable(com.google.gerrit.common.Nullable) Ref(org.eclipse.jgit.lib.Ref) AutoValue(com.google.auto.value.AutoValue) InternalChangeQuery(com.google.gerrit.server.query.change.InternalChangeQuery) Optional(java.util.Optional) MoreObjects.firstNonNull(com.google.common.base.MoreObjects.firstNonNull) Counter0(com.google.gerrit.metrics.Counter0) MetricMaker(com.google.gerrit.metrics.MetricMaker) BatchUpdateOp(com.google.gerrit.server.update.BatchUpdateOp) FluentLogger(com.google.common.flogger.FluentLogger) Joiner(com.google.common.base.Joiner) ChangeMessagesUtil(com.google.gerrit.server.ChangeMessagesUtil) Singleton(com.google.inject.Singleton) PermissionBackendException(com.google.gerrit.server.permissions.PermissionBackendException) ConfigInvalidException(org.eclipse.jgit.errors.ConfigInvalidException) RevCommit(org.eclipse.jgit.revwalk.RevCommit) OpenRepo(com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo) IncorrectObjectTypeException(org.eclipse.jgit.errors.IncorrectObjectTypeException) HashMap(java.util.HashMap) Function(java.util.function.Function) SubmissionListener(com.google.gerrit.server.update.SubmissionListener) MergeValidators(com.google.gerrit.server.git.validators.MergeValidators) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) ImmutableList(com.google.common.collect.ImmutableList) SubmissionExecutor(com.google.gerrit.server.update.SubmissionExecutor) Description(com.google.gerrit.metrics.Description) Objects.requireNonNull(java.util.Objects.requireNonNull) Change(com.google.gerrit.entities.Change) PatchSet(com.google.gerrit.entities.PatchSet) Comparator.comparing(java.util.Comparator.comparing) RestApiException(com.google.gerrit.extensions.restapi.RestApiException) ChangeUtil(com.google.gerrit.server.ChangeUtil) LockFailureException(com.google.gerrit.git.LockFailureException) ChangeContext(com.google.gerrit.server.update.ChangeContext) MergeValidationException(com.google.gerrit.server.git.validators.MergeValidationException) LinkedHashSet(java.util.LinkedHashSet) SubmitRequirement(com.google.gerrit.entities.SubmitRequirement) NotifyResolver(com.google.gerrit.server.change.NotifyResolver) OpenBranch(com.google.gerrit.server.submit.MergeOpRepoManager.OpenBranch) StorageException(com.google.gerrit.exceptions.StorageException) Attempt(com.github.rholder.retry.Attempt) NoSuchProjectException(com.google.gerrit.server.project.NoSuchProjectException) ChangeNotes(com.google.gerrit.server.notedb.ChangeNotes) IOException(java.io.IOException) SubmitRuleOptions(com.google.gerrit.server.project.SubmitRuleOptions) SetMultimap(com.google.common.collect.SetMultimap) ObjectId(org.eclipse.jgit.lib.ObjectId) Provider(com.google.inject.Provider) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) IdentifiedUser(com.google.gerrit.server.IdentifiedUser) Project(com.google.gerrit.entities.Project) TimeUtil(com.google.gerrit.server.util.time.TimeUtil) RequestId(com.google.gerrit.server.logging.RequestId) HashMap(java.util.HashMap) NoSuchProjectException(com.google.gerrit.server.project.NoSuchProjectException) BatchUpdate(com.google.gerrit.server.update.BatchUpdate) LockFailureException(com.google.gerrit.git.LockFailureException) BranchNameKey(com.google.gerrit.entities.BranchNameKey) UpdateException(com.google.gerrit.server.update.UpdateException) MergeUpdateException(com.google.gerrit.exceptions.MergeUpdateException) ResourceNotFoundException(com.google.gerrit.extensions.restapi.ResourceNotFoundException) Change(com.google.gerrit.entities.Change) IOException(java.io.IOException) ChangeData(com.google.gerrit.server.query.change.ChangeData) BranchNameKey(com.google.gerrit.entities.BranchNameKey) MergeUpdateException(com.google.gerrit.exceptions.MergeUpdateException) Project(com.google.gerrit.entities.Project) OpenRepo(com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo) SubmissionId(com.google.gerrit.entities.SubmissionId) ObjectId(org.eclipse.jgit.lib.ObjectId) RequestId(com.google.gerrit.server.logging.RequestId) StorageException(com.google.gerrit.exceptions.StorageException) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) HashMap(java.util.HashMap)

Aggregations

LockFailureException (com.google.gerrit.git.LockFailureException)13 RefUpdate (org.eclipse.jgit.lib.RefUpdate)10 IOException (java.io.IOException)7 BatchRefUpdate (org.eclipse.jgit.lib.BatchRefUpdate)5 ObjectId (org.eclipse.jgit.lib.ObjectId)5 Repository (org.eclipse.jgit.lib.Repository)5 StorageException (com.google.gerrit.exceptions.StorageException)4 RevWalk (org.eclipse.jgit.revwalk.RevWalk)4 ResourceConflictException (com.google.gerrit.extensions.restapi.ResourceConflictException)3 ObjectInserter (org.eclipse.jgit.lib.ObjectInserter)3 BranchNameKey (com.google.gerrit.entities.BranchNameKey)2 ConfigInvalidException (org.eclipse.jgit.errors.ConfigInvalidException)2 Ref (org.eclipse.jgit.lib.Ref)2 RevCommit (org.eclipse.jgit.revwalk.RevCommit)2 Attempt (com.github.rholder.retry.Attempt)1 RetryListener (com.github.rholder.retry.RetryListener)1 AutoValue (com.google.auto.value.AutoValue)1 Joiner (com.google.common.base.Joiner)1 MoreObjects.firstNonNull (com.google.common.base.MoreObjects.firstNonNull)1 Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)1