src/main/java/com/gitblit/git/GitblitReceivePack.java | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/git/PatchsetReceivePack.java | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/git/ReceiveCommandEvent.java | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/service/MirrorService.java | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/tickets/BranchTicketService.java | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/tickets/ITicketService.java | ●●●●● patch | view | raw | blame | history |
src/main/java/com/gitblit/git/GitblitReceivePack.java
@@ -51,7 +51,6 @@ import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; import com.gitblit.tickets.BranchTicketService; import com.gitblit.tickets.BranchTicketService.TicketsBranchUpdated; import com.gitblit.utils.ArrayUtils; import com.gitblit.utils.ClientLogger; import com.gitblit.utils.CommitCache; @@ -346,10 +345,11 @@ } // check for updates pushed to the BranchTicketService branch // if the BranchTicketService is active it will reindex, as appropriate for (ReceiveCommand cmd : commands) { if (Result.OK.equals(cmd.getResult()) && BranchTicketService.BRANCH.equals(cmd.getRefName())) { rp.getRepository().fireEvent(new TicketsBranchUpdated(repository)); rp.getRepository().fireEvent(new ReceiveCommandEvent(repository, cmd)); } } src/main/java/com/gitblit/git/PatchsetReceivePack.java
@@ -60,6 +60,7 @@ import com.gitblit.models.TicketModel.PatchsetType; import com.gitblit.models.TicketModel.Status; import com.gitblit.models.UserModel; import com.gitblit.tickets.BranchTicketService; import com.gitblit.tickets.ITicketService; import com.gitblit.tickets.TicketMilestone; import com.gitblit.tickets.TicketNotifier; @@ -105,7 +106,7 @@ protected final TicketNotifier ticketNotifier; private boolean requireCleanMerge; private boolean requireMergeablePatchset; public PatchsetReceivePack(IGitblit gitblit, Repository db, RepositoryModel repository, UserModel user) { super(gitblit, db, repository, user); @@ -257,12 +258,26 @@ /** Execute commands to update references. */ @Override 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; } } @@ -292,7 +307,7 @@ continue; } if (isPatchsetRef(cmd.getRefName())) { 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; @@ -393,6 +408,8 @@ 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); } } } @@ -539,7 +556,7 @@ case MERGEABLE: break; default: if (ticket == null || requireCleanMerge) { if (ticket == null || requireMergeablePatchset) { sendError(""); sendError("Your patchset can not be cleanly merged into {0}.", forBranch); sendError("Please rebase your patchset and push again."); src/main/java/com/gitblit/git/ReceiveCommandEvent.java
New file @@ -0,0 +1,38 @@ /* * Copyright 2014 gitblit.com. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.gitblit.git; import org.eclipse.jgit.events.RefsChangedEvent; import org.eclipse.jgit.transport.ReceiveCommand; import com.gitblit.models.RepositoryModel; /** * The event fired by other classes to allow this service to index tickets. * * @author James Moger */ public class ReceiveCommandEvent extends RefsChangedEvent { public final RepositoryModel model; public final ReceiveCommand cmd; public ReceiveCommandEvent(RepositoryModel model, ReceiveCommand cmd) { this.model = model; this.cmd = cmd; } } src/main/java/com/gitblit/service/MirrorService.java
@@ -28,6 +28,8 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.transport.FetchResult; import org.eclipse.jgit.transport.ReceiveCommand; import org.eclipse.jgit.transport.ReceiveCommand.Type; import org.eclipse.jgit.transport.RemoteConfig; import org.eclipse.jgit.transport.TrackingRefUpdate; import org.slf4j.Logger; @@ -35,11 +37,11 @@ import com.gitblit.IStoredSettings; import com.gitblit.Keys; import com.gitblit.git.ReceiveCommandEvent; import com.gitblit.manager.IRepositoryManager; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; import com.gitblit.tickets.BranchTicketService; import com.gitblit.tickets.BranchTicketService.TicketsBranchUpdated; import com.gitblit.utils.JGitUtils; /** @@ -147,7 +149,7 @@ FetchResult result = git.fetch().setRemote(mirror.getName()).setDryRun(testing).call(); Collection<TrackingRefUpdate> refUpdates = result.getTrackingRefUpdates(); if (refUpdates.size() > 0) { boolean ticketBranchUpdated = false; ReceiveCommand ticketBranchCmd = null; for (TrackingRefUpdate ru : refUpdates) { StringBuilder sb = new StringBuilder(); sb.append("updated mirror "); @@ -166,12 +168,31 @@ logger.info(sb.toString()); if (BranchTicketService.BRANCH.equals(ru.getLocalName())) { ticketBranchUpdated = true; ReceiveCommand.Type type = null; switch (ru.getResult()) { case NEW: type = Type.CREATE; break; case FAST_FORWARD: type = Type.UPDATE; break; case FORCED: type = Type.UPDATE_NONFASTFORWARD; break; default: type = null; break; } if (type != null) { ticketBranchCmd = new ReceiveCommand(ru.getOldObjectId(), ru.getNewObjectId(), ru.getLocalName(), type); } } } if (ticketBranchUpdated) { repository.fireEvent(new TicketsBranchUpdated(model)); if (ticketBranchCmd != null) { repository.fireEvent(new ReceiveCommandEvent(model, ticketBranchCmd)); } } } catch (Exception e) { src/main/java/com/gitblit/tickets/BranchTicketService.java
@@ -27,6 +27,7 @@ import java.util.Set; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import javax.inject.Inject; @@ -50,15 +51,18 @@ import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevTree; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.transport.ReceiveCommand; import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.TreeWalk; import com.gitblit.Constants; import com.gitblit.git.ReceiveCommandEvent; import com.gitblit.manager.INotificationManager; import com.gitblit.manager.IRepositoryManager; import com.gitblit.manager.IRuntimeManager; import com.gitblit.manager.IUserManager; import com.gitblit.models.PathModel; import com.gitblit.models.PathModel.PathChangeModel; import com.gitblit.models.RefModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.TicketModel; @@ -77,18 +81,6 @@ * */ public class BranchTicketService extends ITicketService implements RefsChangedListener { /** * The event fired by other classes to allow this service to index tickets. */ public static class TicketsBranchUpdated extends RefsChangedEvent { public final RepositoryModel model; public TicketsBranchUpdated(RepositoryModel model) { this.model = model; } } public static final String BRANCH = "refs/gitblit/tickets"; @@ -138,16 +130,60 @@ } /** * Listen for refs changed events and reindex that repository. * Listen for tickets branch changes and (re)index tickets, as appropriate */ @Override public void onRefsChanged(RefsChangedEvent event) { if (!(event instanceof TicketsBranchUpdated)) { public synchronized void onRefsChanged(RefsChangedEvent event) { if (!(event instanceof ReceiveCommandEvent)) { return; } RepositoryModel repository = ((TicketsBranchUpdated) event).model; ReceiveCommandEvent branchUpdate = (ReceiveCommandEvent) event; RepositoryModel repository = branchUpdate.model; ReceiveCommand cmd = branchUpdate.cmd; try { switch (cmd.getType()) { case CREATE: case UPDATE_NONFASTFORWARD: // reindex everything reindex(repository); break; case UPDATE: // incrementally index ticket updates resetCaches(repository); long start = System.nanoTime(); log.info("incrementally indexing {} ticket branch due to received ref update", repository.name); Repository db = repositoryManager.getRepository(repository.name); try { Set<Long> ids = new HashSet<Long>(); List<PathChangeModel> paths = JGitUtils.getFilesInRange(db, cmd.getOldId().getName(), cmd.getNewId().getName()); for (PathChangeModel path : paths) { String name = path.name.substring(path.name.lastIndexOf('/') + 1); if (!JOURNAL.equals(name)) { continue; } String tid = path.path.split("/")[2]; long ticketId = Long.parseLong(tid); if (!ids.contains(ticketId)) { ids.add(ticketId); TicketModel ticket = getTicket(repository, ticketId); log.info(MessageFormat.format("indexing ticket #{0,number,0}: {1}", ticketId, ticket.title)); indexer.index(ticket); } } long end = System.nanoTime(); log.info("incremental indexing of {0} ticket(s) completed in {1} msecs", ids.size(), TimeUnit.NANOSECONDS.toMillis(end - start)); } finally { db.close(); } break; default: log.warn("Unexpected receive type {} in BranchTicketService.onRefsChanged" + cmd.getType()); break; } } catch (Exception e) { log.error("failed to reindex " + repository.name, e); } src/main/java/com/gitblit/tickets/ITicketService.java
@@ -897,6 +897,7 @@ public boolean deleteAll(RepositoryModel repository) { boolean success = deleteAllImpl(repository); if (success) { log.info("Deleted all tickets for {}", repository.name); resetCaches(repository); indexer.deleteAll(repository); } @@ -936,6 +937,8 @@ TicketModel ticket = getTicket(repository, ticketId); boolean success = deleteTicketImpl(repository, ticket, deletedBy); if (success) { log.info(MessageFormat.format("Deleted {0} ticket #{1,number,0}: {2}", repository.name, ticketId, ticket.title)); ticketsCache.invalidate(new TicketKey(repository, ticketId)); indexer.delete(ticket); return true; @@ -1074,6 +1077,7 @@ long end = System.nanoTime(); long secs = TimeUnit.NANOSECONDS.toMillis(end - start); log.info("reindexing completed in {} msecs.", secs); resetCaches(repository); } /**