From c2188a840bc4153ae92112b04b2e06a90d3944aa Mon Sep 17 00:00:00 2001 From: Paul Martin <paul@paulsputer.com> Date: Wed, 27 Apr 2016 18:58:06 -0400 Subject: [PATCH] Ticket Reference handling #1048 --- src/main/java/com/gitblit/tickets/ITicketService.java | 133 +++++++++++++++++++++++++++++++++++++------- 1 files changed, 111 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/gitblit/tickets/ITicketService.java b/src/main/java/com/gitblit/tickets/ITicketService.java index 4cf099f..20b6505 100644 --- a/src/main/java/com/gitblit/tickets/ITicketService.java +++ b/src/main/java/com/gitblit/tickets/ITicketService.java @@ -36,6 +36,7 @@ import com.gitblit.IStoredSettings; import com.gitblit.Keys; import com.gitblit.extensions.TicketHook; +import com.gitblit.manager.IManager; import com.gitblit.manager.INotificationManager; import com.gitblit.manager.IPluginManager; import com.gitblit.manager.IRepositoryManager; @@ -47,10 +48,13 @@ import com.gitblit.models.TicketModel.Change; import com.gitblit.models.TicketModel.Field; import com.gitblit.models.TicketModel.Patchset; +import com.gitblit.models.TicketModel.PatchsetType; import com.gitblit.models.TicketModel.Status; +import com.gitblit.models.TicketModel.TicketLink; import com.gitblit.tickets.TicketIndexer.Lucene; import com.gitblit.utils.DeepCopier; import com.gitblit.utils.DiffUtils; +import com.gitblit.utils.JGitUtils; import com.gitblit.utils.DiffUtils.DiffStat; import com.gitblit.utils.StringUtils; import com.google.common.cache.Cache; @@ -63,7 +67,7 @@ * @author James Moger * */ -public abstract class ITicketService { +public abstract class ITicketService implements IManager { public static final String SETTING_UPDATE_DIFFSTATS = "migration.updateDiffstats"; @@ -176,12 +180,14 @@ * Start the service. * @since 1.4.0 */ + @Override public abstract ITicketService start(); /** * Stop the service. * @since 1.4.0 */ + @Override public final ITicketService stop() { indexer.close(); ticketsCache.invalidateAll(); @@ -1017,12 +1023,12 @@ } /** - * Updates a ticket. + * Updates a ticket and promotes pending links into references. * * @param repository - * @param ticketId + * @param ticketId, or 0 to action pending links in general * @param change - * @return the ticket model if successful + * @return the ticket model if successful, null if failure or using 0 ticketId * @since 1.4.0 */ public final TicketModel updateTicket(RepositoryModel repository, long ticketId, Change change) { @@ -1034,28 +1040,78 @@ throw new RuntimeException("must specify a change author!"); } - TicketKey key = new TicketKey(repository, ticketId); - ticketsCache.invalidate(key); - - boolean success = commitChangeImpl(repository, ticketId, change); - if (success) { - TicketModel ticket = getTicket(repository, ticketId); - ticketsCache.put(key, ticket); - indexer.index(ticket); - - // call the ticket hooks - if (pluginManager != null) { - for (TicketHook hook : pluginManager.getExtensions(TicketHook.class)) { - try { - hook.onUpdateTicket(ticket, change); - } catch (Exception e) { - log.error("Failed to execute extension", e); + boolean success = true; + TicketModel ticket = null; + + if (ticketId > 0) { + TicketKey key = new TicketKey(repository, ticketId); + ticketsCache.invalidate(key); + + success = commitChangeImpl(repository, ticketId, change); + + if (success) { + ticket = getTicket(repository, ticketId); + ticketsCache.put(key, ticket); + indexer.index(ticket); + + // call the ticket hooks + if (pluginManager != null) { + for (TicketHook hook : pluginManager.getExtensions(TicketHook.class)) { + try { + hook.onUpdateTicket(ticket, change); + } catch (Exception e) { + log.error("Failed to execute extension", e); + } } } } - return ticket; } - return null; + + if (success) { + //Now that the ticket has been successfully persisted add references to this ticket from linked tickets + if (change.hasPendingLinks()) { + for (TicketLink link : change.pendingLinks) { + TicketModel linkedTicket = getTicket(repository, link.targetTicketId); + Change dstChange = null; + + //Ignore if not available or self reference + if (linkedTicket != null && link.targetTicketId != ticketId) { + dstChange = new Change(change.author, change.date); + + switch (link.action) { + case Comment: { + if (ticketId == 0) { + throw new RuntimeException("must specify a ticket when linking a comment!"); + } + dstChange.referenceTicket(ticketId, change.comment.id); + } break; + + case Commit: { + dstChange.referenceCommit(link.hash); + } break; + + default: { + throw new RuntimeException( + String.format("must add persist logic for link of type %s", link.action)); + } + } + } + + if (dstChange != null) { + //If not deleted then remain null in journal + if (link.isDelete) { + dstChange.reference.deleted = true; + } + + if (updateTicket(repository, link.targetTicketId, dstChange) != null) { + link.success = true; + } + } + } + } + } + + return ticket; } /** @@ -1210,6 +1266,39 @@ TicketModel revisedTicket = updateTicket(repository, ticket.number, deletion); return revisedTicket; } + + /** + * Deletes a patchset from a ticket. + * + * @param ticket + * @param patchset + * the patchset to delete (should be the highest revision) + * @param userName + * the user deleting the commit + * @return the revised ticket if the deletion was successful + * @since 1.8.0 + */ + public final TicketModel deletePatchset(TicketModel ticket, Patchset patchset, String userName) { + Change deletion = new Change(userName); + deletion.patchset = new Patchset(); + deletion.patchset.number = patchset.number; + deletion.patchset.rev = patchset.rev; + deletion.patchset.type = PatchsetType.Delete; + //Find and delete references to tickets by the removed commits + List<TicketLink> patchsetTicketLinks = JGitUtils.identifyTicketsBetweenCommits( + repositoryManager.getRepository(ticket.repository), + settings, patchset.base, patchset.tip); + + for (TicketLink link : patchsetTicketLinks) { + link.isDelete = true; + } + deletion.pendingLinks = patchsetTicketLinks; + + RepositoryModel repositoryModel = repositoryManager.getRepositoryModel(ticket.repository); + TicketModel revisedTicket = updateTicket(repositoryModel, ticket.number, deletion); + + return revisedTicket; + } /** * Commit a ticket change to the repository. -- Gitblit v1.9.1