/*
 * Copyright 2013 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 static org.eclipse.jgit.transport.BasePackPushConnection.CAPABILITY_SIDE_BAND_64K;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.transport.ReceiveCommand.Result;
import org.eclipse.jgit.transport.ReceiveCommand.Type;
import org.eclipse.jgit.transport.ReceivePack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.Constants;
import com.gitblit.Keys;
import com.gitblit.extensions.PatchsetHook;
import com.gitblit.manager.IGitblit;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.TicketModel;
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.TicketAction;
import com.gitblit.models.TicketModel.TicketLink;
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;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.DiffUtils;
import com.gitblit.utils.DiffUtils.DiffStat;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.JGitUtils.MergeResult;
import com.gitblit.utils.JGitUtils.MergeStatus;
import com.gitblit.utils.RefLogUtils;
import com.gitblit.utils.StringUtils;
import com.google.common.collect.Lists;


/**
 * PatchsetReceivePack processes receive commands and allows for creating, updating,
 * and closing Gitblit tickets.  It also executes Groovy pre- and post- receive
 * hooks.
 *
 * The patchset mechanism defined in this class is based on the ReceiveCommits class
 * from the Gerrit code review server.
 *
 * The general execution flow is:
 * <ol>
 *    <li>onPreReceive()</li>
 *    <li>executeCommands()</li>
 *    <li>onPostReceive()</li>
 * </ol>
 *
 * @author Android Open Source Project
 * @author James Moger
 *
 */
public class PatchsetReceivePack extends GitblitReceivePack {

	protected static final List<String> MAGIC_REFS = Arrays.asList(Constants.R_FOR, Constants.R_TICKET);

	protected static final Pattern NEW_PATCHSET =
			Pattern.compile("^refs/tickets/(?:[0-9a-zA-Z][0-9a-zA-Z]/)?([1-9][0-9]*)(?:/new)?$");

	private static final Logger LOGGER = LoggerFactory.getLogger(PatchsetReceivePack.class);

	protected final ITicketService ticketService;

	protected final TicketNotifier ticketNotifier;

	private boolean requireMergeablePatchset;

	public PatchsetReceivePack(IGitblit gitblit, Repository db, RepositoryModel repository, UserModel user) {
		super(gitblit, db, repository, user);
		this.ticketService = gitblit.getTicketService();
		this.ticketNotifier = ticketService.createNotifier();
	}

	/** Returns the patchset ref root from the ref */
	private String getPatchsetRef(String refName) {
		for (String patchRef : MAGIC_REFS) {
			if (refName.startsWith(patchRef)) {
				return patchRef;
			}
		}
		return null;
	}

	/** Checks if the supplied ref name is a patchset ref */
	private boolean isPatchsetRef(String refName) {
		return !StringUtils.isEmpty(getPatchsetRef(refName));
	}

	/** Checks if the supplied ref name is a change ref */
	private boolean isTicketRef(String refName) {
		return refName.startsWith(Constants.R_TICKETS_PATCHSETS);
	}

	/** Extracts the integration branch from the ref name */
	private String getIntegrationBranch(String refName) {
		String patchsetRef = getPatchsetRef(refName);
		String branch = refName.substring(patchsetRef.length());
		if (branch.indexOf('%') > -1) {
			branch = branch.substring(0, branch.indexOf('%'));
		}

		String defaultBranch = "master";
		try {
			defaultBranch = getRepository().getBranch();
		} catch (Exception e) {
			LOGGER.error("failed to determine default branch for " + repository.name, e);
		}

		if (!StringUtils.isEmpty(getRepositoryModel().mergeTo)) {
			// repository settings specifies a default integration branch
			defaultBranch = Repository.shortenRefName(getRepositoryModel().mergeTo);
		}

		long ticketId = 0L;
		try {
			ticketId = Long.parseLong(branch);
		} catch (Exception e) {
			// not a number
		}
		if (ticketId > 0 || branch.equalsIgnoreCase("default") || branch.equalsIgnoreCase("new")) {
			return defaultBranch;
		}
		return branch;
	}

	/** Extracts the ticket id from the ref name */
	private long getTicketId(String refName) {
		if (refName.indexOf('%') > -1) {
			refName = refName.substring(0, refName.indexOf('%'));
		}
		if (refName.startsWith(Constants.R_FOR)) {
			String ref = refName.substring(Constants.R_FOR.length());
			try {
				return Long.parseLong(ref);
			} catch (Exception e) {
				// not a number
			}
		} else if (refName.startsWith(Constants.R_TICKET) ||
				refName.startsWith(Constants.R_TICKETS_PATCHSETS)) {
			return PatchsetCommand.getTicketNumber(refName);
		}
		return 0L;
	}

	/** Returns true if the ref namespace exists */
	private boolean hasRefNamespace(String ref) {
		Map<String, Ref> blockingFors;
		try {
			blockingFors = getRepository().getRefDatabase().getRefs(ref);
		} catch (IOException err) {
			sendError("Cannot scan refs in {0}", repository.name);
			LOGGER.error("Error!", err);
			return true;
		}
		if (!blockingFors.isEmpty()) {
			sendError("{0} needs the following refs removed to receive patchsets: {1}",
					repository.name, blockingFors.keySet());
			return true;
		}
		return false;
	}

	/** Removes change ref receive commands */
	private List<ReceiveCommand> excludeTicketCommands(Collection<ReceiveCommand> commands) {
		List<ReceiveCommand> filtered = new ArrayList<ReceiveCommand>();
		for (ReceiveCommand cmd : commands) {
			if (!isTicketRef(cmd.getRefName())) {
				// this is not a ticket ref update
				filtered.add(cmd);
			}
		}
		return filtered;
	}

	/** Removes patchset receive commands for pre- and post- hook integrations */
	private List<ReceiveCommand> excludePatchsetCommands(Collection<ReceiveCommand> commands) {
		List<ReceiveCommand> filtered = new ArrayList<ReceiveCommand>();
		for (ReceiveCommand cmd : commands) {
			if (!isPatchsetRef(cmd.getRefName())) {
				// this is a non-patchset ref update
				filtered.add(cmd);
			}
		}
		return filtered;
	}

	/**	Process receive commands EXCEPT for Patchset commands. */
	@Override
	public void onPreReceive(ReceivePack rp, Collection<ReceiveCommand> commands) {
		Collection<ReceiveCommand> filtered = excludePatchsetCommands(commands);
		super.onPreReceive(rp, filtered);
	}

	/**	Process receive commands EXCEPT for Patchset commands. */
	@Override
	public void onPostReceive(ReceivePack rp, Collection<ReceiveCommand> commands) {
		Collection<ReceiveCommand> filtered = excludePatchsetCommands(commands);
		super.onPostReceive(rp, filtered);

		// send all queued ticket notifications after processing all patchsets
		ticketNotifier.sendAll();
	}

	@Override
	protected void validateCommands() {
		// workaround for JGit's awful scoping choices
		//
		// set the patchset refs to OK to bypass checks in the super implementation
		for (final ReceiveCommand cmd : filterCommands(Result.NOT_ATTEMPTED)) {
			if (isPatchsetRef(cmd.getRefName())) {
				if (cmd.getType() == ReceiveCommand.Type.CREATE) {
					cmd.setResult(Result.OK);
				}
			}
		}

		super.validateCommands();
	}

	/** 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;
			}
		}

		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);
	}

	/**
	 * Prepares a patchset command.
	 *
	 * @param cmd
	 * @return the patchset command
	 */
	private PatchsetCommand preparePatchset(ReceiveCommand cmd) {
		String branch = getIntegrationBranch(cmd.getRefName());
		long number = getTicketId(cmd.getRefName());

		TicketModel ticket = null;
		if (number > 0 && ticketService.hasTicket(repository, number)) {
			ticket = ticketService.getTicket(repository, number);
		}

		if (ticket == null) {
			if (number > 0) {
				// requested ticket does not exist
				sendError("Sorry, {0} does not have ticket {1,number,0}!", repository.name, number);
				sendRejection(cmd, "Invalid ticket number");
				return null;
			}
		} else {
			if (ticket.isMerged()) {
				// ticket already merged & resolved
				Change mergeChange = null;
				for (Change change : ticket.changes) {
					if (change.isMerge()) {
						mergeChange = change;
						break;
					}
				}
				if (mergeChange != null) {
					sendError("Sorry, {0} already merged {1} from ticket {2,number,0} to {3}!",
						mergeChange.author, mergeChange.patchset, number, ticket.mergeTo);
				}
				sendRejection(cmd, "Ticket {0,number,0} already resolved", number);
				return null;
			} else if (!StringUtils.isEmpty(ticket.mergeTo)) {
				// ticket specifies integration branch
				branch = ticket.mergeTo;
			}
		}

		final int shortCommitIdLen = settings.getInteger(Keys.web.shortCommitIdLength, 6);
		final String shortTipId = cmd.getNewId().getName().substring(0, shortCommitIdLen);
		final RevCommit tipCommit = JGitUtils.getCommit(getRepository(), cmd.getNewId().getName());
		final String forBranch = branch;
		RevCommit mergeBase = null;
		Ref forBranchRef = getAdvertisedRefs().get(Constants.R_HEADS + forBranch);
		if (forBranchRef == null || forBranchRef.getObjectId() == null) {
			// unknown integration branch
			sendError("Sorry, there is no integration branch named ''{0}''.", forBranch);
			sendRejection(cmd, "Invalid integration branch specified");
			return null;
		} else {
			// determine the merge base for the patchset on the integration branch
			String base = JGitUtils.getMergeBase(getRepository(), forBranchRef.getObjectId(), tipCommit.getId());
			if (StringUtils.isEmpty(base)) {
				sendError("");
				sendError("There is no common ancestry between {0} and {1}.", forBranch, shortTipId);
				sendError("Please reconsider your proposed integration branch, {0}.", forBranch);
				sendError("");
				sendRejection(cmd, "no merge base for patchset and {0}", forBranch);
				return null;
			}
			mergeBase = JGitUtils.getCommit(getRepository(), base);
		}

		// ensure that the patchset can be cleanly merged right now
		MergeStatus status = JGitUtils.canMerge(getRepository(), tipCommit.getName(), forBranch, repository.mergeType);
		switch (status) {
		case ALREADY_MERGED:
			sendError("");
			sendError("You have already merged this patchset.", forBranch);
			sendError("");
			sendRejection(cmd, "everything up-to-date");
			return null;
		case MERGEABLE:
			break;
		default:
			if (ticket == null || requireMergeablePatchset) {
				sendError("");
				sendError("Your patchset can not be cleanly merged into {0}.", forBranch);
				sendError("Please rebase your patchset and push again.");
				sendError("NOTE:", number);
				sendError("You should push your rebase to refs/for/{0,number,0}", number);
				sendError("");
				sendError("  git push origin HEAD:refs/for/{0,number,0}", number);
				sendError("");
				sendRejection(cmd, "patchset not mergeable");
				return null;
			}
		}
		
		// check to see if this commit is already linked to a ticket
		if (ticket != null && 
				JGitUtils.getTicketNumberFromCommitBranch(getRepository(), tipCommit) == ticket.number) {
			sendError("{0} has already been pushed to ticket {1,number,0}.", shortTipId, ticket.number);
			sendRejection(cmd, "everything up-to-date");
			return null;
		}
		
		List<TicketLink> ticketLinks = JGitUtils.identifyTicketsFromCommitMessage(getRepository(), settings, tipCommit);
		
		PatchsetCommand psCmd;
		if (ticket == null) {
			/*
			 *  NEW TICKET
			 */
			Patchset patchset = newPatchset(null, mergeBase.getName(), tipCommit.getName());

			int minLength = 10;
			int maxLength = 100;
			String minTitle = MessageFormat.format("  minimum length of a title is {0} characters.", minLength);
			String maxTitle = MessageFormat.format("  maximum length of a title is {0} characters.", maxLength);

			if (patchset.commits > 1) {
				sendError("");
				sendError("You may not create a ''{0}'' branch proposal ticket from {1} commits!",
						forBranch, patchset.commits);
				sendError("");
				// display an ellipsized log of the commits being pushed
				RevWalk walk = getRevWalk();
				walk.reset();
				walk.sort(RevSort.TOPO);
				int boundary = 3;
				int count = 0;
				try {
					walk.markStart(tipCommit);
					walk.markUninteresting(mergeBase);

					for (;;) {

						RevCommit c = walk.next();
						if (c == null) {
							break;
						}

						if (count < boundary || count >= (patchset.commits - boundary)) {

							walk.parseBody(c);
							sendError("   {0}  {1}", c.getName().substring(0, shortCommitIdLen),
								StringUtils.trimString(c.getShortMessage(), 60));

						} else if (count == boundary) {

							sendError("   ... more commits ...");

						}

						count++;
					}

				} catch (IOException e) {
					// Should never happen, the core receive process would have
					// identified the missing object earlier before we got control.
					LOGGER.error("failed to get commit count", e);
				} finally {
					walk.close();
				}

				sendError("");
				sendError("Possible Solutions:");
				sendError("");
				int solution = 1;
				String forSpec = cmd.getRefName().substring(Constants.R_FOR.length());
				if (forSpec.equals("default") || forSpec.equals("new")) {
					try {
						// determine other possible integration targets
						List<String> bases = Lists.newArrayList();
						for (Ref ref : getRepository().getRefDatabase().getRefs(Constants.R_HEADS).values()) {
							if (!ref.getName().startsWith(Constants.R_TICKET)
									&& !ref.getName().equals(forBranchRef.getName())) {
								if (JGitUtils.isMergedInto(getRepository(), ref.getObjectId(), tipCommit)) {
									bases.add(Repository.shortenRefName(ref.getName()));
								}
							}
						}

						if (!bases.isEmpty()) {

							if (bases.size() == 1) {
								// suggest possible integration targets
								String base = bases.get(0);
								sendError("{0}. Propose this change for the ''{1}'' branch.", solution++, base);
								sendError("");
								sendError("   git push origin HEAD:refs/for/{0}", base);
								sendError("   pt propose {0}", base);
								sendError("");
							} else {
								// suggest possible integration targets
								sendError("{0}. Propose this change for a different branch.", solution++);
								sendError("");
								for (String base : bases) {
									sendError("   git push origin HEAD:refs/for/{0}", base);
									sendError("   pt propose {0}", base);
									sendError("");
								}
							}

						}
					} catch (IOException e) {
						LOGGER.error(null, e);
					}
				}
				sendError("{0}. Squash your changes into a single commit with a meaningful message.", solution++);
				sendError("");
				sendError("{0}. Open a ticket for your changes and then push your {1} commits to the ticket.",
						solution++, patchset.commits);
				sendError("");
				sendError("   git push origin HEAD:refs/for/{id}");
				sendError("   pt propose {id}");
				sendError("");
				sendRejection(cmd, "too many commits");
				return null;
			}

			// require a reasonable title/subject
			String title = tipCommit.getFullMessage().trim().split("\n")[0];
			if (title.length() < minLength) {
				// reject, title too short
				sendError("");
				sendError("Please supply a longer title in your commit message!");
				sendError("");
				sendError(minTitle);
				sendError(maxTitle);
				sendError("");
				sendRejection(cmd, "ticket title is too short [{0}/{1}]", title.length(), maxLength);
				return null;
			}
			if (title.length() > maxLength) {
				// reject, title too long
				sendError("");
				sendError("Please supply a more concise title in your commit message!");
				sendError("");
				sendError(minTitle);
				sendError(maxTitle);
				sendError("");
				sendRejection(cmd, "ticket title is too long [{0}/{1}]", title.length(), maxLength);
				return null;
			}

			// assign new id
			long ticketId = ticketService.assignNewId(repository);

			// create the patchset command
			psCmd = new PatchsetCommand(user.username, patchset);
			psCmd.newTicket(tipCommit, forBranch, ticketId, cmd.getRefName());
		} else {
			/*
			 *  EXISTING TICKET
			 */
			Patchset patchset = newPatchset(ticket, mergeBase.getName(), tipCommit.getName());
			psCmd = new PatchsetCommand(user.username, patchset);
			psCmd.updateTicket(tipCommit, forBranch, ticket, cmd.getRefName());
		}

		// confirm user can push the patchset
		boolean pushPermitted = ticket == null
				|| !ticket.hasPatchsets()
				|| ticket.isAuthor(user.username)
				|| ticket.isPatchsetAuthor(user.username)
				|| ticket.isResponsible(user.username)
				|| user.canPush(repository);

		switch (psCmd.getPatchsetType()) {
		case Proposal:
			// proposals (first patchset) are always acceptable
			break;
		case FastForward:
			// patchset updates must be permitted
			if (!pushPermitted) {
				// reject
				sendError("");
				sendError("To push a patchset to this ticket one of the following must be true:");
				sendError("  1. you created the ticket");
				sendError("  2. you created the first patchset");
				sendError("  3. you are specified as responsible for the ticket");
				sendError("  4. you have push (RW) permissions to {0}", repository.name);
				sendError("");
				sendRejection(cmd, "not permitted to push to ticket {0,number,0}", ticket.number);
				return null;
			}
			break;
		default:
			// non-fast-forward push
			if (!pushPermitted) {
				// reject
				sendRejection(cmd, "non-fast-forward ({0})", psCmd.getPatchsetType());
				return null;
			}
			break;
		}

		Change change = psCmd.getChange();
		change.pendingLinks = ticketLinks;

		return psCmd;
	}

	/**
	 * Creates or updates an ticket with the specified patchset.
	 *
	 * @param cmd
	 * @return a ticket if the creation or update was successful
	 */
	private TicketModel processPatchset(PatchsetCommand cmd) {
		Change change = cmd.getChange();

		if (cmd.isNewTicket()) {
			// create the ticket object
			TicketModel ticket = ticketService.createTicket(repository, cmd.getTicketId(), change);
			if (ticket != null) {
				sendInfo("");
				sendHeader("#{0,number,0}: {1}", ticket.number, StringUtils.trimString(ticket.title, Constants.LEN_SHORTLOG));
				sendInfo("created proposal ticket from patchset");
				sendInfo(ticketService.getTicketUrl(ticket));
				sendInfo("");

				// log the new patch ref
				RefLogUtils.updateRefLog(user, getRepository(),
						Arrays.asList(new ReceiveCommand(cmd.getOldId(), cmd.getNewId(), cmd.getRefName())));

				// call any patchset hooks
				for (PatchsetHook hook : gitblit.getExtensions(PatchsetHook.class)) {
					try {
						hook.onNewPatchset(ticket);
					} catch (Exception e) {
						LOGGER.error("Failed to execute extension", e);
					}
				}

				return ticket;
			} else {
				sendError("FAILED to create ticket");
			}
		} else {
			// update an existing ticket
			TicketModel ticket = ticketService.updateTicket(repository, cmd.getTicketId(), change);
			if (ticket != null) {
				sendInfo("");
				sendHeader("#{0,number,0}: {1}", ticket.number, StringUtils.trimString(ticket.title, Constants.LEN_SHORTLOG));
				if (change.patchset.rev == 1) {
					// new patchset
					sendInfo("uploaded patchset {0} ({1})", change.patchset.number, change.patchset.type.toString());
				} else {
					// updated patchset
					sendInfo("added {0} {1} to patchset {2}",
							change.patchset.added,
							change.patchset.added == 1 ? "commit" : "commits",
							change.patchset.number);
				}
				sendInfo(ticketService.getTicketUrl(ticket));
				sendInfo("");

				// log the new patchset ref
				RefLogUtils.updateRefLog(user, getRepository(),
					Arrays.asList(new ReceiveCommand(cmd.getOldId(), cmd.getNewId(), cmd.getRefName())));

				// call any patchset hooks
				final boolean isNewPatchset = change.patchset.rev == 1;
				for (PatchsetHook hook : gitblit.getExtensions(PatchsetHook.class)) {
					try {
						if (isNewPatchset) {
							hook.onNewPatchset(ticket);
						} else {
							hook.onUpdatePatchset(ticket);
						}
					} catch (Exception e) {
						LOGGER.error("Failed to execute extension", e);
					}
				}

				// return the updated ticket
				return ticket;
			} else {
				sendError("FAILED to upload {0} for ticket {1,number,0}", change.patchset, cmd.getTicketId());
			}
		}

		return null;
	}

	/**
	 * 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();
	}

	

	

	/**
	 * Creates a new patchset with metadata.
	 *
	 * @param ticket
	 * @param mergeBase
	 * @param tip
	 */
	private Patchset newPatchset(TicketModel ticket, String mergeBase, String tip) {
		int totalCommits = JGitUtils.countCommits(getRepository(), getRevWalk(), mergeBase, tip);

		Patchset newPatchset = new Patchset();
		newPatchset.tip = tip;
		newPatchset.base = mergeBase;
		newPatchset.commits = totalCommits;

		Patchset currPatchset = ticket == null ? null : ticket.getCurrentPatchset();
		if (currPatchset == null) {
			/*
			 * PROPOSAL PATCHSET
			 * patchset 1, rev 1
			 */
			newPatchset.number = 1;
			newPatchset.rev = 1;
			newPatchset.type = PatchsetType.Proposal;

			// diffstat from merge base
			DiffStat diffStat = DiffUtils.getDiffStat(getRepository(), mergeBase, tip);
			newPatchset.insertions = diffStat.getInsertions();
			newPatchset.deletions = diffStat.getDeletions();
		} else {
			/*
			 * PATCHSET UPDATE
			 */
			int added = totalCommits - currPatchset.commits;
			boolean ff = JGitUtils.isMergedInto(getRepository(), currPatchset.tip, tip);
			boolean squash = added < 0;
			boolean rebase = !currPatchset.base.equals(mergeBase);

			// determine type, number and rev of the patchset
			if (ff) {
				/*
				 * FAST-FORWARD
				 * patchset number preserved, rev incremented
				 */

				boolean merged = JGitUtils.isMergedInto(getRepository(), currPatchset.tip, ticket.mergeTo);
				if (merged) {
					// current patchset was already merged
					// new patchset, mark as rebase
					newPatchset.type = PatchsetType.Rebase;
					newPatchset.number = currPatchset.number + 1;
					newPatchset.rev = 1;

					// diffstat from parent
					DiffStat diffStat = DiffUtils.getDiffStat(getRepository(), mergeBase, tip);
					newPatchset.insertions = diffStat.getInsertions();
					newPatchset.deletions = diffStat.getDeletions();
				} else {
					// FF update to patchset
					newPatchset.type = PatchsetType.FastForward;
					newPatchset.number = currPatchset.number;
					newPatchset.rev = currPatchset.rev + 1;
					newPatchset.parent = currPatchset.tip;

					// diffstat from parent
					DiffStat diffStat = DiffUtils.getDiffStat(getRepository(), currPatchset.tip, tip);
					newPatchset.insertions = diffStat.getInsertions();
					newPatchset.deletions = diffStat.getDeletions();
				}
			} else {
				/*
				 * NON-FAST-FORWARD
				 * new patchset, rev 1
				 */
				if (rebase && squash) {
					newPatchset.type = PatchsetType.Rebase_Squash;
					newPatchset.number = currPatchset.number + 1;
					newPatchset.rev = 1;
				} else if (squash) {
					newPatchset.type = PatchsetType.Squash;
					newPatchset.number = currPatchset.number + 1;
					newPatchset.rev = 1;
				} else if (rebase) {
					newPatchset.type = PatchsetType.Rebase;
					newPatchset.number = currPatchset.number + 1;
					newPatchset.rev = 1;
				} else {
					newPatchset.type = PatchsetType.Amend;
					newPatchset.number = currPatchset.number + 1;
					newPatchset.rev = 1;
				}

				// diffstat from merge base
				DiffStat diffStat = DiffUtils.getDiffStat(getRepository(), mergeBase, tip);
				newPatchset.insertions = diffStat.getInsertions();
				newPatchset.deletions = diffStat.getDeletions();
			}

			if (added > 0) {
				// ignore squash (negative add)
				newPatchset.added = added;
			}
		}

		return newPatchset;
	}

	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;
	}

	private void updateReflog(RefUpdate ru) {
		if (ru == null) {
			return;
		}

		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:
			LOGGER.error(MessageFormat.format("unexpected ref update type {0} for {1}",
					ru.getResult(), ru.getName()));
			return;
		}
		ReceiveCommand cmd = new ReceiveCommand(ru.getOldObjectId(), ru.getNewObjectId(), ru.getName(), type);
		RefLogUtils.updateRefLog(user, getRepository(), Arrays.asList(cmd));
	}

	/**
	 * Merge the specified patchset to the integration branch.
	 *
	 * @param ticket
	 * @param patchset
	 * @return true, if successful
	 */
	public MergeStatus merge(TicketModel ticket) {
		PersonIdent committer = new PersonIdent(user.getDisplayName(), StringUtils.isEmpty(user.emailAddress) ? (user.username + "@gitblit") : user.emailAddress);
		Patchset patchset = ticket.getCurrentPatchset();
		String message = MessageFormat.format("Merged #{0,number,0} \"{1}\"", ticket.number, ticket.title);
		Ref oldRef = null;
		try {
			oldRef = getRepository().getRef(ticket.mergeTo);
		} catch (IOException e) {
			LOGGER.error("failed to get ref for " + ticket.mergeTo, e);
		}
		MergeResult mergeResult = JGitUtils.merge(
				getRepository(),
				patchset.tip,
				ticket.mergeTo,
				getRepositoryModel().mergeType,
				committer,
				message);

		if (StringUtils.isEmpty(mergeResult.sha)) {
			LOGGER.error("FAILED to merge {} to {} ({})", new Object [] { patchset, ticket.mergeTo, mergeResult.status.name() });
			return mergeResult.status;
		}
		Change change = new Change(user.username);
		change.setField(Field.status, Status.Merged);
		change.setField(Field.mergeSha, mergeResult.sha);
		change.setField(Field.mergeTo, ticket.mergeTo);

		if (StringUtils.isEmpty(ticket.responsible)) {
			// unassigned tickets are assigned to the closer
			change.setField(Field.responsible, user.username);
		}

		long ticketId = ticket.number;
		ticket = ticketService.updateTicket(repository, ticket.number, change);
		if (ticket != null) {
			ticketNotifier.queueMailing(ticket);

			if (oldRef != null) {
				ReceiveCommand cmd = new ReceiveCommand(oldRef.getObjectId(),
						ObjectId.fromString(mergeResult.sha), oldRef.getName());
				cmd.setResult(Result.OK);
				List<ReceiveCommand> commands = Arrays.asList(cmd);

				logRefChange(commands);
				updateIncrementalPushTags(commands);
				updateGitblitRefLog(commands);
			}

			// call patchset hooks
			for (PatchsetHook hook : gitblit.getExtensions(PatchsetHook.class)) {
				try {
					hook.onMergePatchset(ticket);
				} catch (Exception e) {
					LOGGER.error("Failed to execute extension", e);
				}
			}
			return mergeResult.status;
		} else {
			LOGGER.error("FAILED to resolve ticket {} by merge from web ui", ticketId);
		}
		return mergeResult.status;
	}

	public void sendAll() {
		ticketNotifier.sendAll();
	}
}
