/*
 * 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.tickets;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
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 org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.events.RefsChangedEvent;
import org.eclipse.jgit.events.RefsChangedListener;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefRename;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
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.IPluginManager;
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;
import com.gitblit.models.TicketModel.Attachment;
import com.gitblit.models.TicketModel.Change;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.StringUtils;

/**
 * Implementation of a ticket service based on an orphan branch.  All tickets
 * are serialized as a list of JSON changes and persisted in a hashed directory
 * structure, similar to the standard git loose object structure.
 *
 * @author James Moger
 *
 */
public class BranchTicketService extends ITicketService implements RefsChangedListener {

	public static final String BRANCH = "refs/meta/gitblit/tickets";

	private static final String JOURNAL = "journal.json";

	private static final String ID_PATH = "id/";

	private final Map<String, AtomicLong> lastAssignedId;

	public BranchTicketService(
			IRuntimeManager runtimeManager,
			IPluginManager pluginManager,
			INotificationManager notificationManager,
			IUserManager userManager,
			IRepositoryManager repositoryManager) {

		super(runtimeManager,
				pluginManager,
				notificationManager,
				userManager,
				repositoryManager);

		lastAssignedId = new ConcurrentHashMap<String, AtomicLong>();

		// register the branch ticket service for repository ref changes
		Repository.getGlobalListenerList().addRefsChangedListener(this);
	}

	@Override
	public BranchTicketService start() {
		return this;
	}

	@Override
	protected void resetCachesImpl() {
		lastAssignedId.clear();
	}

	@Override
	protected void resetCachesImpl(RepositoryModel repository) {
		if (lastAssignedId.containsKey(repository.name)) {
			lastAssignedId.get(repository.name).set(0);
		}
	}

	@Override
	protected void close() {
	}

	/**
	 * Listen for tickets branch changes and (re)index tickets, as appropriate
	 */
	@Override
	public synchronized void onRefsChanged(RefsChangedEvent event) {
		if (!(event instanceof ReceiveCommandEvent)) {
			return;
		}

		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);
		}
	}

	/**
	 * Returns a RefModel for the refs/meta/gitblit/tickets branch in the repository.
	 * If the branch can not be found, null is returned.
	 *
	 * @return a refmodel for the gitblit tickets branch or null
	 */
	private RefModel getTicketsBranch(Repository db) {
		List<RefModel> refs = JGitUtils.getRefs(db, "refs/");
		Ref oldRef = null;
		for (RefModel ref : refs) {
			if (ref.reference.getName().equals(BRANCH)) {
				return ref;
			} else if (ref.reference.getName().equals("refs/gitblit/tickets")) {
				oldRef = ref.reference;
			}
		}
		if (oldRef != null) {
			// rename old ref to refs/meta/gitblit/tickets
			RefRename cmd;
			try {
				cmd = db.renameRef(oldRef.getName(), BRANCH);
				cmd.setRefLogIdent(new PersonIdent("Gitblit", "gitblit@localhost"));
				cmd.setRefLogMessage("renamed " + oldRef.getName() + " => " + BRANCH);
				Result res = cmd.rename();
				switch (res) {
				case RENAMED:
					log.info(db.getDirectory() + " " + cmd.getRefLogMessage());
					return getTicketsBranch(db);
				default:
					log.error("failed to rename " + oldRef.getName() + " => " + BRANCH + " (" + res.name() + ")");
				}
			} catch (IOException e) {
				log.error("failed to rename tickets branch", e);
			}
		}
		return null;
	}

	/**
	 * Creates the refs/meta/gitblit/tickets branch.
	 * @param db
	 */
	private void createTicketsBranch(Repository db) {
		JGitUtils.createOrphanBranch(db, BRANCH, null);
	}

	/**
	 * Returns the ticket path. This follows the same scheme as Git's object
	 * store path where the first two characters of the hash id are the root
	 * folder with the remaining characters as a subfolder within that folder.
	 *
	 * @param ticketId
	 * @return the root path of the ticket content on the refs/meta/gitblit/tickets branch
	 */
	private String toTicketPath(long ticketId) {
		StringBuilder sb = new StringBuilder();
		sb.append(ID_PATH);
		long m = ticketId % 100L;
		if (m < 10) {
			sb.append('0');
		}
		sb.append(m);
		sb.append('/');
		sb.append(ticketId);
		return sb.toString();
	}

	/**
	 * Returns the path to the attachment for the specified ticket.
	 *
	 * @param ticketId
	 * @param filename
	 * @return the path to the specified attachment
	 */
	private String toAttachmentPath(long ticketId, String filename) {
		return toTicketPath(ticketId) + "/attachments/" + filename;
	}

	/**
	 * Reads a file from the tickets branch.
	 *
	 * @param db
	 * @param file
	 * @return the file content or null
	 */
	private String readTicketsFile(Repository db, String file) {
		RevWalk rw = null;
		try {
			ObjectId treeId = db.resolve(BRANCH + "^{tree}");
			if (treeId == null) {
				return null;
			}
			rw = new RevWalk(db);
			RevTree tree = rw.lookupTree(treeId);
			if (tree != null) {
				return JGitUtils.getStringContent(db, tree, file, Constants.ENCODING);
			}
		} catch (IOException e) {
			log.error("failed to read " + file, e);
		} finally {
			if (rw != null) {
				rw.release();
			}
		}
		return null;
	}

	/**
	 * Writes a file to the tickets branch.
	 *
	 * @param db
	 * @param file
	 * @param content
	 * @param createdBy
	 * @param msg
	 */
	private void writeTicketsFile(Repository db, String file, String content, String createdBy, String msg) {
		if (getTicketsBranch(db) == null) {
			createTicketsBranch(db);
		}

		DirCache newIndex = DirCache.newInCore();
		DirCacheBuilder builder = newIndex.builder();
		ObjectInserter inserter = db.newObjectInserter();

		try {
			// create an index entry for the revised index
			final DirCacheEntry idIndexEntry = new DirCacheEntry(file);
			idIndexEntry.setLength(content.length());
			idIndexEntry.setLastModified(System.currentTimeMillis());
			idIndexEntry.setFileMode(FileMode.REGULAR_FILE);

			// insert new ticket index
			idIndexEntry.setObjectId(inserter.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB,
					content.getBytes(Constants.ENCODING)));

			// add to temporary in-core index
			builder.add(idIndexEntry);

			Set<String> ignorePaths = new HashSet<String>();
			ignorePaths.add(file);

			for (DirCacheEntry entry : getTreeEntries(db, ignorePaths)) {
				builder.add(entry);
			}

			// finish temporary in-core index used for this commit
			builder.finish();

			// commit the change
			commitIndex(db, newIndex, createdBy, msg);

		} catch (ConcurrentRefUpdateException e) {
			log.error("", e);
		} catch (IOException e) {
			log.error("", e);
		} finally {
			inserter.release();
		}
	}

	/**
	 * Ensures that we have a ticket for this ticket id.
	 *
	 * @param repository
	 * @param ticketId
	 * @return true if the ticket exists
	 */
	@Override
	public boolean hasTicket(RepositoryModel repository, long ticketId) {
		boolean hasTicket = false;
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			RefModel ticketsBranch = getTicketsBranch(db);
			if (ticketsBranch == null) {
				return false;
			}
			String ticketPath = toTicketPath(ticketId);
			RevCommit tip = JGitUtils.getCommit(db, BRANCH);
			hasTicket = !JGitUtils.getFilesInPath(db, ticketPath, tip).isEmpty();
		} finally {
			db.close();
		}
		return hasTicket;
	}

	/**
	 * Returns the assigned ticket ids.
	 *
	 * @return the assigned ticket ids
	 */
	@Override
	public synchronized Set<Long> getIds(RepositoryModel repository) {
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			if (getTicketsBranch(db) == null) {
				return Collections.emptySet();
			}
			Set<Long> ids = new TreeSet<Long>();
			List<PathModel> paths = JGitUtils.getDocuments(db, Arrays.asList("json"), BRANCH);
			for (PathModel 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);
				ids.add(ticketId);
			}
			return ids;
		} finally {
			if (db != null) {
				db.close();
			}
		}
	}

	/**
	 * Assigns a new ticket id.
	 *
	 * @param repository
	 * @return a new long id
	 */
	@Override
	public synchronized long assignNewId(RepositoryModel repository) {
		long newId = 0L;
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			if (getTicketsBranch(db) == null) {
				createTicketsBranch(db);
			}

			// identify current highest ticket id by scanning the paths in the tip tree
			if (!lastAssignedId.containsKey(repository.name)) {
				lastAssignedId.put(repository.name, new AtomicLong(0));
			}
			AtomicLong lastId = lastAssignedId.get(repository.name);
			if (lastId.get() <= 0) {
				Set<Long> ids = getIds(repository);
				for (long id : ids) {
					if (id > lastId.get()) {
						lastId.set(id);
					}
				}
			}

			// assign the id and touch an empty journal to hold it's place
			newId = lastId.incrementAndGet();
			String journalPath = toTicketPath(newId) + "/" + JOURNAL;
			writeTicketsFile(db, journalPath, "", "gitblit", "assigned id #" + newId);
		} finally {
			db.close();
		}
		return newId;
	}

	/**
	 * Returns all the tickets in the repository. Querying tickets from the
	 * repository requires deserializing all tickets. This is an  expensive
	 * process and not recommended. Tickets are indexed by Lucene and queries
	 * should be executed against that index.
	 *
	 * @param repository
	 * @param filter
	 *            optional filter to only return matching results
	 * @return a list of tickets
	 */
	@Override
	public List<TicketModel> getTickets(RepositoryModel repository, TicketFilter filter) {
		List<TicketModel> list = new ArrayList<TicketModel>();

		Repository db = repositoryManager.getRepository(repository.name);
		try {
			RefModel ticketsBranch = getTicketsBranch(db);
			if (ticketsBranch == null) {
				return list;
			}

			// Collect the set of all json files
			List<PathModel> paths = JGitUtils.getDocuments(db, Arrays.asList("json"), BRANCH);

			// Deserialize each ticket and optionally filter out unwanted tickets
			for (PathModel path : paths) {
				String name = path.name.substring(path.name.lastIndexOf('/') + 1);
				if (!JOURNAL.equals(name)) {
					continue;
				}
				String json = readTicketsFile(db, path.path);
				if (StringUtils.isEmpty(json)) {
					// journal was touched but no changes were written
					continue;
				}
				try {
					// Reconstruct ticketId from the path
					// id/26/326/journal.json
					String tid = path.path.split("/")[2];
					long ticketId = Long.parseLong(tid);
					List<Change> changes = TicketSerializer.deserializeJournal(json);
					if (ArrayUtils.isEmpty(changes)) {
						log.warn("Empty journal for {}:{}", repository, path.path);
						continue;
					}
					TicketModel ticket = TicketModel.buildTicket(changes);
					ticket.project = repository.getProject();
					ticket.repository = repository.name;
					ticket.number = ticketId;

					// add the ticket, conditionally, to the list
					if (filter == null) {
						list.add(ticket);
					} else {
						if (filter.accept(ticket)) {
							list.add(ticket);
						}
					}
				} catch (Exception e) {
					log.error("failed to deserialize {}/{}\n{}",
							new Object [] { repository, path.path, e.getMessage()});
					log.error(null, e);
				}
			}

			// sort the tickets by creation
			Collections.sort(list);
			return list;
		} finally {
			db.close();
		}
	}

	/**
	 * Retrieves the ticket from the repository by first looking-up the changeId
	 * associated with the ticketId.
	 *
	 * @param repository
	 * @param ticketId
	 * @return a ticket, if it exists, otherwise null
	 */
	@Override
	protected TicketModel getTicketImpl(RepositoryModel repository, long ticketId) {
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			List<Change> changes = getJournal(db, ticketId);
			if (ArrayUtils.isEmpty(changes)) {
				log.warn("Empty journal for {}:{}", repository, ticketId);
				return null;
			}
			TicketModel ticket = TicketModel.buildTicket(changes);
			if (ticket != null) {
				ticket.project = repository.getProject();
				ticket.repository = repository.name;
				ticket.number = ticketId;
			}
			return ticket;
		} finally {
			db.close();
		}
	}

	/**
	 * Retrieves the journal for the ticket.
	 *
	 * @param repository
	 * @param ticketId
	 * @return a journal, if it exists, otherwise null
	 */
	@Override
	protected List<Change> getJournalImpl(RepositoryModel repository, long ticketId) {
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			List<Change> changes = getJournal(db, ticketId);
			if (ArrayUtils.isEmpty(changes)) {
				log.warn("Empty journal for {}:{}", repository, ticketId);
				return null;
			}
			return changes;
		} finally {
			db.close();
		}
	}

	/**
	 * Returns the journal for the specified ticket.
	 *
	 * @param db
	 * @param ticketId
	 * @return a list of changes
	 */
	private List<Change> getJournal(Repository db, long ticketId) {
		RefModel ticketsBranch = getTicketsBranch(db);
		if (ticketsBranch == null) {
			return new ArrayList<Change>();
		}

		if (ticketId <= 0L) {
			return new ArrayList<Change>();
		}

		String journalPath = toTicketPath(ticketId) + "/" + JOURNAL;
		String json = readTicketsFile(db, journalPath);
		if (StringUtils.isEmpty(json)) {
			return new ArrayList<Change>();
		}
		List<Change> list = TicketSerializer.deserializeJournal(json);
		return list;
	}

	@Override
	public boolean supportsAttachments() {
		return true;
	}

	/**
	 * Retrieves the specified attachment from a ticket.
	 *
	 * @param repository
	 * @param ticketId
	 * @param filename
	 * @return an attachment, if found, null otherwise
	 */
	@Override
	public Attachment getAttachment(RepositoryModel repository, long ticketId, String filename) {
		if (ticketId <= 0L) {
			return null;
		}

		// deserialize the ticket model so that we have the attachment metadata
		TicketModel ticket = getTicket(repository, ticketId);
		Attachment attachment = ticket.getAttachment(filename);

		// attachment not found
		if (attachment == null) {
			return null;
		}

		// retrieve the attachment content
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			String attachmentPath = toAttachmentPath(ticketId, attachment.name);
			RevTree tree = JGitUtils.getCommit(db, BRANCH).getTree();
			byte[] content = JGitUtils.getByteContent(db, tree, attachmentPath, false);
			attachment.content = content;
			attachment.size = content.length;
			return attachment;
		} finally {
			db.close();
		}
	}

	/**
	 * Deletes a ticket from the repository.
	 *
	 * @param ticket
	 * @return true if successful
	 */
	@Override
	protected synchronized boolean deleteTicketImpl(RepositoryModel repository, TicketModel ticket, String deletedBy) {
		if (ticket == null) {
			throw new RuntimeException("must specify a ticket!");
		}

		boolean success = false;
		Repository db = repositoryManager.getRepository(ticket.repository);
		try {
			RefModel ticketsBranch = getTicketsBranch(db);

			if (ticketsBranch == null) {
				throw new RuntimeException(BRANCH + " does not exist!");
			}
			String ticketPath = toTicketPath(ticket.number);

			TreeWalk treeWalk = null;
			try {
				ObjectId treeId = db.resolve(BRANCH + "^{tree}");

				// Create the in-memory index of the new/updated ticket
				DirCache index = DirCache.newInCore();
				DirCacheBuilder builder = index.builder();

				// Traverse HEAD to add all other paths
				treeWalk = new TreeWalk(db);
				int hIdx = -1;
				if (treeId != null) {
					hIdx = treeWalk.addTree(treeId);
				}
				treeWalk.setRecursive(true);
				while (treeWalk.next()) {
					String path = treeWalk.getPathString();
					CanonicalTreeParser hTree = null;
					if (hIdx != -1) {
						hTree = treeWalk.getTree(hIdx, CanonicalTreeParser.class);
					}
					if (!path.startsWith(ticketPath)) {
						// add entries from HEAD for all other paths
						if (hTree != null) {
							final DirCacheEntry entry = new DirCacheEntry(path);
							entry.setObjectId(hTree.getEntryObjectId());
							entry.setFileMode(hTree.getEntryFileMode());

							// add to temporary in-core index
							builder.add(entry);
						}
					}
				}

				// finish temporary in-core index used for this commit
				builder.finish();

				success = commitIndex(db, index, deletedBy, "- " + ticket.number);

			} catch (Throwable t) {
				log.error(MessageFormat.format("Failed to delete ticket {0,number,0} from {1}",
						ticket.number, db.getDirectory()), t);
			} finally {
				// release the treewalk
				if (treeWalk != null) {
					treeWalk.release();
				}
			}
		} finally {
			db.close();
		}
		return success;
	}

	/**
	 * Commit a ticket change to the repository.
	 *
	 * @param repository
	 * @param ticketId
	 * @param change
	 * @return true, if the change was committed
	 */
	@Override
	protected synchronized boolean commitChangeImpl(RepositoryModel repository, long ticketId, Change change) {
		boolean success = false;

		Repository db = repositoryManager.getRepository(repository.name);
		try {
			DirCache index = createIndex(db, ticketId, change);
			success = commitIndex(db, index, change.author, "#" + ticketId);

		} catch (Throwable t) {
			log.error(MessageFormat.format("Failed to commit ticket {0,number,0} to {1}",
					ticketId, db.getDirectory()), t);
		} finally {
			db.close();
		}
		return success;
	}

	/**
	 * Creates an in-memory index of the ticket change.
	 *
	 * @param changeId
	 * @param change
	 * @return an in-memory index
	 * @throws IOException
	 */
	private DirCache createIndex(Repository db, long ticketId, Change change)
			throws IOException, ClassNotFoundException, NoSuchFieldException {

		String ticketPath = toTicketPath(ticketId);
		DirCache newIndex = DirCache.newInCore();
		DirCacheBuilder builder = newIndex.builder();
		ObjectInserter inserter = db.newObjectInserter();

		Set<String> ignorePaths = new TreeSet<String>();
		try {
			// create/update the journal
			// exclude the attachment content
			List<Change> changes = getJournal(db, ticketId);
			changes.add(change);
			String journal = TicketSerializer.serializeJournal(changes).trim();

			byte [] journalBytes = journal.getBytes(Constants.ENCODING);
			String journalPath = ticketPath + "/" + JOURNAL;
			final DirCacheEntry journalEntry = new DirCacheEntry(journalPath);
			journalEntry.setLength(journalBytes.length);
			journalEntry.setLastModified(change.date.getTime());
			journalEntry.setFileMode(FileMode.REGULAR_FILE);
			journalEntry.setObjectId(inserter.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, journalBytes));

			// add journal to index
			builder.add(journalEntry);
			ignorePaths.add(journalEntry.getPathString());

			// Add any attachments to the index
			if (change.hasAttachments()) {
				for (Attachment attachment : change.attachments) {
					// build a path name for the attachment and mark as ignored
					String path = toAttachmentPath(ticketId, attachment.name);
					ignorePaths.add(path);

					// create an index entry for this attachment
					final DirCacheEntry entry = new DirCacheEntry(path);
					entry.setLength(attachment.content.length);
					entry.setLastModified(change.date.getTime());
					entry.setFileMode(FileMode.REGULAR_FILE);

					// insert object
					entry.setObjectId(inserter.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, attachment.content));

					// add to temporary in-core index
					builder.add(entry);
				}
			}

			for (DirCacheEntry entry : getTreeEntries(db, ignorePaths)) {
				builder.add(entry);
			}

			// finish the index
			builder.finish();
		} finally {
			inserter.release();
		}
		return newIndex;
	}

	/**
	 * Returns all tree entries that do not match the ignore paths.
	 *
	 * @param db
	 * @param ignorePaths
	 * @param dcBuilder
	 * @throws IOException
	 */
	private List<DirCacheEntry> getTreeEntries(Repository db, Collection<String> ignorePaths) throws IOException {
		List<DirCacheEntry> list = new ArrayList<DirCacheEntry>();
		TreeWalk tw = null;
		try {
			tw = new TreeWalk(db);
			ObjectId treeId = db.resolve(BRANCH + "^{tree}");
			int hIdx = tw.addTree(treeId);
			tw.setRecursive(true);

			while (tw.next()) {
				String path = tw.getPathString();
				CanonicalTreeParser hTree = null;
				if (hIdx != -1) {
					hTree = tw.getTree(hIdx, CanonicalTreeParser.class);
				}
				if (!ignorePaths.contains(path)) {
					// add all other tree entries
					if (hTree != null) {
						final DirCacheEntry entry = new DirCacheEntry(path);
						entry.setObjectId(hTree.getEntryObjectId());
						entry.setFileMode(hTree.getEntryFileMode());
						list.add(entry);
					}
				}
			}
		} finally {
			if (tw != null) {
				tw.release();
			}
		}
		return list;
	}

	private boolean commitIndex(Repository db, DirCache index, String author, String message) throws IOException, ConcurrentRefUpdateException {
		boolean success = false;

		ObjectId headId = db.resolve(BRANCH + "^{commit}");
		if (headId == null) {
			// create the branch
			createTicketsBranch(db);
			headId = db.resolve(BRANCH + "^{commit}");
		}
		ObjectInserter odi = db.newObjectInserter();
		try {
			// Create the in-memory index of the new/updated ticket
			ObjectId indexTreeId = index.writeTree(odi);

			// Create a commit object
			PersonIdent ident = new PersonIdent(author, "gitblit@localhost");
			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(db);
			try {
				RevCommit revCommit = revWalk.parseCommit(commitId);
				RefUpdate ru = db.updateRef(BRANCH);
				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, BRANCH, commitId.toString(),
							rc));
				}
			} finally {
				revWalk.release();
			}
		} finally {
			odi.release();
		}
		return success;
	}

	@Override
	protected boolean deleteAllImpl(RepositoryModel repository) {
		Repository db = repositoryManager.getRepository(repository.name);
		try {
			RefModel branch = getTicketsBranch(db);
			if (branch != null) {
				return JGitUtils.deleteBranchRef(db, BRANCH);
			}
			return true;
		} catch (Exception e) {
			log.error(null, e);
		} finally {
			if (db != null) {
				db.close();
			}
		}
		return false;
	}

	@Override
	protected boolean renameImpl(RepositoryModel oldRepository, RepositoryModel newRepository) {
		return true;
	}

	@Override
	public String toString() {
		return getClass().getSimpleName();
	}
}
