Search in sources :

Example 51 with RefUpdate

use of org.eclipse.jgit.lib.RefUpdate in project gitblit by gitblit.

the class RefLogUtils method updateRefLog.

/**
 * Updates the reflog with the received commands.
 *
 * @param user
 * @param repository
 * @param commands
 * @return true, if the update was successful
 */
public static boolean updateRefLog(UserModel user, Repository repository, Collection<ReceiveCommand> commands) {
    // only track branches and tags
    List<ReceiveCommand> filteredCommands = new ArrayList<ReceiveCommand>();
    for (ReceiveCommand cmd : commands) {
        if (!cmd.getRefName().startsWith(Constants.R_HEADS) && !cmd.getRefName().startsWith(Constants.R_TAGS)) {
            continue;
        }
        filteredCommands.add(cmd);
    }
    if (filteredCommands.isEmpty()) {
        // nothing to log
        return true;
    }
    RefModel reflogBranch = getRefLogBranch(repository);
    if (reflogBranch == null) {
        JGitUtils.createOrphanBranch(repository, GB_REFLOG, null);
    }
    boolean success = false;
    String message = "push";
    try {
        ObjectId headId = repository.resolve(GB_REFLOG + "^{commit}");
        ObjectInserter odi = repository.newObjectInserter();
        try {
            // Create the in-memory index of the reflog log entry
            DirCache index = createIndex(repository, headId, commands);
            ObjectId indexTreeId = index.writeTree(odi);
            PersonIdent ident;
            if (UserModel.ANONYMOUS.equals(user)) {
                // anonymous push
                ident = new PersonIdent(user.username + "/" + user.username, user.username);
            } else {
                // construct real pushing account
                ident = new PersonIdent(MessageFormat.format("{0}/{1}", user.getDisplayName(), user.username), user.emailAddress == null ? user.username : user.emailAddress);
            }
            // Create a commit object
            CommitBuilder commit = new CommitBuilder();
            commit.setAuthor(ident);
            commit.setCommitter(ident);
            commit.setEncoding(Constants.ENCODING);
            commit.setMessage(message);
            commit.setParentId(headId);
            commit.setTreeId(indexTreeId);
            // Insert the commit into the repository
            ObjectId commitId = odi.insert(commit);
            odi.flush();
            RevWalk revWalk = new RevWalk(repository);
            try {
                RevCommit revCommit = revWalk.parseCommit(commitId);
                RefUpdate ru = repository.updateRef(GB_REFLOG);
                ru.setNewObjectId(commitId);
                ru.setExpectedOldObjectId(headId);
                ru.setRefLogMessage("commit: " + revCommit.getShortMessage(), false);
                Result rc = ru.forceUpdate();
                switch(rc) {
                    case NEW:
                    case FORCED:
                    case FAST_FORWARD:
                        success = true;
                        break;
                    case REJECTED:
                    case LOCK_FAILURE:
                        throw new ConcurrentRefUpdateException(JGitText.get().couldNotLockHEAD, ru.getRef(), rc);
                    default:
                        throw new JGitInternalException(MessageFormat.format(JGitText.get().updatingRefFailed, GB_REFLOG, commitId.toString(), rc));
                }
            } finally {
                revWalk.close();
            }
        } finally {
            odi.close();
        }
    } catch (Throwable t) {
        error(t, repository, "Failed to commit reflog entry to {0}");
    }
    return success;
}
Also used : ReceiveCommand(org.eclipse.jgit.transport.ReceiveCommand) RefModel(com.gitblit.models.RefModel) ObjectId(org.eclipse.jgit.lib.ObjectId) ArrayList(java.util.ArrayList) CommitBuilder(org.eclipse.jgit.lib.CommitBuilder) RevWalk(org.eclipse.jgit.revwalk.RevWalk) Result(org.eclipse.jgit.lib.RefUpdate.Result) DirCache(org.eclipse.jgit.dircache.DirCache) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) PersonIdent(org.eclipse.jgit.lib.PersonIdent) JGitInternalException(org.eclipse.jgit.api.errors.JGitInternalException) ConcurrentRefUpdateException(org.eclipse.jgit.api.errors.ConcurrentRefUpdateException) RevCommit(org.eclipse.jgit.revwalk.RevCommit) RefUpdate(org.eclipse.jgit.lib.RefUpdate)

Example 52 with RefUpdate

use of org.eclipse.jgit.lib.RefUpdate in project gitblit by gitblit.

the class PatchsetReceivePack method processReferencedTickets.

/**
 * 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
 */
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();
}
Also used : TicketModel(com.gitblit.models.TicketModel) Patchset(com.gitblit.models.TicketModel.Patchset) Change(com.gitblit.models.TicketModel.Change) IOException(java.io.IOException) RevWalk(org.eclipse.jgit.revwalk.RevWalk) LinkedHashMap(java.util.LinkedHashMap) Ref(org.eclipse.jgit.lib.Ref) TicketLink(com.gitblit.models.TicketModel.TicketLink) RevCommit(org.eclipse.jgit.revwalk.RevCommit) RefUpdate(org.eclipse.jgit.lib.RefUpdate) BatchRefUpdate(org.eclipse.jgit.lib.BatchRefUpdate)

Example 53 with RefUpdate

use of org.eclipse.jgit.lib.RefUpdate in project gitblit by gitblit.

the class PatchsetReceivePack method updateRef.

private RefUpdate updateRef(String ref, ObjectId newId, PatchsetType type) {
    ObjectId ticketRefId = ObjectId.zeroId();
    try {
        ticketRefId = getRepository().resolve(ref);
    } catch (Exception e) {
    // ignore
    }
    try {
        RefUpdate ru = getRepository().updateRef(ref, false);
        ru.setRefLogIdent(getRefLogIdent());
        switch(type) {
            case Amend:
            case Rebase:
            case Rebase_Squash:
            case Squash:
                ru.setForceUpdate(true);
                break;
            default:
                break;
        }
        ru.setExpectedOldObjectId(ticketRefId);
        ru.setNewObjectId(newId);
        RefUpdate.Result result = ru.update(getRevWalk());
        if (result == RefUpdate.Result.LOCK_FAILURE) {
            sendError("Failed to obtain lock when updating {0}:{1}", repository.name, ref);
            sendError("Perhaps an administrator should remove {0}/{1}.lock?", getRepository().getDirectory(), ref);
            return null;
        }
        return ru;
    } catch (IOException e) {
        LOGGER.error("failed to update ref " + ref, e);
        sendError("There was an error updating ref {0}:{1}", repository.name, ref);
    }
    return null;
}
Also used : ObjectId(org.eclipse.jgit.lib.ObjectId) IOException(java.io.IOException) IOException(java.io.IOException) RefUpdate(org.eclipse.jgit.lib.RefUpdate) BatchRefUpdate(org.eclipse.jgit.lib.BatchRefUpdate)

Example 54 with RefUpdate

use of org.eclipse.jgit.lib.RefUpdate in project gerrit by GerritCodeReview.

the class AccountsOnInit method insert.

// TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
// Instants
@SuppressWarnings("JdkObsolete")
public Account insert(Account.Builder account) throws IOException {
    File path = getPath();
    try (Repository repo = new FileRepository(path);
        ObjectInserter oi = repo.newObjectInserter()) {
        PersonIdent ident = new PersonIdent(new GerritPersonIdentProvider(flags.cfg).get(), Date.from(account.registeredOn()));
        Config accountConfig = new Config();
        AccountProperties.writeToAccountConfig(AccountDelta.builder().setActive(!account.inactive()).setFullName(account.fullName()).setPreferredEmail(account.preferredEmail()).setStatus(account.status()).build(), accountConfig);
        DirCache newTree = DirCache.newInCore();
        DirCacheEditor editor = newTree.editor();
        final ObjectId blobId = oi.insert(Constants.OBJ_BLOB, accountConfig.toText().getBytes(UTF_8));
        editor.add(new PathEdit(AccountProperties.ACCOUNT_CONFIG) {

            @Override
            public void apply(DirCacheEntry ent) {
                ent.setFileMode(FileMode.REGULAR_FILE);
                ent.setObjectId(blobId);
            }
        });
        editor.finish();
        ObjectId treeId = newTree.writeTree(oi);
        CommitBuilder cb = new CommitBuilder();
        cb.setTreeId(treeId);
        cb.setCommitter(ident);
        cb.setAuthor(ident);
        cb.setMessage("Create Account");
        ObjectId id = oi.insert(cb);
        oi.flush();
        String refName = RefNames.refsUsers(account.id());
        RefUpdate ru = repo.updateRef(refName);
        ru.setExpectedOldObjectId(ObjectId.zeroId());
        ru.setNewObjectId(id);
        ru.setRefLogIdent(ident);
        ru.setRefLogMessage("Create Account", false);
        Result result = ru.update();
        if (result != Result.NEW) {
            throw new IOException(String.format("Failed to update ref %s: %s", refName, result.name()));
        }
        account.setMetaId(id.name()).build();
    }
    return account.build();
}
Also used : FileRepository(org.eclipse.jgit.internal.storage.file.FileRepository) DirCacheEntry(org.eclipse.jgit.dircache.DirCacheEntry) ObjectId(org.eclipse.jgit.lib.ObjectId) Config(org.eclipse.jgit.lib.Config) GerritPersonIdentProvider(com.google.gerrit.server.GerritPersonIdentProvider) PathEdit(org.eclipse.jgit.dircache.DirCacheEditor.PathEdit) CommitBuilder(org.eclipse.jgit.lib.CommitBuilder) DirCacheEditor(org.eclipse.jgit.dircache.DirCacheEditor) IOException(java.io.IOException) Result(org.eclipse.jgit.lib.RefUpdate.Result) DirCache(org.eclipse.jgit.dircache.DirCache) FileRepository(org.eclipse.jgit.internal.storage.file.FileRepository) Repository(org.eclipse.jgit.lib.Repository) ObjectInserter(org.eclipse.jgit.lib.ObjectInserter) PersonIdent(org.eclipse.jgit.lib.PersonIdent) File(java.io.File) RefUpdate(org.eclipse.jgit.lib.RefUpdate)

Example 55 with RefUpdate

use of org.eclipse.jgit.lib.RefUpdate in project gerrit by GerritCodeReview.

the class RefUpdateUtil method deleteChecked.

/**
 * Delete a single ref, throwing a checked exception on failure.
 *
 * <p>Does not require that the ref have any particular old value. Succeeds as a no-op if the ref
 * did not exist.
 *
 * @param repo repository.
 * @param refName ref name to delete.
 * @throws LockFailureException if a low-level lock failure (e.g. compare-and-swap failure)
 *     occurs.
 * @throws IOException if an error occurred.
 */
public static void deleteChecked(Repository repo, String refName) throws IOException {
    RefUpdate ru = repo.updateRef(refName);
    ru.setForceUpdate(true);
    ru.setCheckConflicting(false);
    switch(ru.delete()) {
        case FORCED:
            // Ref was deleted.
            return;
        case NEW:
            // Ref didn't exist (yes, really).
            return;
        case LOCK_FAILURE:
            throw new LockFailureException("Failed to delete " + refName + ": " + ru.getResult(), ru);
        // throw.
        case NO_CHANGE:
        case FAST_FORWARD:
        case RENAMED:
        case NOT_ATTEMPTED:
        case IO_FAILURE:
        case REJECTED:
        case REJECTED_CURRENT_BRANCH:
        case REJECTED_MISSING_OBJECT:
        case REJECTED_OTHER_REASON:
        default:
            throw new GitUpdateFailureException("Failed to delete " + refName + ": " + ru.getResult(), ru);
    }
}
Also used : BatchRefUpdate(org.eclipse.jgit.lib.BatchRefUpdate) RefUpdate(org.eclipse.jgit.lib.RefUpdate)

Aggregations

RefUpdate (org.eclipse.jgit.lib.RefUpdate)110 Repository (org.eclipse.jgit.lib.Repository)51 ObjectId (org.eclipse.jgit.lib.ObjectId)45 IOException (java.io.IOException)34 Test (org.junit.Test)32 AbstractDaemonTest (com.google.gerrit.acceptance.AbstractDaemonTest)27 TestRepository (org.eclipse.jgit.junit.TestRepository)26 ObjectInserter (org.eclipse.jgit.lib.ObjectInserter)24 RevWalk (org.eclipse.jgit.revwalk.RevWalk)23 Result (org.eclipse.jgit.lib.RefUpdate.Result)22 RevCommit (org.eclipse.jgit.revwalk.RevCommit)20 CommitBuilder (org.eclipse.jgit.lib.CommitBuilder)18 Ref (org.eclipse.jgit.lib.Ref)17 RemoteRefUpdate (org.eclipse.jgit.transport.RemoteRefUpdate)17 PushOneCommit (com.google.gerrit.acceptance.PushOneCommit)15 BatchRefUpdate (org.eclipse.jgit.lib.BatchRefUpdate)14 InMemoryRepository (org.eclipse.jgit.internal.storage.dfs.InMemoryRepository)12 LockFailureException (com.google.gerrit.git.LockFailureException)10 PersonIdent (org.eclipse.jgit.lib.PersonIdent)9 DirCache (org.eclipse.jgit.dircache.DirCache)8