From a502d96a860456ec5e8c96761db70f7cabb74751 Mon Sep 17 00:00:00 2001
From: Paul Martin <paul@paulsputer.com>
Date: Sat, 30 Apr 2016 04:19:14 -0400
Subject: [PATCH] Merge pull request #1073 from gitblit/1062-DocEditorUpdates

---
 src/main/java/com/gitblit/tickets/BranchTicketService.java |  194 ++++++++++++++++++++----------------------------
 1 files changed, 81 insertions(+), 113 deletions(-)

diff --git a/src/main/java/com/gitblit/tickets/BranchTicketService.java b/src/main/java/com/gitblit/tickets/BranchTicketService.java
index f23a325..7bef435 100644
--- a/src/main/java/com/gitblit/tickets/BranchTicketService.java
+++ b/src/main/java/com/gitblit/tickets/BranchTicketService.java
@@ -19,7 +19,6 @@
 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;
@@ -31,21 +30,17 @@
 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;
@@ -58,6 +53,7 @@
 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;
@@ -71,6 +67,8 @@
 import com.gitblit.utils.ArrayUtils;
 import com.gitblit.utils.JGitUtils;
 import com.gitblit.utils.StringUtils;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
 
 /**
  * Implementation of a ticket service based on an orphan branch.  All tickets
@@ -80,6 +78,7 @@
  * @author James Moger
  *
  */
+@Singleton
 public class BranchTicketService extends ITicketService implements RefsChangedListener {
 
 	public static final String BRANCH = "refs/meta/gitblit/tickets";
@@ -90,13 +89,16 @@
 
 	private final Map<String, AtomicLong> lastAssignedId;
 
+	@Inject
 	public BranchTicketService(
 			IRuntimeManager runtimeManager,
+			IPluginManager pluginManager,
 			INotificationManager notificationManager,
 			IUserManager userManager,
 			IRepositoryManager repositoryManager) {
 
 		super(runtimeManager,
+				pluginManager,
 				notificationManager,
 				userManager,
 				repositoryManager);
@@ -109,6 +111,7 @@
 
 	@Override
 	public BranchTicketService start() {
+		log.info("{} started", getClass().getSimpleName());
 		return this;
 	}
 
@@ -289,7 +292,7 @@
 			log.error("failed to read " + file, e);
 		} finally {
 			if (rw != null) {
-				rw.release();
+				rw.close();
 			}
 		}
 		return null;
@@ -330,7 +333,7 @@
 			Set<String> ignorePaths = new HashSet<String>();
 			ignorePaths.add(file);
 
-			for (DirCacheEntry entry : getTreeEntries(db, ignorePaths)) {
+			for (DirCacheEntry entry : JGitUtils.getTreeEntries(db, BRANCH, ignorePaths)) {
 				builder.add(entry);
 			}
 
@@ -345,7 +348,7 @@
 		} catch (IOException e) {
 			log.error("", e);
 		} finally {
-			inserter.release();
+			inserter.close();
 		}
 	}
 
@@ -375,6 +378,37 @@
 	}
 
 	/**
+	 * 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
@@ -395,16 +429,10 @@
 			}
 			AtomicLong lastId = lastAssignedId.get(repository.name);
 			if (lastId.get() <= 0) {
-				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);
-					if (ticketId > lastId.get()) {
-						lastId.set(ticketId);
+				Set<Long> ids = getIds(repository);
+				for (long id : ids) {
+					if (id > lastId.get()) {
+						lastId.set(id);
 					}
 				}
 			}
@@ -517,6 +545,28 @@
 				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();
 		}
@@ -656,7 +706,9 @@
 						ticket.number, db.getDirectory()), t);
 			} finally {
 				// release the treewalk
-				treeWalk.release();
+				if (treeWalk != null) {
+					treeWalk.close();
+				}
 			}
 		} finally {
 			db.close();
@@ -747,116 +799,30 @@
 				}
 			}
 
-			for (DirCacheEntry entry : getTreeEntries(db, ignorePaths)) {
+			for (DirCacheEntry entry : JGitUtils.getTreeEntries(db, BRANCH, ignorePaths)) {
 				builder.add(entry);
 			}
 
 			// finish the index
 			builder.finish();
 		} finally {
-			inserter.release();
+			inserter.close();
 		}
 		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 {
+		final boolean forceCommit = true;
 		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();
-		}
+		
+		success = JGitUtils.commitIndex(db,  BRANCH,  index, headId, forceCommit, author, "gitblit@localhost", message);
+		
 		return success;
 	}
 
@@ -872,7 +838,9 @@
 		} catch (Exception e) {
 			log.error(null, e);
 		} finally {
-			db.close();
+			if (db != null) {
+				db.close();
+			}
 		}
 		return false;
 	}

--
Gitblit v1.9.1