summaryrefslogtreecommitdiffstats
path: root/src/main/java/com/gitblit/tickets
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/gitblit/tickets')
-rw-r--r--src/main/java/com/gitblit/tickets/BranchTicketService.java67
-rw-r--r--src/main/java/com/gitblit/tickets/FileTicketService.java68
-rw-r--r--src/main/java/com/gitblit/tickets/ITicketService.java44
-rw-r--r--src/main/java/com/gitblit/tickets/NullTicketService.java11
-rw-r--r--src/main/java/com/gitblit/tickets/RedisTicketService.java70
5 files changed, 232 insertions, 28 deletions
diff --git a/src/main/java/com/gitblit/tickets/BranchTicketService.java b/src/main/java/com/gitblit/tickets/BranchTicketService.java
index 284b1be1..8c000550 100644
--- a/src/main/java/com/gitblit/tickets/BranchTicketService.java
+++ b/src/main/java/com/gitblit/tickets/BranchTicketService.java
@@ -378,6 +378,37 @@ public class BranchTicketService extends ITicketService implements RefsChangedLi
}
/**
+ * 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
@@ -398,16 +429,10 @@ public class BranchTicketService extends ITicketService implements RefsChangedLi
}
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);
}
}
}
@@ -526,6 +551,28 @@ public class BranchTicketService extends ITicketService implements RefsChangedLi
}
/**
+ * 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
diff --git a/src/main/java/com/gitblit/tickets/FileTicketService.java b/src/main/java/com/gitblit/tickets/FileTicketService.java
index 4386020f..b3d8838e 100644
--- a/src/main/java/com/gitblit/tickets/FileTicketService.java
+++ b/src/main/java/com/gitblit/tickets/FileTicketService.java
@@ -22,6 +22,8 @@ import java.util.ArrayList;
import java.util.Collections;
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.atomic.AtomicLong;
@@ -146,6 +148,31 @@ public class FileTicketService extends ITicketService {
return hasTicket;
}
+ @Override
+ public synchronized Set<Long> getIds(RepositoryModel repository) {
+ Set<Long> ids = new TreeSet<Long>();
+ Repository db = repositoryManager.getRepository(repository.name);
+ try {
+ // identify current highest ticket id by scanning the paths in the tip tree
+ File dir = new File(db.getDirectory(), TICKETS_PATH);
+ dir.mkdirs();
+ List<File> journals = findAll(dir, JOURNAL);
+ for (File journal : journals) {
+ // Reconstruct ticketId from the path
+ // id/26/326/journal.json
+ String path = FileUtils.getRelativePath(dir, journal);
+ String tid = path.split("/")[1];
+ long ticketId = Long.parseLong(tid);
+ ids.add(ticketId);
+ }
+ } finally {
+ if (db != null) {
+ db.close();
+ }
+ }
+ return ids;
+ }
+
/**
* Assigns a new ticket id.
*
@@ -162,18 +189,10 @@ public class FileTicketService extends ITicketService {
}
AtomicLong lastId = lastAssignedId.get(repository.name);
if (lastId.get() <= 0) {
- // identify current highest ticket id by scanning the paths in the tip tree
- File dir = new File(db.getDirectory(), TICKETS_PATH);
- dir.mkdirs();
- List<File> journals = findAll(dir, JOURNAL);
- for (File journal : journals) {
- // Reconstruct ticketId from the path
- // id/26/326/journal.json
- String path = FileUtils.getRelativePath(dir, journal);
- String tid = path.split("/")[1];
- 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);
}
}
}
@@ -284,8 +303,7 @@ public class FileTicketService extends ITicketService {
}
/**
- * Retrieves the ticket from the repository by first looking-up the changeId
- * associated with the ticketId.
+ * Retrieves the ticket from the repository.
*
* @param repository
* @param ticketId
@@ -313,6 +331,28 @@ public class FileTicketService extends ITicketService {
}
/**
+ * 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
diff --git a/src/main/java/com/gitblit/tickets/ITicketService.java b/src/main/java/com/gitblit/tickets/ITicketService.java
index 3261ca96..a6a7a75a 100644
--- a/src/main/java/com/gitblit/tickets/ITicketService.java
+++ b/src/main/java/com/gitblit/tickets/ITicketService.java
@@ -65,6 +65,8 @@ import com.google.common.cache.CacheBuilder;
*/
public abstract class ITicketService {
+ public static final String SETTING_UPDATE_DIFFSTATS = "migration.updateDiffstats";
+
private static final String LABEL = "label";
private static final String MILESTONE = "milestone";
@@ -107,6 +109,8 @@ public abstract class ITicketService {
private final Map<String, List<TicketMilestone>> milestonesCache;
+ private final boolean updateDiffstats;
+
private static class TicketKey {
final String repository;
final long ticketId;
@@ -164,6 +168,8 @@ public abstract class ITicketService {
this.labelsCache = new ConcurrentHashMap<String, List<TicketLabel>>();
this.milestonesCache = new ConcurrentHashMap<String, List<TicketMilestone>>();
+
+ this.updateDiffstats = settings.getBoolean(SETTING_UPDATE_DIFFSTATS, true);
}
/**
@@ -762,6 +768,15 @@ public abstract class ITicketService {
}
/**
+ * Returns the set of assigned ticket ids in the repository.
+ *
+ * @param repository
+ * @return a set of assigned ticket ids in the repository
+ * @since 1.6.0
+ */
+ public abstract Set<Long> getIds(RepositoryModel repository);
+
+ /**
* Assigns a new ticket id.
*
* @param repository
@@ -823,7 +838,7 @@ public abstract class ITicketService {
ticket = getTicketImpl(repository, ticketId);
// if ticket exists
if (ticket != null) {
- if (ticket.hasPatchsets()) {
+ if (ticket.hasPatchsets() && updateDiffstats) {
Repository r = repositoryManager.getRepository(repository.name);
try {
Patchset patchset = ticket.getCurrentPatchset();
@@ -856,6 +871,33 @@ public abstract class ITicketService {
*/
protected abstract TicketModel getTicketImpl(RepositoryModel repository, long ticketId);
+
+ /**
+ * Returns the journal used to build a ticket.
+ *
+ * @param repository
+ * @param ticketId
+ * @return the journal for the ticket, if it exists, otherwise null
+ * @since 1.6.0
+ */
+ public final List<Change> getJournal(RepositoryModel repository, long ticketId) {
+ if (hasTicket(repository, ticketId)) {
+ List<Change> journal = getJournalImpl(repository, ticketId);
+ return journal;
+ }
+ return null;
+ }
+
+ /**
+ * Retrieves the ticket journal.
+ *
+ * @param repository
+ * @param ticketId
+ * @return a ticket, if it exists, otherwise null
+ * @since 1.6.0
+ */
+ protected abstract List<Change> getJournalImpl(RepositoryModel repository, long ticketId);
+
/**
* Get the ticket url
*
diff --git a/src/main/java/com/gitblit/tickets/NullTicketService.java b/src/main/java/com/gitblit/tickets/NullTicketService.java
index 749d8018..d410cdd0 100644
--- a/src/main/java/com/gitblit/tickets/NullTicketService.java
+++ b/src/main/java/com/gitblit/tickets/NullTicketService.java
@@ -17,6 +17,7 @@ package com.gitblit.tickets;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
import com.gitblit.manager.INotificationManager;
import com.gitblit.manager.IPluginManager;
@@ -78,6 +79,11 @@ public class NullTicketService extends ITicketService {
}
@Override
+ public synchronized Set<Long> getIds(RepositoryModel repository) {
+ return Collections.emptySet();
+ }
+
+ @Override
public synchronized long assignNewId(RepositoryModel repository) {
return 0L;
}
@@ -93,6 +99,11 @@ public class NullTicketService extends ITicketService {
}
@Override
+ protected List<Change> getJournalImpl(RepositoryModel repository, long ticketId) {
+ return null;
+ }
+
+ @Override
public boolean supportsAttachments() {
return false;
}
diff --git a/src/main/java/com/gitblit/tickets/RedisTicketService.java b/src/main/java/com/gitblit/tickets/RedisTicketService.java
index 2c5b181f..d773b0bd 100644
--- a/src/main/java/com/gitblit/tickets/RedisTicketService.java
+++ b/src/main/java/com/gitblit/tickets/RedisTicketService.java
@@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
+import java.util.TreeSet;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
@@ -184,6 +185,30 @@ public class RedisTicketService extends ITicketService {
return false;
}
+ @Override
+ public Set<Long> getIds(RepositoryModel repository) {
+ Set<Long> ids = new TreeSet<Long>();
+ Jedis jedis = pool.getResource();
+ try {// account for migrated tickets
+ Set<String> keys = jedis.keys(key(repository, KeyType.journal, "*"));
+ for (String tkey : keys) {
+ // {repo}:journal:{id}
+ String id = tkey.split(":")[2];
+ long ticketId = Long.parseLong(id);
+ ids.add(ticketId);
+ }
+ } catch (JedisException e) {
+ log.error("failed to assign new ticket id in Redis @ " + getUrl(), e);
+ pool.returnBrokenResource(jedis);
+ jedis = null;
+ } finally {
+ if (jedis != null) {
+ pool.returnResource(jedis);
+ }
+ }
+ return ids;
+ }
+
/**
* Assigns a new ticket id.
*
@@ -197,7 +222,14 @@ public class RedisTicketService extends ITicketService {
String key = key(repository, KeyType.counter, null);
String val = jedis.get(key);
if (isNull(val)) {
- jedis.set(key, "0");
+ long lastId = 0;
+ Set<Long> ids = getIds(repository);
+ for (long id : ids) {
+ if (id > lastId) {
+ lastId = id;
+ }
+ }
+ jedis.set(key, "" + lastId);
}
long ticketNumber = jedis.incr(key);
return ticketNumber;
@@ -273,8 +305,7 @@ public class RedisTicketService extends ITicketService {
}
/**
- * Retrieves the ticket from the repository by first looking-up the changeId
- * associated with the ticketId.
+ * Retrieves the ticket from the repository.
*
* @param repository
* @param ticketId
@@ -312,6 +343,39 @@ public class RedisTicketService extends ITicketService {
}
/**
+ * 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) {
+ Jedis jedis = pool.getResource();
+ if (jedis == null) {
+ return null;
+ }
+
+ try {
+ List<Change> changes = getJournal(jedis, repository, ticketId);
+ if (ArrayUtils.isEmpty(changes)) {
+ log.warn("Empty journal for {}:{}", repository, ticketId);
+ return null;
+ }
+ return changes;
+ } catch (JedisException e) {
+ log.error("failed to retrieve journal from Redis @ " + getUrl(), e);
+ pool.returnBrokenResource(jedis);
+ jedis = null;
+ } finally {
+ if (jedis != null) {
+ pool.returnResource(jedis);
+ }
+ }
+ return null;
+ }
+
+ /**
* Returns the journal for the specified ticket.
*
* @param repository