/** * 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(); } }
/** * 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.projectPath; ticket.repository = repository.name; ticket.number = ticketId; } return ticket; } finally { db.close(); } }
/** * 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.projectPath; 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(); } }