Example usage for org.eclipse.jgit.transport ReceiveCommand getOldId

List of usage examples for org.eclipse.jgit.transport ReceiveCommand getOldId

Introduction

In this page you can find the example usage for org.eclipse.jgit.transport ReceiveCommand getOldId.

Prototype

public ObjectId getOldId() 

Source Link

Document

Get the old value the client thinks the ref has.

Usage

From source file:actors.PostReceiveActor.java

License:Apache License

protected Collection<? extends RevCommit> parseCommitsFrom(ReceiveCommand command, Project project) {
    Repository repository = GitRepository.buildGitRepository(project);
    List<RevCommit> list = new ArrayList<>();

    try {/*from w ww. j av a 2s  . com*/
        ObjectId endRange = command.getNewId();
        ObjectId startRange = command.getOldId();

        RevWalk rw = new RevWalk(repository);
        rw.markStart(rw.parseCommit(endRange));
        if (startRange.equals(ObjectId.zeroId())) {
            // maybe this is a tag or an orphan branch
            list.add(rw.parseCommit(endRange));
            rw.dispose();
            return list;
        } else {
            rw.markUninteresting(rw.parseCommit(startRange));
        }

        for (RevCommit rev : rw) {
            list.add(rev);
        }
        rw.dispose();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return list;
}

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

License:Apache License

/**
 * Instrumentation point where the incoming push event has been parsed,
 * validated, objects created BUT refs have not been updated. You might
 * use this to enforce a branch-write permissions model.
 *//*w  w w . ja v  a  2 s  .  c o  m*/
@Override
public void onPreReceive(ReceivePack rp, Collection<ReceiveCommand> commands) {

    if (commands.size() == 0) {
        // no receive commands to process
        // this can happen if receive pack subclasses intercept and filter
        // the commands
        LOGGER.debug("skipping pre-receive processing, no refs created, updated, or removed");
        return;
    }

    if (repository.isMirror) {
        // repository is a mirror
        for (ReceiveCommand cmd : commands) {
            sendRejection(cmd, "Gitblit does not allow pushes to \"{0}\" because it is a mirror!",
                    repository.name);
        }
        return;
    }

    if (repository.isFrozen) {
        // repository is frozen/readonly
        for (ReceiveCommand cmd : commands) {
            sendRejection(cmd, "Gitblit does not allow pushes to \"{0}\" because it is frozen!",
                    repository.name);
        }
        return;
    }

    if (!repository.isBare) {
        // repository has a working copy
        for (ReceiveCommand cmd : commands) {
            sendRejection(cmd, "Gitblit does not allow pushes to \"{0}\" because it has a working copy!",
                    repository.name);
        }
        return;
    }

    if (!canPush(commands)) {
        // user does not have push permissions
        for (ReceiveCommand cmd : commands) {
            sendRejection(cmd, "User \"{0}\" does not have push permissions for \"{1}\"!", user.username,
                    repository.name);
        }
        return;
    }

    if (repository.accessRestriction.atLeast(AccessRestrictionType.PUSH) && repository.verifyCommitter) {
        // enforce committer verification
        if (StringUtils.isEmpty(user.emailAddress)) {
            // reject the push because the pushing account does not have an email address
            for (ReceiveCommand cmd : commands) {
                sendRejection(cmd,
                        "Sorry, the account \"{0}\" does not have an email address set for committer verification!",
                        user.username);
            }
            return;
        }

        // Optionally enforce that the committer of first parent chain
        // match the account being used to push the commits.
        //
        // This requires all merge commits are executed with the "--no-ff"
        // option to force a merge commit even if fast-forward is possible.
        // This ensures that the chain first parents has the commit
        // identity of the merging user.
        boolean allRejected = false;
        for (ReceiveCommand cmd : commands) {
            String firstParent = null;
            try {
                List<RevCommit> commits = JGitUtils.getRevLog(rp.getRepository(), cmd.getOldId().name(),
                        cmd.getNewId().name());
                for (RevCommit commit : commits) {

                    if (firstParent != null) {
                        if (!commit.getName().equals(firstParent)) {
                            // ignore: commit is right-descendant of a merge
                            continue;
                        }
                    }

                    // update expected next commit id
                    if (commit.getParentCount() == 0) {
                        firstParent = null;
                    } else {
                        firstParent = commit.getParents()[0].getId().getName();
                    }

                    PersonIdent committer = commit.getCommitterIdent();
                    if (!user.is(committer.getName(), committer.getEmailAddress())) {
                        // verification failed
                        String reason = MessageFormat.format(
                                "{0} by {1} <{2}> was not committed by {3} ({4}) <{5}>", commit.getId().name(),
                                committer.getName(),
                                StringUtils.isEmpty(committer.getEmailAddress()) ? "?"
                                        : committer.getEmailAddress(),
                                user.getDisplayName(), user.username, user.emailAddress);
                        LOGGER.warn(reason);
                        cmd.setResult(Result.REJECTED_OTHER_REASON, reason);
                        allRejected &= true;
                        break;
                    } else {
                        allRejected = false;
                    }
                }
            } catch (Exception e) {
                LOGGER.error("Failed to verify commits were made by pushing user", e);
            }
        }

        if (allRejected) {
            // all ref updates rejected, abort
            return;
        }
    }

    for (ReceiveCommand cmd : commands) {
        String ref = cmd.getRefName();
        if (ref.startsWith(Constants.R_HEADS)) {
            switch (cmd.getType()) {
            case UPDATE_NONFASTFORWARD:
            case DELETE:
                // reset branch commit cache on REWIND and DELETE
                CommitCache.instance().clear(repository.name, ref);
                break;
            default:
                break;
            }
        } else if (ref.equals(BranchTicketService.BRANCH)) {
            // ensure pushing user is an administrator OR an owner
            // i.e. prevent ticket tampering
            boolean permitted = user.canAdmin() || repository.isOwner(user.username);
            if (!permitted) {
                sendRejection(cmd, "{0} is not permitted to push to {1}", user.username, ref);
            }
        } else if (ref.startsWith(Constants.R_FOR)) {
            // prevent accidental push to refs/for
            sendRejection(cmd, "{0} is not configured to receive patchsets", repository.name);
        }
    }

    // call pre-receive plugins
    for (ReceiveHook hook : gitblit.getExtensions(ReceiveHook.class)) {
        try {
            hook.onPreReceive(this, commands);
        } catch (Exception e) {
            LOGGER.error("Failed to execute extension", e);
        }
    }

    Set<String> scripts = new LinkedHashSet<String>();
    scripts.addAll(gitblit.getPreReceiveScriptsInherited(repository));
    if (!ArrayUtils.isEmpty(repository.preReceiveScripts)) {
        scripts.addAll(repository.preReceiveScripts);
    }
    runGroovy(commands, scripts);
    for (ReceiveCommand cmd : commands) {
        if (!Result.NOT_ATTEMPTED.equals(cmd.getResult())) {
            LOGGER.warn(MessageFormat.format("{0} {1} because \"{2}\"", cmd.getNewId().getName(),
                    cmd.getResult(), cmd.getMessage()));
        }
    }
}

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

License:Apache License

/**
 * Log the ref changes in the container log.
 *
 * @param commands//from w  w  w  . jav a  2 s.  c  o  m
 */
protected void logRefChange(Collection<ReceiveCommand> commands) {
    boolean isRefCreationOrDeletion = false;

    // log ref changes
    for (ReceiveCommand cmd : commands) {

        if (Result.OK.equals(cmd.getResult())) {
            // add some logging for important ref changes
            switch (cmd.getType()) {
            case DELETE:
                LOGGER.info(MessageFormat.format("{0} DELETED {1} in {2} ({3})", user.username,
                        cmd.getRefName(), repository.name, cmd.getOldId().name()));
                isRefCreationOrDeletion = true;
                break;
            case CREATE:
                LOGGER.info(MessageFormat.format("{0} CREATED {1} in {2}", user.username, cmd.getRefName(),
                        repository.name));
                isRefCreationOrDeletion = true;
                break;
            case UPDATE:
                LOGGER.info(MessageFormat.format("{0} UPDATED {1} in {2} (from {3} to {4})", user.username,
                        cmd.getRefName(), repository.name, cmd.getOldId().name(), cmd.getNewId().name()));
                break;
            case UPDATE_NONFASTFORWARD:
                LOGGER.info(MessageFormat.format("{0} UPDATED NON-FAST-FORWARD {1} in {2} (from {3} to {4})",
                        user.username, cmd.getRefName(), repository.name, cmd.getOldId().name(),
                        cmd.getNewId().name()));
                break;
            default:
                break;
            }
        }
    }

    if (isRefCreationOrDeletion) {
        gitblit.resetRepositoryCache(repository.name);
    }
}

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

License:Apache License

/** Execute commands to update references. */
@Override/*from w w  w  .  ja  v a2 s  .  c om*/
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.GitblitReceivePack.java

License:Apache License

/**
 * Automatically closes open tickets and adds references to tickets if made in the commit message.
 *
 * @param cmd/* w  w w  .  j a  v a 2s  . com*/
 */
private Collection<TicketModel> processReferencedTickets(ReceiveCommand cmd) {
    Map<Long, TicketModel> changedTickets = new LinkedHashMap<Long, TicketModel>();

    final RevWalk rw = getRevWalk();
    try {
        rw.reset();
        rw.markStart(rw.parseCommit(cmd.getNewId()));
        if (!ObjectId.zeroId().equals(cmd.getOldId())) {
            rw.markUninteresting(rw.parseCommit(cmd.getOldId()));
        }

        RevCommit c;
        while ((c = rw.next()) != null) {
            rw.parseBody(c);
            List<TicketLink> ticketLinks = JGitUtils.identifyTicketsFromCommitMessage(getRepository(), settings,
                    c);
            if (ticketLinks == null) {
                continue;
            }

            for (TicketLink link : ticketLinks) {

                TicketModel ticket = ticketService.getTicket(repository, link.targetTicketId);
                if (ticket == null) {
                    continue;
                }

                Change change = null;
                String commitSha = c.getName();
                String branchName = Repository.shortenRefName(cmd.getRefName());

                switch (link.action) {
                case Commit: {
                    //A commit can reference a ticket in any branch even if the ticket is closed.
                    //This allows developers to identify and communicate related issues
                    change = new Change(user.username);
                    change.referenceCommit(commitSha);
                }
                    break;

                case Close: {
                    // As this isn't a patchset theres no merging taking place when closing a ticket
                    if (ticket.isClosed()) {
                        continue;
                    }

                    change = new Change(user.username);
                    change.setField(Field.status, Status.Fixed);

                    if (StringUtils.isEmpty(ticket.responsible)) {
                        // unassigned tickets are assigned to the closer
                        change.setField(Field.responsible, user.username);
                    }
                }

                default: {
                    //No action
                }
                    break;
                }

                if (change != null) {
                    ticket = ticketService.updateTicket(repository, ticket.number, change);
                }

                if (ticket != null) {
                    sendInfo("");
                    sendHeader("#{0,number,0}: {1}", ticket.number,
                            StringUtils.trimString(ticket.title, Constants.LEN_SHORTLOG));

                    switch (link.action) {
                    case Commit: {
                        sendInfo("referenced by push of {0} to {1}", commitSha, branchName);
                        changedTickets.put(ticket.number, ticket);
                    }
                        break;

                    case Close: {
                        sendInfo("closed by push of {0} to {1}", commitSha, branchName);
                        changedTickets.put(ticket.number, ticket);
                    }
                        break;

                    default: {
                    }
                    }

                    sendInfo(ticketService.getTicketUrl(ticket));
                    sendInfo("");
                } else {
                    switch (link.action) {
                    case Commit: {
                        sendError("FAILED to reference ticket {0} by push of {1}", link.targetTicketId,
                                commitSha);
                    }
                        break;

                    case Close: {
                        sendError("FAILED to close ticket {0} by push of {1}", link.targetTicketId, commitSha);
                    }
                        break;

                    default: {
                    }
                    }
                }
            }
        }

    } catch (IOException e) {
        LOGGER.error("Can't scan for changes to reference or close", e);
    } finally {
        rw.reset();
    }

    return changedTickets.values();
}

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

License:Apache License

/** Execute commands to update references. */
@Override// ww  w .  j  a  v  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.gitblit.git.PatchsetReceivePack.java

License:Apache License

/**
 * Automatically closes open tickets that have been merged to their integration
 * branch by a client and adds references to tickets if made in the commit message.
 *
 * @param cmd//from www  .  ja  v a2  s. c o  m
 */
private Collection<TicketModel> processReferencedTickets(ReceiveCommand cmd) {
    Map<Long, TicketModel> mergedTickets = new LinkedHashMap<Long, TicketModel>();
    final RevWalk rw = getRevWalk();
    try {
        rw.reset();
        rw.markStart(rw.parseCommit(cmd.getNewId()));
        if (!ObjectId.zeroId().equals(cmd.getOldId())) {
            rw.markUninteresting(rw.parseCommit(cmd.getOldId()));
        }

        RevCommit c;
        while ((c = rw.next()) != null) {
            rw.parseBody(c);
            List<TicketLink> ticketLinks = JGitUtils.identifyTicketsFromCommitMessage(getRepository(), settings,
                    c);
            if (ticketLinks == null) {
                continue;
            }

            for (TicketLink link : ticketLinks) {

                if (mergedTickets.containsKey(link.targetTicketId)) {
                    continue;
                }

                TicketModel ticket = ticketService.getTicket(repository, link.targetTicketId);
                if (ticket == null) {
                    continue;
                }
                String integrationBranch;
                if (StringUtils.isEmpty(ticket.mergeTo)) {
                    // unspecified integration branch
                    integrationBranch = null;
                } else {
                    // specified integration branch
                    integrationBranch = Constants.R_HEADS + ticket.mergeTo;
                }

                Change change;
                Patchset patchset = null;
                String mergeSha = c.getName();
                String mergeTo = Repository.shortenRefName(cmd.getRefName());

                if (link.action == TicketAction.Commit) {
                    //A commit can reference a ticket in any branch even if the ticket is closed.
                    //This allows developers to identify and communicate related issues
                    change = new Change(user.username);
                    change.referenceCommit(mergeSha);
                } else {
                    // ticket must be open and, if specified, the ref must match the integration branch
                    if (ticket.isClosed()
                            || (integrationBranch != null && !integrationBranch.equals(cmd.getRefName()))) {
                        continue;
                    }

                    String baseRef = PatchsetCommand.getBasePatchsetBranch(ticket.number);
                    boolean knownPatchset = false;
                    Set<Ref> refs = getRepository().getAllRefsByPeeledObjectId().get(c.getId());
                    if (refs != null) {
                        for (Ref ref : refs) {
                            if (ref.getName().startsWith(baseRef)) {
                                knownPatchset = true;
                                break;
                            }
                        }
                    }

                    if (knownPatchset) {
                        // identify merged patchset by the patchset tip
                        for (Patchset ps : ticket.getPatchsets()) {
                            if (ps.tip.equals(mergeSha)) {
                                patchset = ps;
                                break;
                            }
                        }

                        if (patchset == null) {
                            // should not happen - unless ticket has been hacked
                            sendError("Failed to find the patchset for {0} in ticket {1,number,0}?!", mergeSha,
                                    ticket.number);
                            continue;
                        }

                        // create a new change
                        change = new Change(user.username);
                    } else {
                        // new patchset pushed by user
                        String base = cmd.getOldId().getName();
                        patchset = newPatchset(ticket, base, mergeSha);
                        PatchsetCommand psCmd = new PatchsetCommand(user.username, patchset);
                        psCmd.updateTicket(c, mergeTo, ticket, null);

                        // create a ticket patchset ref
                        updateRef(psCmd.getPatchsetBranch(), c.getId(), patchset.type);
                        RefUpdate ru = updateRef(psCmd.getTicketBranch(), c.getId(), patchset.type);
                        updateReflog(ru);

                        // create a change from the patchset command
                        change = psCmd.getChange();
                    }

                    // set the common change data about the merge
                    change.setField(Field.status, Status.Merged);
                    change.setField(Field.mergeSha, mergeSha);
                    change.setField(Field.mergeTo, mergeTo);

                    if (StringUtils.isEmpty(ticket.responsible)) {
                        // unassigned tickets are assigned to the closer
                        change.setField(Field.responsible, user.username);
                    }
                }

                ticket = ticketService.updateTicket(repository, ticket.number, change);

                if (ticket != null) {
                    sendInfo("");
                    sendHeader("#{0,number,0}: {1}", ticket.number,
                            StringUtils.trimString(ticket.title, Constants.LEN_SHORTLOG));

                    switch (link.action) {
                    case Commit: {
                        sendInfo("referenced by push of {0} to {1}", c.getName(), mergeTo);
                    }
                        break;

                    case Close: {
                        sendInfo("closed by push of {0} to {1}", patchset, mergeTo);
                        mergedTickets.put(ticket.number, ticket);
                    }
                        break;

                    default: {

                    }
                    }

                    sendInfo(ticketService.getTicketUrl(ticket));
                    sendInfo("");

                } else {
                    String shortid = mergeSha.substring(0,
                            settings.getInteger(Keys.web.shortCommitIdLength, 6));

                    switch (link.action) {
                    case Commit: {
                        sendError("FAILED to reference ticket {0,number,0} by push of {1}", link.targetTicketId,
                                shortid);
                    }
                        break;
                    case Close: {
                        sendError("FAILED to close ticket {0,number,0} by push of {1}", link.targetTicketId,
                                shortid);
                    }
                        break;

                    default: {

                    }
                    }
                }
            }
        }

    } catch (IOException e) {
        LOGGER.error("Can't scan for changes to reference or close", e);
    } finally {
        rw.reset();
    }

    return mergedTickets.values();
}

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

License:Apache License

/**
 * Instrumentation point where the incoming push event has been parsed,
 * validated, objects created BUT refs have not been updated. You might
 * use this to enforce a branch-write permissions model.
 *//*from  w  ww . ja  va 2  s  .c  om*/
@Override
public void onPreReceive(ReceivePack rp, Collection<ReceiveCommand> commands) {
    if (repository.isFrozen) {
        // repository is frozen/readonly
        String reason = MessageFormat.format("Gitblit does not allow pushes to \"{0}\" because it is frozen!",
                repository.name);
        logger.warn(reason);
        for (ReceiveCommand cmd : commands) {
            cmd.setResult(Result.REJECTED_OTHER_REASON, reason);
        }
        return;
    }

    if (!repository.isBare) {
        // repository has a working copy
        String reason = MessageFormat.format(
                "Gitblit does not allow pushes to \"{0}\" because it has a working copy!", repository.name);
        logger.warn(reason);
        for (ReceiveCommand cmd : commands) {
            cmd.setResult(Result.REJECTED_OTHER_REASON, reason);
        }
        return;
    }

    if (!user.canPush(repository)) {
        // user does not have push permissions
        String reason = MessageFormat.format("User \"{0}\" does not have push permissions for \"{1}\"!",
                user.username, repository.name);
        logger.warn(reason);
        for (ReceiveCommand cmd : commands) {
            cmd.setResult(Result.REJECTED_OTHER_REASON, reason);
        }
        return;
    }

    if (repository.accessRestriction.atLeast(AccessRestrictionType.PUSH) && repository.verifyCommitter) {
        // enforce committer verification
        if (StringUtils.isEmpty(user.emailAddress)) {
            // emit warning if user does not have an email address 
            logger.warn(MessageFormat.format(
                    "Consider setting an email address for {0} ({1}) to improve committer verification.",
                    user.getDisplayName(), user.username));
        }

        // Optionally enforce that the committer of the left parent chain
        // match the account being used to push the commits.
        // 
        // This requires all merge commits are executed with the "--no-ff"
        // option to force a merge commit even if fast-forward is possible.
        // This ensures that the chain of left parents has the commit
        // identity of the merging user.
        boolean allRejected = false;
        for (ReceiveCommand cmd : commands) {
            String linearParent = null;
            try {
                List<RevCommit> commits = JGitUtils.getRevLog(rp.getRepository(), cmd.getOldId().name(),
                        cmd.getNewId().name());
                for (RevCommit commit : commits) {

                    if (linearParent != null) {
                        if (!commit.getName().equals(linearParent)) {
                            // ignore: commit is right-descendant of a merge
                            continue;
                        }
                    }

                    // update expected next commit id
                    if (commit.getParentCount() == 0) {
                        linearParent = null;
                    } else {
                        linearParent = commit.getParents()[0].getId().getName();
                    }

                    PersonIdent committer = commit.getCommitterIdent();
                    if (!user.is(committer.getName(), committer.getEmailAddress())) {
                        String reason;
                        if (StringUtils.isEmpty(user.emailAddress)) {
                            // account does not have an email address
                            reason = MessageFormat.format("{0} by {1} <{2}> was not committed by {3} ({4})",
                                    commit.getId().name(), committer.getName(),
                                    StringUtils.isEmpty(committer.getEmailAddress()) ? "?"
                                            : committer.getEmailAddress(),
                                    user.getDisplayName(), user.username);
                        } else {
                            // account has an email address
                            reason = MessageFormat.format(
                                    "{0} by {1} <{2}> was not committed by {3} ({4}) <{5}>",
                                    commit.getId().name(), committer.getName(),
                                    StringUtils.isEmpty(committer.getEmailAddress()) ? "?"
                                            : committer.getEmailAddress(),
                                    user.getDisplayName(), user.username, user.emailAddress);
                        }
                        logger.warn(reason);
                        cmd.setResult(Result.REJECTED_OTHER_REASON, reason);
                        allRejected &= true;
                        break;
                    } else {
                        allRejected = false;
                    }
                }
            } catch (Exception e) {
                logger.error("Failed to verify commits were made by pushing user", e);
            }
        }

        if (allRejected) {
            // all ref updates rejected, abort
            return;
        }
    }

    // reset branch commit cache on REWIND and DELETE
    for (ReceiveCommand cmd : commands) {
        String ref = cmd.getRefName();
        if (ref.startsWith(Constants.R_HEADS)) {
            switch (cmd.getType()) {
            case UPDATE_NONFASTFORWARD:
            case DELETE:
                CommitCache.instance().clear(repository.name, ref);
                break;
            default:
                break;
            }
        }
    }

    Set<String> scripts = new LinkedHashSet<String>();
    scripts.addAll(GitBlit.self().getPreReceiveScriptsInherited(repository));
    if (!ArrayUtils.isEmpty(repository.preReceiveScripts)) {
        scripts.addAll(repository.preReceiveScripts);
    }
    runGroovy(repository, user, commands, rp, scripts);
    for (ReceiveCommand cmd : commands) {
        if (!Result.NOT_ATTEMPTED.equals(cmd.getResult())) {
            logger.warn(MessageFormat.format("{0} {1} because \"{2}\"", cmd.getNewId().getName(),
                    cmd.getResult(), cmd.getMessage()));
        }
    }
}

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

License:Apache License

/**
 * Instrumentation point where the incoming push has been applied to the
 * repository. This is the point where we would trigger a Jenkins build
 * or send an email.//from  w  w  w .ja va2 s  .  c o  m
 */
@Override
public void onPostReceive(ReceivePack rp, Collection<ReceiveCommand> commands) {
    if (commands.size() == 0) {
        logger.debug("skipping post-receive hooks, no refs created, updated, or removed");
        return;
    }

    // log ref changes
    for (ReceiveCommand cmd : commands) {
        if (Result.OK.equals(cmd.getResult())) {
            // add some logging for important ref changes
            switch (cmd.getType()) {
            case DELETE:
                logger.info(MessageFormat.format("{0} DELETED {1} in {2} ({3})", user.username,
                        cmd.getRefName(), repository.name, cmd.getOldId().name()));
                break;
            case CREATE:
                logger.info(MessageFormat.format("{0} CREATED {1} in {2}", user.username, cmd.getRefName(),
                        repository.name));
                break;
            case UPDATE:
                logger.info(MessageFormat.format("{0} UPDATED {1} in {2} (from {3} to {4})", user.username,
                        cmd.getRefName(), repository.name, cmd.getOldId().name(), cmd.getNewId().name()));
                break;
            case UPDATE_NONFASTFORWARD:
                logger.info(MessageFormat.format("{0} UPDATED NON-FAST-FORWARD {1} in {2} (from {3} to {4})",
                        user.username, cmd.getRefName(), repository.name, cmd.getOldId().name(),
                        cmd.getNewId().name()));
                break;
            default:
                break;
            }
        }
    }

    if (repository.useIncrementalPushTags) {
        // tag each pushed branch tip
        String emailAddress = user.emailAddress == null ? rp.getRefLogIdent().getEmailAddress()
                : user.emailAddress;
        PersonIdent userIdent = new PersonIdent(user.getDisplayName(), emailAddress);

        for (ReceiveCommand cmd : commands) {
            if (!cmd.getRefName().startsWith("refs/heads/")) {
                // only tag branch ref changes
                continue;
            }

            if (!ReceiveCommand.Type.DELETE.equals(cmd.getType())
                    && ReceiveCommand.Result.OK.equals(cmd.getResult())) {
                String objectId = cmd.getNewId().getName();
                String branch = cmd.getRefName().substring("refs/heads/".length());
                // get translation based on the server's locale setting
                String template = Translation.get("gb.incrementalPushTagMessage");
                String msg = MessageFormat.format(template, branch);
                String prefix;
                if (StringUtils.isEmpty(repository.incrementalPushTagPrefix)) {
                    prefix = GitBlit.getString(Keys.git.defaultIncrementalPushTagPrefix, "r");
                } else {
                    prefix = repository.incrementalPushTagPrefix;
                }

                JGitUtils.createIncrementalRevisionTag(rp.getRepository(), objectId, userIdent, prefix, "0",
                        msg);
            }
        }
    }

    // update push log
    try {
        RefLogUtils.updateRefLog(user, rp.getRepository(), commands);
        logger.debug(MessageFormat.format("{0} push log updated", repository.name));
    } catch (Exception e) {
        logger.error(MessageFormat.format("Failed to update {0} pushlog", repository.name), e);
    }

    // run Groovy hook scripts 
    Set<String> scripts = new LinkedHashSet<String>();
    scripts.addAll(GitBlit.self().getPostReceiveScriptsInherited(repository));
    if (!ArrayUtils.isEmpty(repository.postReceiveScripts)) {
        scripts.addAll(repository.postReceiveScripts);
    }
    runGroovy(repository, user, commands, rp, scripts);
}

From source file:com.gitblit.plugin.flowdock.FlowDockReceiveHook.java

License:Apache License

@Override
public void onPostReceive(GitblitReceivePack receivePack, Collection<ReceiveCommand> commands) {
    if (!shallPost(receivePack, commands)) {
        return;//from  ww w. j a  va  2 s.  com
    }

    IRuntimeManager runtimeManager = GitblitContext.getManager(IRuntimeManager.class);
    try {
        for (ReceiveCommand cmd : commands) {
            if (cmd.getRefName().startsWith(Constants.R_TAGS)) {
                boolean shallPostTag = runtimeManager.getSettings().getBoolean(Plugin.SETTING_POST_TAGS, true);
                if (!shallPostTag) {
                    continue;
                }
            } else if (cmd.getRefName().startsWith(Constants.R_HEADS)) {
                boolean shallPostBranch = runtimeManager.getSettings().getBoolean(Plugin.SETTING_POST_BRANCHES,
                        true);
                if (!shallPostBranch) {
                    continue;
                }
            } else {
                // ignore other refs
                continue;
            }

            RepositoryModel repo = receivePack.getRepositoryModel();

            String repoUrl = getUrl(repo.name, null, null);
            String diffUrl = getUrl(repo.name, cmd.getOldId().getName(), cmd.getNewId().getName());

            GitPayload payload = new GitPayload().pusher(receivePack.getUserModel()).repository(repo.name)
                    .repoUrl(repoUrl).tags(getTags(repo)).ref(cmd.getRefName())
                    .refName(Repository.shortenRefName(cmd.getRefName())).diffUrl(diffUrl)
                    .before(cmd.getOldId().getName()).after(cmd.getNewId().getName());

            List<RevCommit> commits = getCommits(receivePack, cmd.getOldId().name(), cmd.getNewId().name());
            for (RevCommit commit : commits) {
                Commit c = new Commit();
                c.id = commit.getName();
                c.url = getUrl(repo.name, null, commit.getName());
                c.message = commit.getFullMessage().trim();

                PersonIdent author = commit.getAuthorIdent();
                c.author = new Ident(author.getName(), author.getEmailAddress());
                c.timestamp = author.getWhen();
                if (c.timestamp == null) {
                    c.timestamp = commit.getCommitterIdent().getWhen();
                }

                List<PathChangeModel> paths = JGitUtils.getFilesInCommit(receivePack.getRepository(), commit);
                c.added = filter(paths, ChangeType.ADD);
                c.modified = filter(paths, ChangeType.MODIFY);
                c.removed = filter(paths, ChangeType.DELETE);

                payload.add(c);
            }

            flowdock.setFlow(repo, payload);
            flowdock.sendAsync(payload);
        }
    } catch (Exception e) {
        log.error("Failed to notify FlowDock!", e);
    }
}