/*
 * 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 groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;

import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;

import org.eclipse.jgit.lib.AnyObjectId;
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.RevWalk;
import org.eclipse.jgit.transport.PostReceiveHook;
import org.eclipse.jgit.transport.PreReceiveHook;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.transport.ReceiveCommand.Result;
import org.eclipse.jgit.transport.ReceivePack;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.Constants;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.client.Translation;
import com.gitblit.extensions.ReceiveHook;
import com.gitblit.manager.IGitblit;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.TicketModel;
import com.gitblit.models.UserModel;
import com.gitblit.models.TicketModel.Change;
import com.gitblit.models.TicketModel.Field;
import com.gitblit.models.TicketModel.Patchset;
import com.gitblit.models.TicketModel.Status;
import com.gitblit.models.TicketModel.TicketAction;
import com.gitblit.models.TicketModel.TicketLink;
import com.gitblit.tickets.BranchTicketService;
import com.gitblit.tickets.ITicketService;
import com.gitblit.tickets.TicketNotifier;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.ClientLogger;
import com.gitblit.utils.CommitCache;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.RefLogUtils;
import com.gitblit.utils.StringUtils;
import com.google.common.collect.Lists;


/**
 * GitblitReceivePack processes receive commands.  It also executes Groovy pre-
 * and post- receive hooks.
 *
 * 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 GitblitReceivePack extends ReceivePack implements PreReceiveHook, PostReceiveHook {

	private static final Logger LOGGER = LoggerFactory.getLogger(GitblitReceivePack.class);

	protected final RepositoryModel repository;

	protected final UserModel user;

	protected final File groovyDir;

	protected String gitblitUrl;

	protected GroovyScriptEngine gse;

	protected final IStoredSettings settings;

	protected final IGitblit gitblit;
	
	protected final ITicketService ticketService;

	protected final TicketNotifier ticketNotifier;
	

	public GitblitReceivePack(
			IGitblit gitblit,
			Repository db,
			RepositoryModel repository,
			UserModel user) {

		super(db);
		this.settings = gitblit.getSettings();
		this.gitblit = gitblit;
		this.repository = repository;
		this.user = user;
		this.groovyDir = gitblit.getHooksFolder();
		try {
			// set Grape root
			File grapeRoot = gitblit.getGrapesFolder();
			grapeRoot.mkdirs();
			System.setProperty("grape.root", grapeRoot.getAbsolutePath());
			this.gse = new GroovyScriptEngine(groovyDir.getAbsolutePath());
		} catch (IOException e) {
		}

		if (gitblit.getTicketService().isAcceptingTicketUpdates(repository)) {
			this.ticketService = gitblit.getTicketService();
			this.ticketNotifier = this.ticketService.createNotifier();
		} else {
			this.ticketService = null;
			this.ticketNotifier = null;
		}
		
		// set advanced ref permissions
		setAllowCreates(user.canCreateRef(repository));
		setAllowDeletes(user.canDeleteRef(repository));
		setAllowNonFastForwards(user.canRewindRef(repository));

		int maxObjectSz = settings.getInteger(Keys.git.maxObjectSizeLimit, -1);
		if (maxObjectSz >= 0) {
			setMaxObjectSizeLimit(maxObjectSz);
		}
		int maxPackSz = settings.getInteger(Keys.git.maxPackSizeLimit, -1);
		if (maxPackSz >= 0) {
			setMaxPackSizeLimit(maxPackSz);
		}
		setCheckReceivedObjects(settings.getBoolean(Keys.git.checkReceivedObjects, true));
		setCheckReferencedObjectsAreReachable(settings.getBoolean(Keys.git.checkReferencedObjectsAreReachable, true));

		// setup pre and post receive hook
		setPreReceiveHook(this);
		setPostReceiveHook(this);
	}

	/**
	 * Returns true if the user is permitted to apply the receive commands to
	 * the repository.
	 *
	 * @param commands
	 * @return true if the user may push these commands
	 */
	protected boolean canPush(Collection<ReceiveCommand> commands) {
		// TODO Consider supporting branch permissions here (issue-36)
		// Not sure if that should be Gerrit-style, refs/meta/config, or
		// gitolite-style, permissions in users.conf
		//
		// How could commands be empty?
		//
		// Because a subclass, like PatchsetReceivePack, filters receive
		// commands before this method is called.  This makes it possible for
		// this method to test an empty list.  In this case, we assume that the
		// subclass receive pack properly enforces push restrictions. for the
		// ref.
		//
		// The empty test is not explicitly required, it's written here to
		// clarify special-case behavior.

		return commands.isEmpty() ? true : user.canPush(repository);
	}

	/**
	 * 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.
	 */
	@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()));
			}
		}
	}

	/**
	 * 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.
	 */
	@Override
	public void onPostReceive(ReceivePack rp, Collection<ReceiveCommand> commands) {
		if (commands.size() == 0) {
			LOGGER.debug("skipping post-receive processing, no refs created, updated, or removed");
			return;
		}

		logRefChange(commands);
		updateIncrementalPushTags(commands);
		updateGitblitRefLog(commands);

		// 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 ReceiveCommandEvent(repository, cmd));
			}
		}

		// call post-receive plugins
		for (ReceiveHook hook : gitblit.getExtensions(ReceiveHook.class)) {
			try {
				hook.onPostReceive(this, commands);
			} catch (Exception e) {
				LOGGER.error("Failed to execute extension", e);
			}
		}

		// run Groovy hook scripts
		Set<String> scripts = new LinkedHashSet<String>();
		scripts.addAll(gitblit.getPostReceiveScriptsInherited(repository));
		if (!ArrayUtils.isEmpty(repository.postReceiveScripts)) {
			scripts.addAll(repository.postReceiveScripts);
		}
		runGroovy(commands, scripts);
	}

	/**
	 * Log the ref changes in the container log.
	 *
	 * @param commands
	 */
	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);
		}
	}

	/**
	 * Optionally update the incremental push tags.
	 *
	 * @param commands
	 */
	protected void updateIncrementalPushTags(Collection<ReceiveCommand> commands) {
		if (!repository.useIncrementalPushTags) {
			return;
		}

		// tag each pushed branch tip
		String emailAddress = user.emailAddress == null ? getRefLogIdent().getEmailAddress() : user.emailAddress;
		PersonIdent userIdent = new PersonIdent(user.getDisplayName(), emailAddress);

		for (ReceiveCommand cmd : commands) {
			if (!cmd.getRefName().startsWith(Constants.R_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(Constants.R_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 = settings.getString(Keys.git.defaultIncrementalPushTagPrefix, "r");
				} else {
					prefix = repository.incrementalPushTagPrefix;
				}

				JGitUtils.createIncrementalRevisionTag(
						getRepository(),
						objectId,
						userIdent,
						prefix,
						"0",
						msg);
			}
		}
	}

	/**
	 * Update Gitblit's internal reflog.
	 *
	 * @param commands
	 */
	protected void updateGitblitRefLog(Collection<ReceiveCommand> commands) {
		try {
			RefLogUtils.updateRefLog(user, getRepository(), commands);
			LOGGER.debug(MessageFormat.format("{0} reflog updated", repository.name));
		} catch (Exception e) {
			LOGGER.error(MessageFormat.format("Failed to update {0} reflog", repository.name), e);
		}
	}

	/** Execute commands to update references. */
	@Override
	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);
		}
	}

	protected void setGitblitUrl(String url) {
		this.gitblitUrl = url;
	}

	public void sendRejection(final ReceiveCommand cmd, final String why, Object... objects) {
		String text;
		if (ArrayUtils.isEmpty(objects)) {
			text = why;
		} else {
			text = MessageFormat.format(why, objects);
		}
		cmd.setResult(Result.REJECTED_OTHER_REASON, text);
		LOGGER.error(text + " (" + user.username + ")");
	}

	public void sendHeader(String msg, Object... objects) {
		sendInfo("--> ", msg, objects);
	}

	public void sendInfo(String msg, Object... objects) {
		sendInfo("    ", msg, objects);
	}

	private void sendInfo(String prefix, String msg, Object... objects) {
		String text;
		if (ArrayUtils.isEmpty(objects)) {
			text = msg;
			super.sendMessage(prefix + msg);
		} else {
			text = MessageFormat.format(msg, objects);
			super.sendMessage(prefix + text);
		}
		if (!StringUtils.isEmpty(msg)) {
			LOGGER.info(text + " (" + user.username + ")");
		}
	}

	public void sendError(String msg, Object... objects) {
		String text;
		if (ArrayUtils.isEmpty(objects)) {
			text = msg;
			super.sendError(msg);
		} else {
			text = MessageFormat.format(msg, objects);
			super.sendError(text);
		}
		if (!StringUtils.isEmpty(msg)) {
			LOGGER.error(text + " (" + user.username + ")");
		}
	}

	/**
	 * Runs the specified Groovy hook scripts.
	 *
	 * @param repository
	 * @param user
	 * @param commands
	 * @param scripts
	 */
	private void runGroovy(Collection<ReceiveCommand> commands, Set<String> scripts) {
		if (scripts == null || scripts.size() == 0) {
			// no Groovy scripts to execute
			return;
		}

		Binding binding = new Binding();
		binding.setVariable("gitblit", gitblit);
		binding.setVariable("repository", repository);
		binding.setVariable("receivePack", this);
		binding.setVariable("user", user);
		binding.setVariable("commands", commands);
		binding.setVariable("url", gitblitUrl);
		binding.setVariable("logger", LOGGER);
		binding.setVariable("clientLogger", new ClientLogger(this));
		for (String script : scripts) {
			if (StringUtils.isEmpty(script)) {
				continue;
			}
			// allow script to be specified without .groovy extension
			// this is easier to read in the settings
			File file = new File(groovyDir, script);
			if (!file.exists() && !script.toLowerCase().endsWith(".groovy")) {
				file = new File(groovyDir, script + ".groovy");
				if (file.exists()) {
					script = file.getName();
				}
			}
			try {
				Object result = gse.run(script, binding);
				if (result instanceof Boolean) {
					if (!((Boolean) result)) {
						LOGGER.error(MessageFormat.format(
								"Groovy script {0} has failed!  Hook scripts aborted.", script));
						break;
					}
				}
			} catch (Exception e) {
				LOGGER.error(
						MessageFormat.format("Failed to execute Groovy script {0}", script), e);
			}
		}
	}

	public IGitblit getGitblit() {
		return gitblit;
	}

	public RepositoryModel getRepositoryModel() {
		return repository;
	}

	public UserModel getUserModel() {
		return user;
	}
	
	/**
	 * Automatically closes open tickets and adds references to tickets if made in the commit message.
	 *
	 * @param cmd
	 */
	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();
	}
}
