From cd7e4f9186f2ace4416780a7dd6341e01e23a45f Mon Sep 17 00:00:00 2001 From: Paul Martin <paul@paulsputer.com> Date: Wed, 06 Apr 2016 14:46:58 -0400 Subject: [PATCH] Fix for #962 - Delete patchset ability --- src/main/java/com/gitblit/models/TicketModel.java | 210 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 199 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/gitblit/models/TicketModel.java b/src/main/java/com/gitblit/models/TicketModel.java index 1ff55dd..7495448 100644 --- a/src/main/java/com/gitblit/models/TicketModel.java +++ b/src/main/java/com/gitblit/models/TicketModel.java @@ -35,6 +35,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Set; import java.util.TreeSet; import java.util.regex.Matcher; @@ -90,6 +91,10 @@ public Integer deletions; + public Priority priority; + + public Severity severity; + /** * Builds an effective ticket from the collection of changes. A change may * Add or Subtract information from a ticket, but the collection of changes @@ -102,6 +107,30 @@ TicketModel ticket; List<Change> effectiveChanges = new ArrayList<Change>(); Map<String, Change> comments = new HashMap<String, Change>(); + Map<Integer, Integer> latestRevisions = new HashMap<Integer, Integer>(); + + int latestPatchsetNumber = -1; + + List<Integer> deletedPatchsets = new ArrayList<Integer>(); + + for (Change change : changes) { + if (change.patchset != null) { + if (change.patchset.isDeleted()) { + deletedPatchsets.add(change.patchset.number); + } else { + Integer latestRev = latestRevisions.get(change.patchset.number); + + if (latestRev == null || change.patchset.rev > latestRev) { + latestRevisions.put(change.patchset.number, change.patchset.rev); + } + + if (change.patchset.number > latestPatchsetNumber) { + latestPatchsetNumber = change.patchset.number; + } + } + } + } + for (Change change : changes) { if (change.comment != null) { if (comments.containsKey(change.comment.id)) { @@ -116,6 +145,19 @@ } else { effectiveChanges.add(change); comments.put(change.comment.id, change); + } + } else if (change.patchset != null) { + //All revisions of a deleted patchset are not displayed + if (!deletedPatchsets.contains(change.patchset.number)) { + + Integer latestRev = latestRevisions.get(change.patchset.number); + + if ( (change.patchset.number < latestPatchsetNumber) + && (change.patchset.rev == latestRev)) { + change.patchset.canDelete = true; + } + + effectiveChanges.add(change); } } else { effectiveChanges.add(change); @@ -140,6 +182,8 @@ changes = new ArrayList<Change>(); status = Status.New; type = Type.defaultType; + priority = Priority.defaultPriority; + severity = Severity.defaultSeverity; } public boolean isOpen() { @@ -516,6 +560,12 @@ case mergeSha: mergeSha = toString(value); break; + case priority: + priority = TicketModel.Priority.fromObject(value, priority); + break; + case severity: + severity = TicketModel.Severity.fromObject(value, severity); + break; default: // unknown break; @@ -636,7 +686,7 @@ } public boolean hasComment() { - return comment != null && !comment.isDeleted(); + return comment != null && !comment.isDeleted() && comment.text != null; } public Comment comment(String text) { @@ -785,7 +835,21 @@ for (String item : items) { list.add(prefix + item); } - setField(field, join(list, ",")); + if (hasField(field)) { + String flat = getString(field); + if (isEmpty(flat)) { + // field is empty, use this list + setField(field, join(list, ",")); + } else { + // merge this list into the existing field list + Set<String> set = new TreeSet<String>(Arrays.asList(flat.split(","))); + set.addAll(list); + setField(field, join(set, ",")); + } + } else { + // does not have a list for this field + setField(field, join(list, ",")); + } } public String getId() { @@ -1006,8 +1070,14 @@ public int added; public PatchsetType type; + public transient boolean canDelete = false; + public boolean isFF() { return PatchsetType.FastForward == type; + } + + public boolean isDeleted() { + return PatchsetType.Delete == type; } @Override @@ -1138,7 +1208,8 @@ } public static enum Score { - approved(2), looks_good(1), not_reviewed(0), needs_improvement(-1), vetoed(-2); + approved(2), looks_good(1), not_reviewed(0), needs_improvement(-1), vetoed( + -2); final int value; @@ -1154,20 +1225,29 @@ public String toString() { return name().toLowerCase().replace('_', ' '); } + + public static Score fromScore(int score) { + for (Score s : values()) { + if (s.getValue() == score) { + return s; + } + } + throw new NoSuchElementException(String.valueOf(score)); + } } public static enum Field { title, body, responsible, type, status, milestone, mergeSha, mergeTo, - topic, labels, watchers, reviewers, voters, mentions; + topic, labels, watchers, reviewers, voters, mentions, priority, severity; } public static enum Type { - Enhancement, Task, Bug, Proposal, Question; + Enhancement, Task, Bug, Proposal, Question, Maintenance; public static Type defaultType = Task; public static Type [] choices() { - return new Type [] { Enhancement, Task, Bug, Question }; + return new Type [] { Enhancement, Task, Bug, Question, Maintenance }; } @Override @@ -1201,13 +1281,15 @@ } public static enum Status { - New, Open, Resolved, Fixed, Merged, Wontfix, Declined, Duplicate, Invalid, On_Hold; + New, Open, Closed, Resolved, Fixed, Merged, Wontfix, Declined, Duplicate, Invalid, Abandoned, On_Hold, No_Change_Required; - public static Status [] requestWorkflow = { Open, Resolved, Declined, Duplicate, Invalid, On_Hold }; + public static Status [] requestWorkflow = { Open, Resolved, Declined, Duplicate, Invalid, Abandoned, On_Hold, No_Change_Required }; - public static Status [] bugWorkflow = { Open, Fixed, Wontfix, Duplicate, Invalid, On_Hold }; + public static Status [] bugWorkflow = { Open, Fixed, Wontfix, Duplicate, Invalid, Abandoned, On_Hold, No_Change_Required }; - public static Status [] proposalWorkflow = { Open, Declined, On_Hold}; + public static Status [] proposalWorkflow = { Open, Resolved, Declined, Abandoned, On_Hold, No_Change_Required }; + + public static Status [] milestoneWorkflow = { Open, Closed, Abandoned, On_Hold }; @Override public String toString() { @@ -1248,7 +1330,7 @@ } public static enum PatchsetType { - Proposal, FastForward, Rebase, Squash, Rebase_Squash, Amend; + Proposal, FastForward, Rebase, Squash, Rebase_Squash, Amend, Delete; public boolean isRewrite() { return (this != FastForward) && (this != Proposal); @@ -1283,4 +1365,110 @@ return null; } } + + public static enum Priority { + Low(-1), Normal(0), High(1), Urgent(2); + + public static Priority defaultPriority = Normal; + + final int value; + + Priority(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static Priority [] choices() { + return new Priority [] { Urgent, High, Normal, Low }; + } + + @Override + public String toString() { + return name().toLowerCase().replace('_', ' '); + } + + public static Priority fromObject(Object o, Priority defaultPriority) { + 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.name().equalsIgnoreCase(str) + || priority.toString().equalsIgnoreCase(str)) { + return priority; + } + } + } else if (o instanceof Number) { + + switch (((Number) o).intValue()) { + case -1: return Priority.Low; + case 0: return Priority.Normal; + case 1: return Priority.High; + case 2: return Priority.Urgent; + default: return Priority.Normal; + } + } + + return defaultPriority; + } + } + + public static enum Severity { + Unrated(-1), Negligible(1), Minor(2), Serious(3), Critical(4), Catastrophic(5); + + public static Severity defaultSeverity = Unrated; + + final int value; + + Severity(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static Severity [] choices() { + return new Severity [] { Unrated, Negligible, Minor, Serious, Critical, Catastrophic }; + } + + @Override + public String toString() { + return name().toLowerCase().replace('_', ' '); + } + + public static Severity fromObject(Object o, Severity defaultSeverity) { + if (o instanceof Severity) { + // cast and return + return (Severity) o; + } else if (o instanceof String) { + // find by name + for (Severity severity : values()) { + String str = o.toString(); + if (severity.name().equalsIgnoreCase(str) + || severity.toString().equalsIgnoreCase(str)) { + return severity; + } + } + } else if (o instanceof Number) { + + switch (((Number) o).intValue()) { + case -1: return Severity.Unrated; + case 1: return Severity.Negligible; + case 2: return Severity.Minor; + case 3: return Severity.Serious; + case 4: return Severity.Critical; + case 5: return Severity.Catastrophic; + default: return Severity.Unrated; + } + } + + return defaultSeverity; + } + } } -- Gitblit v1.9.1