From a04808340abb7056fefb45645d9f5653813338fc Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Tue, 17 Sep 2013 17:49:20 -0400 Subject: [PATCH] Removed unused Issues classes --- /dev/null | 231 --------------------------------- src/test/java/com/gitblit/tests/GitBlitSuite.java | 2 src/main/java/com/gitblit/LuceneExecutor.java | 137 +------------------ 3 files changed, 8 insertions(+), 362 deletions(-) diff --git a/src/main/java/com/gitblit/LuceneExecutor.java b/src/main/java/com/gitblit/LuceneExecutor.java index 0e4baae..3446289 100644 --- a/src/main/java/com/gitblit/LuceneExecutor.java +++ b/src/main/java/com/gitblit/LuceneExecutor.java @@ -56,7 +56,6 @@ import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; -import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TopScoreDocCollector; import org.apache.lucene.search.highlight.Fragmenter; import org.apache.lucene.search.highlight.Highlighter; @@ -86,14 +85,11 @@ import org.slf4j.LoggerFactory; import com.gitblit.Constants.SearchObjectType; -import com.gitblit.models.IssueModel; -import com.gitblit.models.IssueModel.Attachment; import com.gitblit.models.PathModel.PathChangeModel; import com.gitblit.models.RefModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.SearchResult; import com.gitblit.utils.ArrayUtils; -import com.gitblit.utils.IssueUtils; import com.gitblit.utils.JGitUtils; import com.gitblit.utils.StringUtils; @@ -109,7 +105,6 @@ private static final int INDEX_VERSION = 5; private static final String FIELD_OBJECT_TYPE = "type"; - private static final String FIELD_ISSUE = "issue"; private static final String FIELD_PATH = "path"; private static final String FIELD_COMMIT = "commit"; private static final String FIELD_BRANCH = "branch"; @@ -120,7 +115,6 @@ private static final String FIELD_DATE = "date"; private static final String FIELD_TAG = "tag"; private static final String FIELD_LABEL = "label"; - private static final String FIELD_ATTACHMENT = "attachment"; private static final String CONF_FILE = "lucene.conf"; private static final String LUCENE_DIR = "lucene"; @@ -475,9 +469,8 @@ && branch.equals(defaultBranch)) { // indexing "default" branch indexBranch = true; - } else if (IssueUtils.GB_ISSUES.equals(branch)) { - // skip the GB_ISSUES branch because it is indexed later - // note: this is different than updateIndex + } else if (branch.getName().startsWith(com.gitblit.Constants.R_GITBLIT)) { + // skip Gitblit internal branches indexBranch = false; } else { // normal explicit branch check @@ -617,19 +610,6 @@ // finished reader.release(); - // this repository has a gb-issues branch, index all issues - if (IssueUtils.getIssuesBranch(repository) != null) { - List<IssueModel> issues = IssueUtils.getIssues(repository, null); - if (issues.size() > 0) { - result.branchCount += 1; - } - for (IssueModel issue : issues) { - result.issueCount++; - Document doc = createDocument(issue); - writer.addDocument(doc); - } - } - // commit all changes and reset the searcher config.setInt(CONF_INDEX, null, CONF_VERSION, INDEX_VERSION); config.save(); @@ -722,55 +702,6 @@ return result; } - /** - * Incrementally update the index with the specified issue for the - * repository. - * - * @param repositoryName - * @param issue - * @return true, if successful - */ - public boolean index(String repositoryName, IssueModel issue) { - try { - // delete the old issue from the index, if exists - deleteIssue(repositoryName, issue.id); - Document doc = createDocument(issue); - return index(repositoryName, doc); - } catch (Exception e) { - logger.error(MessageFormat.format("Error while indexing issue {0} in {1}", issue.id, repositoryName), e); - } - return false; - } - - /** - * Delete an issue from the repository index. - * - * @param repositoryName - * @param issueId - * @throws Exception - * @return true, if deleted, false if no record was deleted - */ - private boolean deleteIssue(String repositoryName, String issueId) throws Exception { - BooleanQuery query = new BooleanQuery(); - Term objectTerm = new Term(FIELD_OBJECT_TYPE, SearchObjectType.issue.name()); - query.add(new TermQuery(objectTerm), Occur.MUST); - Term issueidTerm = new Term(FIELD_ISSUE, issueId); - query.add(new TermQuery(issueidTerm), Occur.MUST); - - IndexWriter writer = getIndexWriter(repositoryName); - int numDocsBefore = writer.numDocs(); - writer.deleteDocuments(query); - writer.commit(); - int numDocsAfter = writer.numDocs(); - if (numDocsBefore == numDocsAfter) { - logger.debug(MessageFormat.format("no records found to delete {0}", query.toString())); - return false; - } else { - logger.debug(MessageFormat.format("deleted {0} records with {1}", numDocsBefore - numDocsAfter, query.toString())); - return true; - } - } - /** * Delete a blob from the specified branch of the repository index. * @@ -870,10 +801,9 @@ && branch.equals(defaultBranch)) { // indexing "default" branch indexBranch = true; - } else if (IssueUtils.GB_ISSUES.equals(branch)) { - // update issues modified on the GB_ISSUES branch - // note: this is different than reindex - indexBranch = true; + } else if (branch.getName().startsWith(com.gitblit.Constants.R_GITBLIT)) { + // ignore internal Gitblit branches + indexBranch = false; } else { // normal explicit branch check indexBranch = model.indexedBranches.contains(branch.getName()); @@ -904,35 +834,11 @@ result.branchCount += 1; } - // track the issue ids that we have already indexed - Set<String> indexedIssues = new TreeSet<String>(); - // reverse the list of commits so we start with the first commit Collections.reverse(revs); for (RevCommit commit : revs) { - if (IssueUtils.GB_ISSUES.equals(branch)) { - // only index an issue once during updateIndex - String issueId = commit.getShortMessage().substring(2).trim(); - if (indexedIssues.contains(issueId)) { - continue; - } - indexedIssues.add(issueId); - - IssueModel issue = IssueUtils.getIssue(repository, issueId); - if (issue == null) { - // issue was deleted, remove from index - if (!deleteIssue(model.name, issueId)) { - logger.error(MessageFormat.format("Failed to delete issue {0} from Lucene index!", issueId)); - } - } else { - // issue was updated - index(model.name, issue); - result.issueCount++; - } - } else { - // index a commit - result.add(index(model.name, repository, branchName, commit)); - } + // index a commit + result.add(index(model.name, repository, branchName, commit)); } // update the config @@ -958,34 +864,6 @@ return result; } - /** - * Creates a Lucene document from an issue. - * - * @param issue - * @return a Lucene document - */ - private Document createDocument(IssueModel issue) { - Document doc = new Document(); - doc.add(new Field(FIELD_OBJECT_TYPE, SearchObjectType.issue.name(), Store.YES, - Field.Index.NOT_ANALYZED)); - doc.add(new Field(FIELD_ISSUE, issue.id, Store.YES, Index.ANALYZED)); - doc.add(new Field(FIELD_BRANCH, IssueUtils.GB_ISSUES, Store.YES, Index.ANALYZED)); - doc.add(new Field(FIELD_DATE, DateTools.dateToString(issue.created, Resolution.MINUTE), - Store.YES, Field.Index.NO)); - doc.add(new Field(FIELD_AUTHOR, issue.reporter, Store.YES, Index.ANALYZED)); - List<String> attachments = new ArrayList<String>(); - for (Attachment attachment : issue.getAttachments()) { - attachments.add(attachment.name.toLowerCase()); - } - doc.add(new Field(FIELD_ATTACHMENT, StringUtils.flattenStrings(attachments), Store.YES, - Index.ANALYZED)); - doc.add(new Field(FIELD_SUMMARY, issue.summary, Store.YES, Index.ANALYZED)); - doc.add(new Field(FIELD_CONTENT, issue.toString(), Store.YES, Index.ANALYZED)); - doc.add(new Field(FIELD_LABEL, StringUtils.flattenStrings(issue.getLabels()), Store.YES, - Index.ANALYZED)); - return doc; - } - /** * Creates a Lucene document for a commit * @@ -1042,7 +920,6 @@ result.type = SearchObjectType.fromName(doc.get(FIELD_OBJECT_TYPE)); result.branch = doc.get(FIELD_BRANCH); result.commitId = doc.get(FIELD_COMMIT); - result.issueId = doc.get(FIELD_ISSUE); result.path = doc.get(FIELD_PATH); if (doc.get(FIELD_TAG) != null) { result.tags = StringUtils.getStringsFromValue(doc.get(FIELD_TAG)); diff --git a/src/main/java/com/gitblit/models/IssueModel.java b/src/main/java/com/gitblit/models/IssueModel.java deleted file mode 100644 index c903891..0000000 --- a/src/main/java/com/gitblit/models/IssueModel.java +++ /dev/null @@ -1,532 +0,0 @@ -/* - * Copyright 2012 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.models; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Date; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -import com.gitblit.utils.ArrayUtils; -import com.gitblit.utils.StringUtils; -import com.gitblit.utils.TimeUtils; - -/** - * The Gitblit Issue model, its component classes, and enums. - * - * @author James Moger - * - */ -public class IssueModel implements Serializable, Comparable<IssueModel> { - - private static final long serialVersionUID = 1L; - - public String id; - - public Type type; - - public Status status; - - public Priority priority; - - public Date created; - - public String summary; - - public String description; - - public String reporter; - - public String owner; - - public String milestone; - - public List<Change> changes; - - public IssueModel() { - // the first applied change set the date appropriately - created = new Date(0); - - type = Type.Defect; - status = Status.New; - priority = Priority.Medium; - - changes = new ArrayList<Change>(); - } - - public String getStatus() { - String s = status.toString(); - if (!StringUtils.isEmpty(owner)) - s += " (" + owner + ")"; - return s; - } - - public boolean hasLabel(String label) { - return getLabels().contains(label); - } - - public List<String> getLabels() { - List<String> list = new ArrayList<String>(); - String labels = null; - for (Change change : changes) { - if (change.hasField(Field.Labels)) { - labels = change.getString(Field.Labels); - } - } - if (!StringUtils.isEmpty(labels)) { - list.addAll(StringUtils.getStringsFromValue(labels, " ")); - } - return list; - } - - public Attachment getAttachment(String name) { - Attachment attachment = null; - for (Change change : changes) { - if (change.hasAttachments()) { - Attachment a = change.getAttachment(name); - if (a != null) { - attachment = a; - } - } - } - return attachment; - } - - public List<Attachment> getAttachments() { - List<Attachment> list = new ArrayList<Attachment>(); - for (Change change : changes) { - if (change.hasAttachments()) { - list.addAll(change.attachments); - } - } - return list; - } - - public void applyChange(Change change) { - if (changes.size() == 0) { - // first change created the issue - created = change.created; - } - changes.add(change); - - if (change.hasFieldChanges()) { - for (FieldChange fieldChange : change.fieldChanges) { - switch (fieldChange.field) { - case Id: - id = fieldChange.value.toString(); - break; - case Type: - type = IssueModel.Type.fromObject(fieldChange.value); - break; - case Status: - status = IssueModel.Status.fromObject(fieldChange.value); - break; - case Priority: - priority = IssueModel.Priority.fromObject(fieldChange.value); - break; - case Summary: - summary = fieldChange.value.toString(); - break; - case Description: - description = fieldChange.value.toString(); - break; - case Reporter: - reporter = fieldChange.value.toString(); - break; - case Owner: - owner = fieldChange.value.toString(); - break; - case Milestone: - milestone = fieldChange.value.toString(); - break; - } - } - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("issue "); - sb.append(id.substring(0, 8)); - sb.append(" (" + summary + ")\n"); - for (Change change : changes) { - sb.append(change); - sb.append('\n'); - } - return sb.toString(); - } - - @Override - public int compareTo(IssueModel o) { - return o.created.compareTo(created); - } - - @Override - public boolean equals(Object o) { - if (o instanceof IssueModel) - return id.equals(((IssueModel) o).id); - return super.equals(o); - } - - @Override - public int hashCode() { - return id.hashCode(); - } - - public static class Change implements Serializable, Comparable<Change> { - - private static final long serialVersionUID = 1L; - - public final Date created; - - public final String author; - - public String id; - - public char code; - - public Comment comment; - - public Set<FieldChange> fieldChanges; - - public Set<Attachment> attachments; - - public Change(String author) { - this.created = new Date((System.currentTimeMillis() / 1000) * 1000); - this.author = author; - this.id = StringUtils.getSHA1(created.toString() + author); - } - - public boolean hasComment() { - return comment != null && !comment.deleted; - } - - public void comment(String text) { - comment = new Comment(text); - comment.id = StringUtils.getSHA1(created.toString() + author + text); - } - - public boolean hasAttachments() { - return !ArrayUtils.isEmpty(attachments); - } - - public void addAttachment(Attachment attachment) { - if (attachments == null) { - attachments = new LinkedHashSet<Attachment>(); - } - attachments.add(attachment); - } - - public Attachment getAttachment(String name) { - for (Attachment attachment : attachments) { - if (attachment.name.equalsIgnoreCase(name)) { - return attachment; - } - } - return null; - } - - public boolean hasField(Field field) { - return !StringUtils.isEmpty(getString(field)); - } - - public boolean hasFieldChanges() { - return !ArrayUtils.isEmpty(fieldChanges); - } - - public Object getField(Field field) { - if (fieldChanges != null) { - for (FieldChange fieldChange : fieldChanges) { - if (fieldChange.field == field) { - return fieldChange.value; - } - } - } - return null; - } - - public void setField(Field field, Object value) { - FieldChange fieldChange = new FieldChange(field, value); - if (fieldChanges == null) { - fieldChanges = new LinkedHashSet<FieldChange>(); - } - fieldChanges.add(fieldChange); - } - - public String getString(Field field) { - Object value = getField(field); - if (value == null) { - return null; - } - return value.toString(); - } - - @Override - public int compareTo(Change c) { - return created.compareTo(c.created); - } - - @Override - public int hashCode() { - return id.hashCode(); - } - - @Override - public boolean equals(Object o) { - if (o instanceof Change) { - return id.equals(((Change) o).id); - } - return false; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(new TimeUtils().timeAgo(created)); - switch (code) { - case '+': - sb.append(" created by "); - break; - default: - if (hasComment()) { - sb.append(" commented on by "); - } else { - sb.append(" changed by "); - } - } - sb.append(author).append(" - "); - if (hasComment()) { - if (comment.deleted) { - sb.append("(deleted) "); - } - sb.append(comment.text).append(" "); - } - if (hasFieldChanges()) { - switch (code) { - case '+': - break; - default: - for (FieldChange fieldChange : fieldChanges) { - sb.append("\n "); - sb.append(fieldChange); - } - break; - } - } - return sb.toString(); - } - } - - public static class Comment implements Serializable { - - private static final long serialVersionUID = 1L; - - public String text; - - public String id; - - public boolean deleted; - - Comment(String text) { - this.text = text; - } - - @Override - public String toString() { - return text; - } - } - - public static class FieldChange implements Serializable { - - private static final long serialVersionUID = 1L; - - public final Field field; - - public final Object value; - - FieldChange(Field field, Object value) { - this.field = field; - this.value = value; - } - - @Override - public int hashCode() { - return field.hashCode(); - } - - @Override - public boolean equals(Object o) { - if (o instanceof FieldChange) { - return field.equals(((FieldChange) o).field); - } - return false; - } - - @Override - public String toString() { - return field + ": " + value; - } - } - - public static class Attachment implements Serializable { - - private static final long serialVersionUID = 1L; - - public final String name; - public String id; - public long size; - public byte[] content; - public boolean deleted; - - public Attachment(String name) { - this.name = name; - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - @Override - public boolean equals(Object o) { - if (o instanceof Attachment) { - return name.equalsIgnoreCase(((Attachment) o).name); - } - return false; - } - - @Override - public String toString() { - return name; - } - } - - public static enum Field { - Id, Summary, Description, Reporter, Owner, Type, Status, Priority, Milestone, Component, Labels; - } - - public static enum Type { - Defect, Enhancement, Task, Review, Other; - - public static Type fromObject(Object o) { - if (o instanceof Type) { - // cast and return - return (Type) o; - } else if (o instanceof String) { - // find by name - for (Type type : values()) { - String str = o.toString(); - if (type.toString().equalsIgnoreCase(str)) { - return type; - } - } - } else if (o instanceof Number) { - // by ordinal - int id = ((Number) o).intValue(); - if (id >= 0 && id < values().length) { - return values()[id]; - } - } - return null; - } - } - - public static enum Priority { - Low, Medium, High, Critical; - - public static Priority fromObject(Object o) { - if (o instanceof Priority) { - // cast and return - return (Priority) o; - } else if (o instanceof String) { - // find by name - for (Priority priority : values()) { - String str = o.toString(); - if (priority.toString().equalsIgnoreCase(str)) { - return priority; - } - } - } else if (o instanceof Number) { - // by ordinal - int id = ((Number) o).intValue(); - if (id >= 0 && id < values().length) { - return values()[id]; - } - } - return null; - } - } - - public static enum Status { - New, Accepted, Started, Review, Queued, Testing, Done, Fixed, WontFix, Duplicate, Invalid; - - public static Status fromObject(Object o) { - if (o instanceof Status) { - // cast and return - return (Status) o; - } else if (o instanceof String) { - // find by name - for (Status status : values()) { - String str = o.toString(); - if (status.toString().equalsIgnoreCase(str)) { - return status; - } - } - } else if (o instanceof Number) { - // by ordinal - int id = ((Number) o).intValue(); - if (id >= 0 && id < values().length) { - return values()[id]; - } - } - return null; - } - - public boolean atLeast(Status status) { - return ordinal() >= status.ordinal(); - } - - public boolean exceeds(Status status) { - return ordinal() > status.ordinal(); - } - - public boolean isClosed() { - return ordinal() >= Done.ordinal(); - } - - public Status next() { - switch (this) { - case New: - return Started; - case Accepted: - return Started; - case Started: - return Testing; - case Review: - return Testing; - case Queued: - return Testing; - case Testing: - return Done; - } - return Accepted; - } - } -} diff --git a/src/main/java/com/gitblit/utils/IssueUtils.java b/src/main/java/com/gitblit/utils/IssueUtils.java deleted file mode 100644 index dd09235..0000000 --- a/src/main/java/com/gitblit/utils/IssueUtils.java +++ /dev/null @@ -1,829 +0,0 @@ -/* - * Copyright 2012 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.utils; - -import java.io.IOException; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -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.internal.JGitText; -import org.eclipse.jgit.lib.CommitBuilder; -import org.eclipse.jgit.lib.Constants; -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.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.treewalk.CanonicalTreeParser; -import org.eclipse.jgit.treewalk.TreeWalk; -import org.eclipse.jgit.treewalk.filter.AndTreeFilter; -import org.eclipse.jgit.treewalk.filter.PathFilterGroup; -import org.eclipse.jgit.treewalk.filter.TreeFilter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.gitblit.models.IssueModel; -import com.gitblit.models.IssueModel.Attachment; -import com.gitblit.models.IssueModel.Change; -import com.gitblit.models.IssueModel.Field; -import com.gitblit.models.IssueModel.Status; -import com.gitblit.models.RefModel; -import com.gitblit.utils.JsonUtils.ExcludeField; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - -/** - * Utility class for reading Gitblit issues. - * - * @author James Moger - * - */ -public class IssueUtils { - - public static interface IssueFilter { - public abstract boolean accept(IssueModel issue); - } - - public static final String GB_ISSUES = "refs/gitblit/issues"; - - static final Logger LOGGER = LoggerFactory.getLogger(IssueUtils.class); - - /** - * Log an error message and exception. - * - * @param t - * @param repository - * if repository is not null it MUST be the {0} parameter in the - * pattern. - * @param pattern - * @param objects - */ - private static void error(Throwable t, Repository repository, String pattern, Object... objects) { - List<Object> parameters = new ArrayList<Object>(); - if (objects != null && objects.length > 0) { - for (Object o : objects) { - parameters.add(o); - } - } - if (repository != null) { - parameters.add(0, repository.getDirectory().getAbsolutePath()); - } - LOGGER.error(MessageFormat.format(pattern, parameters.toArray()), t); - } - - /** - * Returns a RefModel for the gb-issues branch in the repository. If the - * branch can not be found, null is returned. - * - * @param repository - * @return a refmodel for the gb-issues branch or null - */ - public static RefModel getIssuesBranch(Repository repository) { - List<RefModel> refs = JGitUtils.getRefs(repository, com.gitblit.Constants.R_GITBLIT); - for (RefModel ref : refs) { - if (ref.reference.getName().equals(GB_ISSUES)) { - return ref; - } - } - return null; - } - - /** - * Returns all the issues in the repository. Querying issues from the - * repository requires deserializing all changes for all issues. This is an - * expensive process and not recommended. Issues should be indexed by Lucene - * and queries should be executed against that index. - * - * @param repository - * @param filter - * optional issue filter to only return matching results - * @return a list of issues - */ - public static List<IssueModel> getIssues(Repository repository, IssueFilter filter) { - List<IssueModel> list = new ArrayList<IssueModel>(); - RefModel issuesBranch = getIssuesBranch(repository); - if (issuesBranch == null) { - return list; - } - - // Collect the set of all issue paths - Set<String> issuePaths = new HashSet<String>(); - final TreeWalk tw = new TreeWalk(repository); - try { - RevCommit head = JGitUtils.getCommit(repository, GB_ISSUES); - tw.addTree(head.getTree()); - tw.setRecursive(false); - while (tw.next()) { - if (tw.getDepth() < 2 && tw.isSubtree()) { - tw.enterSubtree(); - if (tw.getDepth() == 2) { - issuePaths.add(tw.getPathString()); - } - } - } - } catch (IOException e) { - error(e, repository, "{0} failed to query issues"); - } finally { - tw.release(); - } - - // Build each issue and optionally filter out unwanted issues - - for (String issuePath : issuePaths) { - RevWalk rw = new RevWalk(repository); - try { - RevCommit start = rw.parseCommit(repository.resolve(GB_ISSUES)); - rw.markStart(start); - } catch (Exception e) { - error(e, repository, "Failed to find {1} in {0}", GB_ISSUES); - } - TreeFilter treeFilter = AndTreeFilter.create( - PathFilterGroup.createFromStrings(issuePath), TreeFilter.ANY_DIFF); - rw.setTreeFilter(treeFilter); - Iterator<RevCommit> revlog = rw.iterator(); - - List<RevCommit> commits = new ArrayList<RevCommit>(); - while (revlog.hasNext()) { - commits.add(revlog.next()); - } - - // release the revwalk - rw.release(); - - if (commits.size() == 0) { - LOGGER.warn("Failed to find changes for issue " + issuePath); - continue; - } - - // sort by commit order, first commit first - Collections.reverse(commits); - - StringBuilder sb = new StringBuilder("["); - boolean first = true; - for (RevCommit commit : commits) { - if (!first) { - sb.append(','); - } - String message = commit.getFullMessage(); - // commit message is formatted: C ISSUEID\n\nJSON - // C is an single char commit code - // ISSUEID is an SHA-1 hash - String json = message.substring(43); - sb.append(json); - first = false; - } - sb.append(']'); - - // Deserialize the JSON array as a Collection<Change>, this seems - // slightly faster than deserializing each change by itself. - Collection<Change> changes = JsonUtils.fromJsonString(sb.toString(), - new TypeToken<Collection<Change>>() { - }.getType()); - - // create an issue object form the changes - IssueModel issue = buildIssue(changes, true); - - // add the issue, conditionally, to the list - if (filter == null) { - list.add(issue); - } else { - if (filter.accept(issue)) { - list.add(issue); - } - } - } - - // sort the issues by creation - Collections.sort(list); - return list; - } - - /** - * Retrieves the specified issue from the repository with all changes - * applied to build the effective issue. - * - * @param repository - * @param issueId - * @return an issue, if it exists, otherwise null - */ - public static IssueModel getIssue(Repository repository, String issueId) { - return getIssue(repository, issueId, true); - } - - /** - * Retrieves the specified issue from the repository. - * - * @param repository - * @param issueId - * @param effective - * if true, the effective issue is built by processing comment - * changes, deletions, etc. if false, the raw issue is built - * without consideration for comment changes, deletions, etc. - * @return an issue, if it exists, otherwise null - */ - public static IssueModel getIssue(Repository repository, String issueId, boolean effective) { - RefModel issuesBranch = getIssuesBranch(repository); - if (issuesBranch == null) { - return null; - } - - if (StringUtils.isEmpty(issueId)) { - return null; - } - - String issuePath = getIssuePath(issueId); - - // Collect all changes as JSON array from commit messages - List<RevCommit> commits = JGitUtils.getRevLog(repository, GB_ISSUES, issuePath, 0, -1); - - // sort by commit order, first commit first - Collections.reverse(commits); - - StringBuilder sb = new StringBuilder("["); - boolean first = true; - for (RevCommit commit : commits) { - if (!first) { - sb.append(','); - } - String message = commit.getFullMessage(); - // commit message is formatted: C ISSUEID\n\nJSON - // C is an single char commit code - // ISSUEID is an SHA-1 hash - String json = message.substring(43); - sb.append(json); - first = false; - } - sb.append(']'); - - // Deserialize the JSON array as a Collection<Change>, this seems - // slightly faster than deserializing each change by itself. - Collection<Change> changes = JsonUtils.fromJsonString(sb.toString(), - new TypeToken<Collection<Change>>() { - }.getType()); - - // create an issue object and apply the changes to it - IssueModel issue = buildIssue(changes, effective); - return issue; - } - - /** - * Builds an issue from a set of changes. - * - * @param changes - * @param effective - * if true, the effective issue is built which accounts for - * comment changes, comment deletions, etc. if false, the raw - * issue is built. - * @return an issue - */ - private static IssueModel buildIssue(Collection<Change> changes, boolean effective) { - IssueModel issue; - if (effective) { - List<Change> effectiveChanges = new ArrayList<Change>(); - Map<String, Change> comments = new HashMap<String, Change>(); - for (Change change : changes) { - if (change.comment != null) { - if (comments.containsKey(change.comment.id)) { - Change original = comments.get(change.comment.id); - Change clone = DeepCopier.copy(original); - clone.comment.text = change.comment.text; - clone.comment.deleted = change.comment.deleted; - int idx = effectiveChanges.indexOf(original); - effectiveChanges.remove(original); - effectiveChanges.add(idx, clone); - comments.put(clone.comment.id, clone); - } else { - effectiveChanges.add(change); - comments.put(change.comment.id, change); - } - } else { - effectiveChanges.add(change); - } - } - - // effective issue - issue = new IssueModel(); - for (Change change : effectiveChanges) { - issue.applyChange(change); - } - } else { - // raw issue - issue = new IssueModel(); - for (Change change : changes) { - issue.applyChange(change); - } - } - return issue; - } - - /** - * Retrieves the specified attachment from an issue. - * - * @param repository - * @param issueId - * @param filename - * @return an attachment, if found, null otherwise - */ - public static Attachment getIssueAttachment(Repository repository, String issueId, - String filename) { - RefModel issuesBranch = getIssuesBranch(repository); - if (issuesBranch == null) { - return null; - } - - if (StringUtils.isEmpty(issueId)) { - return null; - } - - // deserialize the issue model so that we have the attachment metadata - IssueModel issue = getIssue(repository, issueId, true); - Attachment attachment = issue.getAttachment(filename); - - // attachment not found - if (attachment == null) { - return null; - } - - // retrieve the attachment content - String issuePath = getIssuePath(issueId); - RevTree tree = JGitUtils.getCommit(repository, GB_ISSUES).getTree(); - byte[] content = JGitUtils - .getByteContent(repository, tree, issuePath + "/" + attachment.id, false); - attachment.content = content; - attachment.size = content.length; - return attachment; - } - - /** - * Creates an issue in the gb-issues branch of the repository. The branch is - * automatically created if it does not already exist. Your change must - * include an author, summary, and description, at a minimum. If your change - * does not have those minimum requirements a RuntimeException will be - * thrown. - * - * @param repository - * @param change - * @return true if successful - */ - public static IssueModel createIssue(Repository repository, Change change) { - RefModel issuesBranch = getIssuesBranch(repository); - if (issuesBranch == null) { - JGitUtils.createOrphanBranch(repository, GB_ISSUES, null); - } - - if (StringUtils.isEmpty(change.author)) { - throw new RuntimeException("Must specify a change author!"); - } - if (!change.hasField(Field.Summary)) { - throw new RuntimeException("Must specify a summary!"); - } - if (!change.hasField(Field.Description)) { - throw new RuntimeException("Must specify a description!"); - } - - change.setField(Field.Reporter, change.author); - - String issueId = StringUtils.getSHA1(change.created.toString() + change.author - + change.getString(Field.Summary) + change.getField(Field.Description)); - change.setField(Field.Id, issueId); - change.code = '+'; - - boolean success = commit(repository, issueId, change); - if (success) { - return getIssue(repository, issueId, false); - } - return null; - } - - /** - * Updates an issue in the gb-issues branch of the repository. - * - * @param repository - * @param issueId - * @param change - * @return true if successful - */ - public static boolean updateIssue(Repository repository, String issueId, Change change) { - boolean success = false; - RefModel issuesBranch = getIssuesBranch(repository); - - if (issuesBranch == null) { - throw new RuntimeException("gb-issues branch does not exist!"); - } - - if (change == null) { - throw new RuntimeException("change can not be null!"); - } - - if (StringUtils.isEmpty(change.author)) { - throw new RuntimeException("must specify a change author!"); - } - - // determine update code - // default update code is '=' for a general change - change.code = '='; - if (change.hasField(Field.Status)) { - Status status = Status.fromObject(change.getField(Field.Status)); - if (status.isClosed()) { - // someone closed the issue - change.code = 'x'; - } - } - success = commit(repository, issueId, change); - return success; - } - - /** - * Deletes an issue from the repository. - * - * @param repository - * @param issueId - * @return true if successful - */ - public static boolean deleteIssue(Repository repository, String issueId, String author) { - boolean success = false; - RefModel issuesBranch = getIssuesBranch(repository); - - if (issuesBranch == null) { - throw new RuntimeException(GB_ISSUES + " does not exist!"); - } - - if (StringUtils.isEmpty(issueId)) { - throw new RuntimeException("must specify an issue id!"); - } - - String issuePath = getIssuePath(issueId); - - String message = "- " + issueId; - try { - ObjectId headId = repository.resolve(GB_ISSUES + "^{commit}"); - ObjectInserter odi = repository.newObjectInserter(); - try { - // Create the in-memory index of the new/updated issue - DirCache index = DirCache.newInCore(); - DirCacheBuilder dcBuilder = index.builder(); - // Traverse HEAD to add all other paths - TreeWalk treeWalk = new TreeWalk(repository); - int hIdx = -1; - if (headId != null) - hIdx = treeWalk.addTree(new RevWalk(repository).parseTree(headId)); - 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(issuePath)) { - // add entries from HEAD for all other paths - if (hTree != null) { - // create a new DirCacheEntry with data retrieved - // from HEAD - final DirCacheEntry dcEntry = new DirCacheEntry(path); - dcEntry.setObjectId(hTree.getEntryObjectId()); - dcEntry.setFileMode(hTree.getEntryFileMode()); - - // add to temporary in-core index - dcBuilder.add(dcEntry); - } - } - } - - // release the treewalk - treeWalk.release(); - - // finish temporary in-core index used for this commit - dcBuilder.finish(); - - 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.CHARACTER_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(repository); - try { - RevCommit revCommit = revWalk.parseCommit(commitId); - RefUpdate ru = repository.updateRef(GB_ISSUES); - 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, GB_ISSUES, commitId.toString(), - rc)); - } - } finally { - revWalk.release(); - } - } finally { - odi.release(); - } - } catch (Throwable t) { - error(t, repository, "Failed to delete issue {1} to {0}", issueId); - } - return success; - } - - /** - * Changes the text of an issue comment. - * - * @param repository - * @param issue - * @param change - * the change with the comment to change - * @param author - * the author of the revision - * @param comment - * the revised comment - * @return true, if the change was successful - */ - public static boolean changeComment(Repository repository, IssueModel issue, Change change, - String author, String comment) { - Change revision = new Change(author); - revision.comment(comment); - revision.comment.id = change.comment.id; - return updateIssue(repository, issue.id, revision); - } - - /** - * Deletes a comment from an issue. - * - * @param repository - * @param issue - * @param change - * the change with the comment to delete - * @param author - * @return true, if the deletion was successful - */ - public static boolean deleteComment(Repository repository, IssueModel issue, Change change, - String author) { - Change deletion = new Change(author); - deletion.comment(change.comment.text); - deletion.comment.id = change.comment.id; - deletion.comment.deleted = true; - return updateIssue(repository, issue.id, deletion); - } - - /** - * Commit a change to the repository. Each issue is composed on changes. - * Issues are built from applying the changes in the order they were - * committed to the repository. The changes are actually specified in the - * commit messages and not in the RevTrees which allows for clean, - * distributed merging. - * - * @param repository - * @param issueId - * @param change - * @return true, if the change was committed - */ - private static boolean commit(Repository repository, String issueId, Change change) { - boolean success = false; - - try { - // assign ids to new attachments - // attachments are stored by an SHA1 id - if (change.hasAttachments()) { - for (Attachment attachment : change.attachments) { - if (!ArrayUtils.isEmpty(attachment.content)) { - byte[] prefix = (change.created.toString() + change.author).getBytes(); - byte[] bytes = new byte[prefix.length + attachment.content.length]; - System.arraycopy(prefix, 0, bytes, 0, prefix.length); - System.arraycopy(attachment.content, 0, bytes, prefix.length, - attachment.content.length); - attachment.id = "attachment-" + StringUtils.getSHA1(bytes); - } - } - } - - // serialize the change as json - // exclude any attachment from json serialization - Gson gson = JsonUtils.gson(new ExcludeField( - "com.gitblit.models.IssueModel$Attachment.content")); - String json = gson.toJson(change); - - // include the json change in the commit message - String issuePath = getIssuePath(issueId); - String message = change.code + " " + issueId + "\n\n" + json; - - // Create a commit file. This is required for a proper commit and - // ensures we can retrieve the commit log of the issue path. - // - // This file is NOT serialized as part of the Change object. - switch (change.code) { - case '+': { - // New Issue. - Attachment placeholder = new Attachment("issue"); - placeholder.id = placeholder.name; - placeholder.content = "DO NOT REMOVE".getBytes(Constants.CHARACTER_ENCODING); - change.addAttachment(placeholder); - break; - } - default: { - // Update Issue. - String changeId = StringUtils.getSHA1(json); - Attachment placeholder = new Attachment("change-" + changeId); - placeholder.id = placeholder.name; - placeholder.content = "REMOVABLE".getBytes(Constants.CHARACTER_ENCODING); - change.addAttachment(placeholder); - break; - } - } - - ObjectId headId = repository.resolve(GB_ISSUES + "^{commit}"); - ObjectInserter odi = repository.newObjectInserter(); - try { - // Create the in-memory index of the new/updated issue - DirCache index = createIndex(repository, headId, issuePath, change); - ObjectId indexTreeId = index.writeTree(odi); - - // Create a commit object - PersonIdent ident = new PersonIdent(change.author, "gitblit@localhost"); - CommitBuilder commit = new CommitBuilder(); - commit.setAuthor(ident); - commit.setCommitter(ident); - commit.setEncoding(Constants.CHARACTER_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(repository); - try { - RevCommit revCommit = revWalk.parseCommit(commitId); - RefUpdate ru = repository.updateRef(GB_ISSUES); - 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, GB_ISSUES, commitId.toString(), - rc)); - } - } finally { - revWalk.release(); - } - } finally { - odi.release(); - } - } catch (Throwable t) { - error(t, repository, "Failed to commit issue {1} to {0}", issueId); - } - return success; - } - - /** - * Returns the issue 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 issueId - * @return the root path of the issue content on the gb-issues branch - */ - static String getIssuePath(String issueId) { - return issueId.substring(0, 2) + "/" + issueId.substring(2); - } - - /** - * Creates an in-memory index of the issue change. - * - * @param repo - * @param headId - * @param change - * @return an in-memory index - * @throws IOException - */ - private static DirCache createIndex(Repository repo, ObjectId headId, String issuePath, - Change change) throws IOException { - - DirCache inCoreIndex = DirCache.newInCore(); - DirCacheBuilder dcBuilder = inCoreIndex.builder(); - ObjectInserter inserter = repo.newObjectInserter(); - - Set<String> ignorePaths = new TreeSet<String>(); - try { - // Add any attachments to the temporary index - if (change.hasAttachments()) { - for (Attachment attachment : change.attachments) { - // build a path name for the attachment and mark as ignored - String path = issuePath + "/" + attachment.id; - ignorePaths.add(path); - - // create an index entry for this attachment - final DirCacheEntry dcEntry = new DirCacheEntry(path); - dcEntry.setLength(attachment.content.length); - dcEntry.setLastModified(change.created.getTime()); - dcEntry.setFileMode(FileMode.REGULAR_FILE); - - // insert object - dcEntry.setObjectId(inserter.insert(Constants.OBJ_BLOB, attachment.content)); - - // add to temporary in-core index - dcBuilder.add(dcEntry); - } - } - - // Traverse HEAD to add all other paths - TreeWalk treeWalk = new TreeWalk(repo); - int hIdx = -1; - if (headId != null) - hIdx = treeWalk.addTree(new RevWalk(repo).parseTree(headId)); - treeWalk.setRecursive(true); - - while (treeWalk.next()) { - String path = treeWalk.getPathString(); - CanonicalTreeParser hTree = null; - if (hIdx != -1) - hTree = treeWalk.getTree(hIdx, CanonicalTreeParser.class); - if (!ignorePaths.contains(path)) { - // add entries from HEAD for all other paths - if (hTree != null) { - // create a new DirCacheEntry with data retrieved from - // HEAD - final DirCacheEntry dcEntry = new DirCacheEntry(path); - dcEntry.setObjectId(hTree.getEntryObjectId()); - dcEntry.setFileMode(hTree.getEntryFileMode()); - - // add to temporary in-core index - dcBuilder.add(dcEntry); - } - } - } - - // release the treewalk - treeWalk.release(); - - // finish temporary in-core index used for this commit - dcBuilder.finish(); - } finally { - inserter.release(); - } - return inCoreIndex; - } -} \ No newline at end of file diff --git a/src/test/java/com/gitblit/tests/GitBlitSuite.java b/src/test/java/com/gitblit/tests/GitBlitSuite.java index 51f05a9..2d653af 100644 --- a/src/test/java/com/gitblit/tests/GitBlitSuite.java +++ b/src/test/java/com/gitblit/tests/GitBlitSuite.java @@ -59,7 +59,7 @@ MarkdownUtilsTest.class, JGitUtilsTest.class, SyndicationUtilsTest.class, DiffUtilsTest.class, MetricUtilsTest.class, X509UtilsTest.class, GitBlitTest.class, FederationTests.class, RpcTests.class, GitServletTest.class, GitDaemonTest.class, - GroovyScriptTest.class, LuceneExecutorTest.class, IssuesTest.class, RepositoryModelTest.class, + GroovyScriptTest.class, LuceneExecutorTest.class, RepositoryModelTest.class, FanoutServiceTest.class, Issue0259Test.class, Issue0271Test.class, HtpasswdUserServiceTest.class, ModelUtilsTest.class, JnaUtilsTest.class }) public class GitBlitSuite { diff --git a/src/test/java/com/gitblit/tests/IssuesTest.java b/src/test/java/com/gitblit/tests/IssuesTest.java deleted file mode 100644 index 54cac33..0000000 --- a/src/test/java/com/gitblit/tests/IssuesTest.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2012 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.tests; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.List; - -import org.bouncycastle.util.Arrays; -import org.eclipse.jgit.lib.Repository; -import org.junit.Test; - -import com.gitblit.LuceneExecutor; -import com.gitblit.models.IssueModel; -import com.gitblit.models.IssueModel.Attachment; -import com.gitblit.models.IssueModel.Change; -import com.gitblit.models.IssueModel.Field; -import com.gitblit.models.IssueModel.Priority; -import com.gitblit.models.IssueModel.Status; -import com.gitblit.models.SearchResult; -import com.gitblit.utils.FileUtils; -import com.gitblit.utils.IssueUtils; -import com.gitblit.utils.IssueUtils.IssueFilter; - -/** - * Tests the mechanics of distributed issue management on the gb-issues branch. - * - * @author James Moger - * - */ -public class IssuesTest { - - @Test - public void testLifecycle() throws Exception { - Repository repository = GitBlitSuite.getIssuesTestRepository(); - String name = FileUtils.getRelativePath(GitBlitSuite.REPOSITORIES, repository.getDirectory()); - - // create and insert an issue - Change c1 = newChange("testCreation() " + Long.toHexString(System.currentTimeMillis())); - IssueModel issue = IssueUtils.createIssue(repository, c1); - assertNotNull(issue.id); - - // retrieve issue and compare - IssueModel constructed = IssueUtils.getIssue(repository, issue.id); - compare(issue, constructed); - - assertEquals(1, constructed.changes.size()); - - // C1: create the issue - c1 = newChange("testUpdates() " + Long.toHexString(System.currentTimeMillis())); - issue = IssueUtils.createIssue(repository, c1); - assertNotNull(issue.id); - - constructed = IssueUtils.getIssue(repository, issue.id); - compare(issue, constructed); - assertEquals(1, constructed.changes.size()); - - // C2: set owner - Change c2 = new Change("C2"); - c2.comment("I'll fix this"); - c2.setField(Field.Owner, c2.author); - assertTrue(IssueUtils.updateIssue(repository, issue.id, c2)); - constructed = IssueUtils.getIssue(repository, issue.id); - assertEquals(2, constructed.changes.size()); - assertEquals(c2.author, constructed.owner); - - // C3: add a note - Change c3 = new Change("C3"); - c3.comment("yeah, this is working"); - assertTrue(IssueUtils.updateIssue(repository, issue.id, c3)); - constructed = IssueUtils.getIssue(repository, issue.id); - assertEquals(3, constructed.changes.size()); - - // C4: add attachment - Change c4 = new Change("C4"); - Attachment a = newAttachment(); - c4.addAttachment(a); - assertTrue(IssueUtils.updateIssue(repository, issue.id, c4)); - - Attachment a1 = IssueUtils.getIssueAttachment(repository, issue.id, a.name); - assertEquals(a.content.length, a1.content.length); - assertTrue(Arrays.areEqual(a.content, a1.content)); - - // C5: close the issue - Change c5 = new Change("C5"); - c5.comment("closing issue"); - c5.setField(Field.Status, Status.Fixed); - assertTrue(IssueUtils.updateIssue(repository, issue.id, c5)); - - // retrieve issue again - constructed = IssueUtils.getIssue(repository, issue.id); - - assertEquals(5, constructed.changes.size()); - assertTrue(constructed.status.isClosed()); - - List<IssueModel> allIssues = IssueUtils.getIssues(repository, null); - List<IssueModel> openIssues = IssueUtils.getIssues(repository, new IssueFilter() { - @Override - public boolean accept(IssueModel issue) { - return !issue.status.isClosed(); - } - }); - List<IssueModel> closedIssues = IssueUtils.getIssues(repository, new IssueFilter() { - @Override - public boolean accept(IssueModel issue) { - return issue.status.isClosed(); - } - }); - - assertTrue(allIssues.size() > 0); - assertEquals(1, openIssues.size()); - assertEquals(1, closedIssues.size()); - - // build a new Lucene index - LuceneExecutor lucene = new LuceneExecutor(null, GitBlitSuite.REPOSITORIES); - lucene.deleteIndex(name); - for (IssueModel anIssue : allIssues) { - lucene.index(name, anIssue); - } - List<SearchResult> hits = lucene.search("working", 1, 10, name); - assertTrue(hits.size() == 1); - - // reindex an issue - issue = allIssues.get(0); - Change change = new Change("reindex"); - change.comment("this is a test of reindexing an issue"); - IssueUtils.updateIssue(repository, issue.id, change); - issue = IssueUtils.getIssue(repository, issue.id); - lucene.index(name, issue); - - hits = lucene.search("working", 1, 10, name); - assertTrue(hits.size() == 1); - - - // delete all issues - for (IssueModel anIssue : allIssues) { - assertTrue(IssueUtils.deleteIssue(repository, anIssue.id, "D")); - } - - lucene.close(); - repository.close(); - } - - @Test - public void testChangeComment() throws Exception { - Repository repository = GitBlitSuite.getIssuesTestRepository(); - // C1: create the issue - Change c1 = newChange("testChangeComment() " + Long.toHexString(System.currentTimeMillis())); - IssueModel issue = IssueUtils.createIssue(repository, c1); - assertNotNull(issue.id); - assertTrue(issue.changes.get(0).hasComment()); - - assertTrue(IssueUtils.changeComment(repository, issue, c1, "E1", "I changed the comment")); - issue = IssueUtils.getIssue(repository, issue.id); - assertTrue(issue.changes.get(0).hasComment()); - assertEquals("I changed the comment", issue.changes.get(0).comment.text); - - assertTrue(IssueUtils.deleteIssue(repository, issue.id, "D")); - - repository.close(); - } - - @Test - public void testDeleteComment() throws Exception { - Repository repository = GitBlitSuite.getIssuesTestRepository(); - // C1: create the issue - Change c1 = newChange("testDeleteComment() " + Long.toHexString(System.currentTimeMillis())); - IssueModel issue = IssueUtils.createIssue(repository, c1); - assertNotNull(issue.id); - assertTrue(issue.changes.get(0).hasComment()); - - assertTrue(IssueUtils.deleteComment(repository, issue, c1, "D1")); - issue = IssueUtils.getIssue(repository, issue.id); - assertEquals(1, issue.changes.size()); - assertFalse(issue.changes.get(0).hasComment()); - - issue = IssueUtils.getIssue(repository, issue.id, false); - assertEquals(2, issue.changes.size()); - assertTrue(issue.changes.get(0).hasComment()); - assertFalse(issue.changes.get(1).hasComment()); - - assertTrue(IssueUtils.deleteIssue(repository, issue.id, "D")); - - repository.close(); - } - - private Change newChange(String summary) { - Change change = new Change("C1"); - change.setField(Field.Summary, summary); - change.setField(Field.Description, "this is my description"); - change.setField(Field.Priority, Priority.High); - change.setField(Field.Labels, "helpdesk"); - change.comment("my comment"); - return change; - } - - private Attachment newAttachment() { - Attachment attachment = new Attachment(Long.toHexString(System.currentTimeMillis()) - + ".txt"); - attachment.content = new byte[] { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a }; - return attachment; - } - - private void compare(IssueModel issue, IssueModel constructed) { - assertEquals(issue.id, constructed.id); - assertEquals(issue.reporter, constructed.reporter); - assertEquals(issue.owner, constructed.owner); - assertEquals(issue.summary, constructed.summary); - assertEquals(issue.description, constructed.description); - assertEquals(issue.created, constructed.created); - - assertTrue(issue.hasLabel("helpdesk")); - } -} \ No newline at end of file -- Gitblit v1.9.1