Example usage for org.eclipse.jgit.lib BatchRefUpdate addCommand

List of usage examples for org.eclipse.jgit.lib BatchRefUpdate addCommand

Introduction

In this page you can find the example usage for org.eclipse.jgit.lib BatchRefUpdate addCommand.

Prototype

public BatchRefUpdate addCommand(Collection<ReceiveCommand> cmd) 

Source Link

Document

Add commands to this batch update.

Usage

From source file:com.gitblit.git.GitblitReceivePack.java

License:Apache License

/** Execute commands to update references. */
@Override//from ww  w  .j a  v  a  2s  . c o m
protected void executeCommands() {
    List<ReceiveCommand> toApply = filterCommands(Result.NOT_ATTEMPTED);
    if (toApply.isEmpty()) {
        return;
    }

    ProgressMonitor updating = NullProgressMonitor.INSTANCE;
    boolean sideBand = isCapabilityEnabled(CAPABILITY_SIDE_BAND_64K);
    if (sideBand) {
        SideBandProgressMonitor pm = new SideBandProgressMonitor(msgOut);
        pm.setDelayStart(250, TimeUnit.MILLISECONDS);
        updating = pm;
    }

    BatchRefUpdate batch = getRepository().getRefDatabase().newBatchUpdate();
    batch.setAllowNonFastForwards(isAllowNonFastForwards());
    batch.setRefLogIdent(getRefLogIdent());
    batch.setRefLogMessage("push", true);

    for (ReceiveCommand cmd : toApply) {
        if (Result.NOT_ATTEMPTED != cmd.getResult()) {
            // Already rejected by the core receive process.
            continue;
        }
        batch.addCommand(cmd);
    }

    if (!batch.getCommands().isEmpty()) {
        try {
            batch.execute(getRevWalk(), updating);
        } catch (IOException err) {
            for (ReceiveCommand cmd : toApply) {
                if (cmd.getResult() == Result.NOT_ATTEMPTED) {
                    sendRejection(cmd, "lock error: {0}", err.getMessage());
                }
            }
        }
    }

    //
    // if there are ref update receive commands that were
    // successfully processed and there is an active ticket service for the repository
    // then process any referenced tickets
    //
    if (ticketService != null) {
        List<ReceiveCommand> allUpdates = ReceiveCommand.filter(batch.getCommands(), Result.OK);
        if (!allUpdates.isEmpty()) {
            int ticketsProcessed = 0;
            for (ReceiveCommand cmd : allUpdates) {
                switch (cmd.getType()) {
                case CREATE:
                case UPDATE:
                    if (cmd.getRefName().startsWith(Constants.R_HEADS)) {
                        Collection<TicketModel> tickets = processReferencedTickets(cmd);
                        ticketsProcessed += tickets.size();
                        for (TicketModel ticket : tickets) {
                            ticketNotifier.queueMailing(ticket);
                        }
                    }
                    break;

                case UPDATE_NONFASTFORWARD:
                    if (cmd.getRefName().startsWith(Constants.R_HEADS)) {
                        String base = JGitUtils.getMergeBase(getRepository(), cmd.getOldId(), cmd.getNewId());
                        List<TicketLink> deletedRefs = JGitUtils.identifyTicketsBetweenCommits(getRepository(),
                                settings, base, cmd.getOldId().name());
                        for (TicketLink link : deletedRefs) {
                            link.isDelete = true;
                        }
                        Change deletion = new Change(user.username);
                        deletion.pendingLinks = deletedRefs;
                        ticketService.updateTicket(repository, 0, deletion);

                        Collection<TicketModel> tickets = processReferencedTickets(cmd);
                        ticketsProcessed += tickets.size();
                        for (TicketModel ticket : tickets) {
                            ticketNotifier.queueMailing(ticket);
                        }
                    }
                    break;
                case DELETE:
                    //Identify if the branch has been merged 
                    SortedMap<Integer, String> bases = new TreeMap<Integer, String>();
                    try {
                        ObjectId dObj = cmd.getOldId();
                        Collection<Ref> tips = getRepository().getRefDatabase().getRefs(Constants.R_HEADS)
                                .values();
                        for (Ref ref : tips) {
                            ObjectId iObj = ref.getObjectId();
                            String mergeBase = JGitUtils.getMergeBase(getRepository(), dObj, iObj);
                            if (mergeBase != null) {
                                int d = JGitUtils.countCommits(getRepository(), getRevWalk(), mergeBase,
                                        dObj.name());
                                bases.put(d, mergeBase);
                                //All commits have been merged into some other branch
                                if (d == 0) {
                                    break;
                                }
                            }
                        }

                        if (bases.isEmpty()) {
                            //TODO: Handle orphan branch case
                        } else {
                            if (bases.firstKey() > 0) {
                                //Delete references from the remaining commits that haven't been merged
                                String mergeBase = bases.get(bases.firstKey());
                                List<TicketLink> deletedRefs = JGitUtils.identifyTicketsBetweenCommits(
                                        getRepository(), settings, mergeBase, dObj.name());

                                for (TicketLink link : deletedRefs) {
                                    link.isDelete = true;
                                }
                                Change deletion = new Change(user.username);
                                deletion.pendingLinks = deletedRefs;
                                ticketService.updateTicket(repository, 0, deletion);
                            }
                        }

                    } catch (IOException e) {
                        LOGGER.error(null, e);
                    }
                    break;

                default:
                    break;
                }
            }

            if (ticketsProcessed == 1) {
                sendInfo("1 ticket updated");
            } else if (ticketsProcessed > 1) {
                sendInfo("{0} tickets updated", ticketsProcessed);
            }
        }

        // reset the ticket caches for the repository
        ticketService.resetCaches(repository);
    }
}

From source file:com.gitblit.git.PatchsetReceivePack.java

License:Apache License

/** Execute commands to update references. */
@Override//from w w  w. j av a 2 s.c  o  m
protected void executeCommands() {
    // we process patchsets unless the user is pushing something special
    boolean processPatchsets = true;
    for (ReceiveCommand cmd : filterCommands(Result.NOT_ATTEMPTED)) {
        if (ticketService instanceof BranchTicketService
                && BranchTicketService.BRANCH.equals(cmd.getRefName())) {
            // the user is pushing an update to the BranchTicketService data
            processPatchsets = false;
        }
    }

    // workaround for JGit's awful scoping choices
    //
    // reset the patchset refs to NOT_ATTEMPTED (see validateCommands)
    for (ReceiveCommand cmd : filterCommands(Result.OK)) {
        if (isPatchsetRef(cmd.getRefName())) {
            cmd.setResult(Result.NOT_ATTEMPTED);
        } else if (ticketService instanceof BranchTicketService
                && BranchTicketService.BRANCH.equals(cmd.getRefName())) {
            // the user is pushing an update to the BranchTicketService data
            processPatchsets = false;
        }
    }

    List<ReceiveCommand> toApply = filterCommands(Result.NOT_ATTEMPTED);
    if (toApply.isEmpty()) {
        return;
    }

    ProgressMonitor updating = NullProgressMonitor.INSTANCE;
    boolean sideBand = isCapabilityEnabled(CAPABILITY_SIDE_BAND_64K);
    if (sideBand) {
        SideBandProgressMonitor pm = new SideBandProgressMonitor(msgOut);
        pm.setDelayStart(250, TimeUnit.MILLISECONDS);
        updating = pm;
    }

    BatchRefUpdate batch = getRepository().getRefDatabase().newBatchUpdate();
    batch.setAllowNonFastForwards(isAllowNonFastForwards());
    batch.setRefLogIdent(getRefLogIdent());
    batch.setRefLogMessage("push", true);

    ReceiveCommand patchsetRefCmd = null;
    PatchsetCommand patchsetCmd = null;
    for (ReceiveCommand cmd : toApply) {
        if (Result.NOT_ATTEMPTED != cmd.getResult()) {
            // Already rejected by the core receive process.
            continue;
        }

        if (isPatchsetRef(cmd.getRefName()) && processPatchsets) {

            if (ticketService == null) {
                sendRejection(cmd,
                        "Sorry, the ticket service is unavailable and can not accept patchsets at this time.");
                continue;
            }

            if (!ticketService.isReady()) {
                sendRejection(cmd, "Sorry, the ticket service can not accept patchsets at this time.");
                continue;
            }

            if (UserModel.ANONYMOUS.equals(user)) {
                // server allows anonymous pushes, but anonymous patchset
                // contributions are prohibited by design
                sendRejection(cmd, "Sorry, anonymous patchset contributions are prohibited.");
                continue;
            }

            final Matcher m = NEW_PATCHSET.matcher(cmd.getRefName());
            if (m.matches()) {
                // prohibit pushing directly to a patchset ref
                long id = getTicketId(cmd.getRefName());
                sendError("You may not directly push directly to a patchset ref!");
                sendError("Instead, please push to one the following:");
                sendError(" - {0}{1,number,0}", Constants.R_FOR, id);
                sendError(" - {0}{1,number,0}", Constants.R_TICKET, id);
                sendRejection(cmd, "protected ref");
                continue;
            }

            if (hasRefNamespace(Constants.R_FOR)) {
                // the refs/for/ namespace exists and it must not
                LOGGER.error("{} already has refs in the {} namespace", repository.name, Constants.R_FOR);
                sendRejection(cmd, "Sorry, a repository administrator will have to remove the {} namespace",
                        Constants.R_FOR);
                continue;
            }

            if (cmd.getNewId().equals(ObjectId.zeroId())) {
                // ref deletion request
                if (cmd.getRefName().startsWith(Constants.R_TICKET)) {
                    if (user.canDeleteRef(repository)) {
                        batch.addCommand(cmd);
                    } else {
                        sendRejection(cmd, "Sorry, you do not have permission to delete {}", cmd.getRefName());
                    }
                } else {
                    sendRejection(cmd, "Sorry, you can not delete {}", cmd.getRefName());
                }
                continue;
            }

            if (patchsetRefCmd != null) {
                sendRejection(cmd, "You may only push one patchset at a time.");
                continue;
            }

            LOGGER.info(MessageFormat.format("Verifying {0} push ref \"{1}\" received from {2}",
                    repository.name, cmd.getRefName(), user.username));

            // responsible verification
            String responsible = PatchsetCommand.getSingleOption(cmd, PatchsetCommand.RESPONSIBLE);
            if (!StringUtils.isEmpty(responsible)) {
                UserModel assignee = gitblit.getUserModel(responsible);
                if (assignee == null) {
                    // no account by this name
                    sendRejection(cmd,
                            "{0} can not be assigned any tickets because there is no user account by that name",
                            responsible);
                    continue;
                } else if (!assignee.canPush(repository)) {
                    // account does not have RW permissions
                    sendRejection(cmd,
                            "{0} ({1}) can not be assigned any tickets because the user does not have RW permissions for {2}",
                            assignee.getDisplayName(), assignee.username, repository.name);
                    continue;
                }
            }

            // milestone verification
            String milestone = PatchsetCommand.getSingleOption(cmd, PatchsetCommand.MILESTONE);
            if (!StringUtils.isEmpty(milestone)) {
                TicketMilestone milestoneModel = ticketService.getMilestone(repository, milestone);
                if (milestoneModel == null) {
                    // milestone does not exist
                    sendRejection(cmd, "Sorry, \"{0}\" is not a valid milestone!", milestone);
                    continue;
                }
            }

            // watcher verification
            List<String> watchers = PatchsetCommand.getOptions(cmd, PatchsetCommand.WATCH);
            if (!ArrayUtils.isEmpty(watchers)) {
                boolean verified = true;
                for (String watcher : watchers) {
                    UserModel user = gitblit.getUserModel(watcher);
                    if (user == null) {
                        // watcher does not exist
                        sendRejection(cmd, "Sorry, \"{0}\" is not a valid username for the watch list!",
                                watcher);
                        verified = false;
                        break;
                    }
                }
                if (!verified) {
                    continue;
                }
            }

            patchsetRefCmd = cmd;
            patchsetCmd = preparePatchset(cmd);
            if (patchsetCmd != null) {
                batch.addCommand(patchsetCmd);
            }
            continue;
        }

        batch.addCommand(cmd);
    }

    if (!batch.getCommands().isEmpty()) {
        try {
            batch.execute(getRevWalk(), updating);
        } catch (IOException err) {
            for (ReceiveCommand cmd : toApply) {
                if (cmd.getResult() == Result.NOT_ATTEMPTED) {
                    sendRejection(cmd, "lock error: {0}", err.getMessage());
                    LOGGER.error(
                            MessageFormat.format("failed to lock {0}:{1}", repository.name, cmd.getRefName()),
                            err);
                }
            }
        }
    }

    //
    // set the results into the patchset ref receive command
    //
    if (patchsetRefCmd != null && patchsetCmd != null) {
        if (!patchsetCmd.getResult().equals(Result.OK)) {
            // patchset command failed!
            LOGGER.error(
                    patchsetCmd.getType() + " " + patchsetCmd.getRefName() + " " + patchsetCmd.getResult());
            patchsetRefCmd.setResult(patchsetCmd.getResult(), patchsetCmd.getMessage());
        } else {
            // all patchset commands were applied
            patchsetRefCmd.setResult(Result.OK);

            // update the ticket branch ref
            RefUpdate ru = updateRef(patchsetCmd.getTicketBranch(), patchsetCmd.getNewId(),
                    patchsetCmd.getPatchsetType());
            updateReflog(ru);

            TicketModel ticket = processPatchset(patchsetCmd);
            if (ticket != null) {
                ticketNotifier.queueMailing(ticket);
            }
        }
    }

    //
    // if there are standard ref update receive commands that were
    // successfully processed, process referenced tickets, if any
    //
    List<ReceiveCommand> allUpdates = ReceiveCommand.filter(batch.getCommands(), Result.OK);
    List<ReceiveCommand> refUpdates = excludePatchsetCommands(allUpdates);
    List<ReceiveCommand> stdUpdates = excludeTicketCommands(refUpdates);
    if (!stdUpdates.isEmpty()) {
        int ticketsProcessed = 0;
        for (ReceiveCommand cmd : stdUpdates) {
            switch (cmd.getType()) {
            case CREATE:
            case UPDATE:
                if (cmd.getRefName().startsWith(Constants.R_HEADS)) {
                    Collection<TicketModel> tickets = processReferencedTickets(cmd);
                    ticketsProcessed += tickets.size();
                    for (TicketModel ticket : tickets) {
                        ticketNotifier.queueMailing(ticket);
                    }
                }
                break;

            case UPDATE_NONFASTFORWARD:
                if (cmd.getRefName().startsWith(Constants.R_HEADS)) {
                    String base = JGitUtils.getMergeBase(getRepository(), cmd.getOldId(), cmd.getNewId());
                    List<TicketLink> deletedRefs = JGitUtils.identifyTicketsBetweenCommits(getRepository(),
                            settings, base, cmd.getOldId().name());
                    for (TicketLink link : deletedRefs) {
                        link.isDelete = true;
                    }
                    Change deletion = new Change(user.username);
                    deletion.pendingLinks = deletedRefs;
                    ticketService.updateTicket(repository, 0, deletion);

                    Collection<TicketModel> tickets = processReferencedTickets(cmd);
                    ticketsProcessed += tickets.size();
                    for (TicketModel ticket : tickets) {
                        ticketNotifier.queueMailing(ticket);
                    }
                }
                break;
            default:
                break;
            }
        }

        if (ticketsProcessed == 1) {
            sendInfo("1 ticket updated");
        } else if (ticketsProcessed > 1) {
            sendInfo("{0} tickets updated", ticketsProcessed);
        }
    }

    // reset the ticket caches for the repository
    ticketService.resetCaches(repository);
}

From source file:com.google.gerrit.pgm.RebuildNotedb.java

License:Apache License

private void deleteDraftRefs(Repository allUsersRepo) throws IOException {
    RefDatabase refDb = allUsersRepo.getRefDatabase();
    Map<String, Ref> allRefs = refDb.getRefs(RefNames.REFS_DRAFT_COMMENTS);
    BatchRefUpdate bru = refDb.newBatchUpdate();
    for (Map.Entry<String, Ref> ref : allRefs.entrySet()) {
        bru.addCommand(new ReceiveCommand(ref.getValue().getObjectId(), ObjectId.zeroId(),
                RefNames.REFS_DRAFT_COMMENTS + ref.getKey()));
    }/*from  ww  w  .  jav a2 s .c  om*/
    execute(bru, allUsersRepo);
}

From source file:com.google.gerrit.server.ChangeUtil.java

License:Apache License

public void deleteDraftChange(Change change) throws NoSuchChangeException, OrmException, IOException {
    Change.Id changeId = change.getId();
    if (change.getStatus() != Change.Status.DRAFT) {
        throw new NoSuchChangeException(changeId);
    }/* w  w w.  ja  v  a  2  s .  c om*/

    ReviewDb db = this.db.get();
    db.changes().beginTransaction(change.getId());
    try {
        List<PatchSet> patchSets = db.patchSets().byChange(changeId).toList();
        for (PatchSet ps : patchSets) {
            if (!ps.isDraft()) {
                throw new NoSuchChangeException(changeId);
            }
            db.accountPatchReviews().delete(db.accountPatchReviews().byPatchSet(ps.getId()));
        }

        // No need to delete from notedb; draft patch sets will be filtered out.
        db.patchComments().delete(db.patchComments().byChange(changeId));

        db.patchSetApprovals().delete(db.patchSetApprovals().byChange(changeId));
        db.patchSetAncestors().delete(db.patchSetAncestors().byChange(changeId));
        db.patchSets().delete(patchSets);
        db.changeMessages().delete(db.changeMessages().byChange(changeId));
        db.starredChanges().delete(db.starredChanges().byChange(changeId));
        db.changes().delete(Collections.singleton(change));

        // Delete all refs at once.
        try (Repository repo = gitManager.openRepository(change.getProject()); RevWalk rw = new RevWalk(repo)) {
            String prefix = new PatchSet.Id(changeId, 1).toRefName();
            prefix = prefix.substring(0, prefix.length() - 1);
            BatchRefUpdate ru = repo.getRefDatabase().newBatchUpdate();
            for (Ref ref : repo.getRefDatabase().getRefs(prefix).values()) {
                ru.addCommand(new ReceiveCommand(ref.getObjectId(), ObjectId.zeroId(), ref.getName()));
            }
            ru.execute(rw, NullProgressMonitor.INSTANCE);
            for (ReceiveCommand cmd : ru.getCommands()) {
                if (cmd.getResult() != ReceiveCommand.Result.OK) {
                    throw new IOException("failed: " + cmd + ": " + cmd.getResult());
                }
            }
        }

        db.commit();
        indexer.delete(change.getId());
    } finally {
        db.rollback();
    }
}

From source file:com.google.gerrit.server.CommentsUtil.java

License:Apache License

public void deleteAllDraftsFromAllUsers(Change.Id changeId) throws IOException {
    try (Repository repo = repoManager.openRepository(allUsers); RevWalk rw = new RevWalk(repo)) {
        BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate();
        for (Ref ref : getDraftRefs(repo, changeId)) {
            bru.addCommand(new ReceiveCommand(ref.getObjectId(), ObjectId.zeroId(), ref.getName()));
        }//from w  ww  . j av  a 2s.  co  m
        bru.setRefLogMessage("Delete drafts from NoteDb", false);
        bru.execute(rw, NullProgressMonitor.INSTANCE);
        for (ReceiveCommand cmd : bru.getCommands()) {
            if (cmd.getResult() != ReceiveCommand.Result.OK) {
                throw new IOException(String.format("Failed to delete draft comment ref %s at %s: %s (%s)",
                        cmd.getRefName(), cmd.getOldId(), cmd.getResult(), cmd.getMessage()));
            }
        }
    }
}

From source file:com.google.gerrit.server.edit.ChangeEditModifier.java

License:Apache License

/**
 * Rebase change edit on latest patch set
 *
 * @param edit change edit that contains edit to rebase
 * @param current patch set to rebase the edit on
 * @throws AuthException/*ww w  .j  av  a 2s. c o m*/
 * @throws ResourceConflictException thrown if rebase fails due to merge conflicts
 * @throws InvalidChangeOperationException
 * @throws IOException
 */
public void rebaseEdit(ChangeEdit edit, PatchSet current)
        throws AuthException, ResourceConflictException, InvalidChangeOperationException, IOException {
    if (!currentUser.get().isIdentifiedUser()) {
        throw new AuthException("Authentication required");
    }

    Change change = edit.getChange();
    IdentifiedUser me = (IdentifiedUser) currentUser.get();
    String refName = RefNames.refsEdit(me.getAccountId(), change.getId(), current.getId());
    try (Repository repo = gitManager.openRepository(change.getProject());
            RevWalk rw = new RevWalk(repo);
            ObjectInserter inserter = repo.newObjectInserter()) {
        BatchRefUpdate ru = repo.getRefDatabase().newBatchUpdate();
        RevCommit editCommit = edit.getEditCommit();
        if (editCommit.getParentCount() == 0) {
            throw new InvalidChangeOperationException("Rebase edit against root commit not supported");
        }
        RevCommit tip = rw.parseCommit(ObjectId.fromString(current.getRevision().get()));
        ThreeWayMerger m = MergeStrategy.RESOLVE.newMerger(repo, true);
        m.setObjectInserter(inserter);
        m.setBase(ObjectId.fromString(edit.getBasePatchSet().getRevision().get()));

        if (m.merge(tip, editCommit)) {
            ObjectId tree = m.getResultTreeId();

            CommitBuilder commit = new CommitBuilder();
            commit.setTreeId(tree);
            for (int i = 0; i < tip.getParentCount(); i++) {
                commit.addParentId(tip.getParent(i));
            }
            commit.setAuthor(editCommit.getAuthorIdent());
            commit.setCommitter(new PersonIdent(editCommit.getCommitterIdent(), TimeUtil.nowTs()));
            commit.setMessage(editCommit.getFullMessage());
            ObjectId newEdit = inserter.insert(commit);
            inserter.flush();

            ru.addCommand(new ReceiveCommand(ObjectId.zeroId(), newEdit, refName));
            ru.addCommand(
                    new ReceiveCommand(edit.getRef().getObjectId(), ObjectId.zeroId(), edit.getRefName()));
            ru.execute(rw, NullProgressMonitor.INSTANCE);
            for (ReceiveCommand cmd : ru.getCommands()) {
                if (cmd.getResult() != ReceiveCommand.Result.OK) {
                    throw new IOException("failed: " + cmd);
                }
            }
        } else {
            // TODO(davido): Allow to resolve conflicts inline
            throw new ResourceConflictException("merge conflict");
        }
    }
}

From source file:com.google.gerrit.server.git.ChainedReceiveCommands.java

License:Apache License

/**
 * Add commands from this instance to a native JGit batch update.
 * <p>//w w w.j  a  v  a 2 s  .  c  om
 * Exactly one command per ref will be added to the update. The old SHA-1 will
 * be the old SHA-1 of the first command added to this instance for that ref;
 * the new SHA-1 will be the new SHA-1 of the last command.
 *
 * @param bru batch update
 */
public void addTo(BatchRefUpdate bru) {
    for (ReceiveCommand cmd : commands.values()) {
        bru.addCommand(cmd);
    }
}

From source file:com.google.gerrit.server.git.VersionedMetaData.java

License:Apache License

/**
 * Open a batch of updates to the same metadata ref.
 * <p>// w ww.j  a  v  a2  s.c om
 * 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.
 *
 * @param update helper info about the update.
 * @throws IOException if the update failed.
 */
public BatchMetaDataUpdate openUpdate(final MetaDataUpdate update) throws IOException {
    final Repository db = update.getRepository();

    reader = db.newObjectReader();
    inserter = db.newObjectInserter();
    final RevWalk rw = new RevWalk(reader);
    final RevTree tree = revision != null ? rw.parseTree(revision) : null;
    newTree = readTree(tree);
    return new BatchMetaDataUpdate() {
        AnyObjectId 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;
            try {
                config.newTree = newTree;
                config.reader = reader;
                config.inserter = inserter;
                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;
            }
        }

        @Override
        public void write(VersionedMetaData config, CommitBuilder commit) throws IOException {
            if (!doSave(config, commit)) {
                return;
            }

            // Reuse tree from parent commit unless there are contents in newTree or
            // there is no tree for a parent commit.
            ObjectId res = newTree.getEntryCount() != 0 || srcTree == null ? newTree.writeTree(inserter)
                    : srcTree.copy();
            if (res.equals(srcTree) && !update.allowEmpty() && (commit.getTreeId() == null)) {
                // If there are no changes to the content, don't create the commit.
                return;
            }

            // If changes are made to the DirCache and those changes are written as
            // a commit and then the tree ID is set for the CommitBuilder, then
            // those previous DirCache changes will be ignored and the commit's
            // tree will be replaced with the ID in the CommitBuilder. The same is
            // true if you explicitly set tree ID in a commit and then make changes
            // to the DirCache; that tree ID will be ignored and replaced by that of
            // 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()) {
                ObjectId id = ChangeIdUtil.computeChangeId(res, getRevision(), commit.getAuthor(),
                        commit.getCommitter(), commit.getMessage());
                commit.setMessage(ChangeIdUtil.insertId(commit.getMessage(), id));
            }

            src = inserter.insert(commit);
            srcTree = res;
        }

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

        @Override
        public void removeRef(String refName) throws IOException {
            RefUpdate ru = db.updateRef(refName);
            ru.setForceUpdate(true);
            if (revision != null) {
                ru.setExpectedOldObjectId(revision);
            }
            RefUpdate.Result result = ru.delete();
            switch (result) {
            case FORCED:
                update.fireGitRefUpdatedEvent(ru);
                return;
            default:
                throw new IOException(
                        "Cannot delete " + ru.getName() + " in " + db.getDirectory() + ": " + ru.getResult());
            }
        }

        @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;

            rw.close();
            if (inserter != null) {
                inserter.close();
                inserter = null;
            }

            if (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));
                inserter.flush();
                revision = rw.parseCommit(newId);
                return revision;
            }

            RefUpdate ru = db.updateRef(refName);
            ru.setExpectedOldObjectId(oldId);
            ru.setNewObjectId(src);
            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);
            }
            inserter.flush();
            RefUpdate.Result result = ru.update();
            switch (result) {
            case NEW:
            case FAST_FORWARD:
                revision = rw.parseCommit(ru.getNewObjectId());
                update.fireGitRefUpdatedEvent(ru);
                return revision;
            default:
                throw new IOException(
                        "Cannot update " + ru.getName() + " in " + db.getDirectory() + ": " + ru.getResult());
            }
        }
    };
}

From source file:com.google.gerrit.server.notedb.NoteDbUpdateManagerTest.java

License:Apache License

@SafeVarargs
private static BatchRefUpdate newBatchRefUpdate(Consumer<ReceiveCommand>... resultSetters) {
    try (Repository repo = new InMemoryRepository(new DfsRepositoryDescription("repo"))) {
        BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate();
        for (int i = 0; i < resultSetters.length; i++) {
            ReceiveCommand cmd = new ReceiveCommand(ObjectId.fromString(String.format("%039x1", i)),
                    ObjectId.fromString(String.format("%039x2", i)), "refs/heads/branch" + i);
            bru.addCommand(cmd);
            resultSetters[i].accept(cmd);
        }// w w w .j av a 2s.  com
        return bru;
    }
}

From source file:com.google.gerrit.server.project.DeleteBranches.java

License:Apache License

@Override
public Response<?> apply(ProjectResource project, Input input)
        throws OrmException, IOException, ResourceConflictException {
    input = Input.init(input);//  w  ww .jav a  2  s.  co m
    try (Repository r = repoManager.openRepository(project.getNameKey())) {
        BatchRefUpdate batchUpdate = r.getRefDatabase().newBatchUpdate();
        for (String branch : input.branches) {
            batchUpdate.addCommand(createDeleteCommand(project, r, branch));
        }
        try (RevWalk rw = new RevWalk(r)) {
            batchUpdate.execute(rw, NullProgressMonitor.INSTANCE);
        }
        StringBuilder errorMessages = new StringBuilder();
        for (ReceiveCommand command : batchUpdate.getCommands()) {
            if (command.getResult() == Result.OK) {
                postDeletion(project, command);
            } else {
                appendAndLogErrorMessage(errorMessages, command);
            }
        }
        if (errorMessages.length() > 0) {
            throw new ResourceConflictException(errorMessages.toString());
        }
    }
    return Response.none();
}