import com.gitblit.Constants.AccessPermission;\r
import com.gitblit.Constants.AuthorizationControl;\r
import com.gitblit.models.RegistrantAccessPermission;\r
+import com.gitblit.models.RepositoryModel;\r
import com.gitblit.models.TicketModel;\r
import com.gitblit.models.TicketModel.Change;\r
import com.gitblit.models.TicketModel.Field;\r
\r
form.setOutputMarkupId(true);\r
\r
- form.add(new TicketRelationEditorPanel("dependencies", dependenciesModel, getRepositoryModel()));\r
+ form.add(new TicketRelationEditorPanel("dependencies", dependenciesModel, ticket.number) {\r
+ private static final long serialVersionUID = 1L;\r
+ @Override\r
+ protected RepositoryModel getRepositoryModel() {\r
+ return EditTicketPage.this.getRepositoryModel();\r
+ }\r
+ });\r
\r
final IModel<String> markdownPreviewModel = Model.of(ticket.body == null ? "" : ticket.body);\r
descriptionPreview = new Label("descriptionPreview", markdownPreviewModel);\r
import com.gitblit.Constants.AccessPermission;\r
import com.gitblit.Constants.AuthorizationControl;\r
import com.gitblit.models.RegistrantAccessPermission;\r
+import com.gitblit.models.RepositoryModel;\r
import com.gitblit.models.TicketModel;\r
import com.gitblit.models.TicketModel.Change;\r
import com.gitblit.models.TicketModel.Field;\r
descriptionEditor.setRepository(repositoryName);\r
form.add(descriptionEditor);\r
\r
- form.add(new TicketRelationEditorPanel("dependencies", dependenciesModel, getRepositoryModel()));\r
+ form.add(new TicketRelationEditorPanel("dependencies", dependenciesModel, null) {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+ \r
+ @Override\r
+ protected RepositoryModel getRepositoryModel() {\r
+ return NewTicketPage.this.getRepositoryModel();\r
+ }\r
+ });\r
\r
if (currentUser.canAdmin(null, getRepositoryModel())) {\r
// responsible\r
package com.gitblit.wicket.panels;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.jsoup.helper.StringUtil;
import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.TicketModel;
+import com.gitblit.tickets.ITicketService;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.pages.TicketsPage;
-public class TicketRelationEditorPanel extends BasePanel {
+public abstract class TicketRelationEditorPanel extends BasePanel {
private static final long serialVersionUID = 1L;
private IModel<List<String>> dependenciesModel;
private IModel<String> addDependencyModel;
-
+ private Long baseTicketId;
- public TicketRelationEditorPanel(String wicketId, IModel<List<String>> pdependenciesModel, final RepositoryModel repositoryModel) {
+ public TicketRelationEditorPanel(String wicketId, IModel<List<String>> pdependenciesModel, Long baseTicketId) {
super(wicketId);
this.dependenciesModel = pdependenciesModel;
this.addDependencyModel = Model.of();
+ this.baseTicketId = baseTicketId;
add(new ListView<String>("dependencyList", dependenciesModel) {
protected void populateItem(ListItem<String> item) {
final String ticketId = item.getModelObject();
- PageParameters tp = WicketUtils.newObjectParameter(repositoryModel.name, ticketId);
+ PageParameters tp = WicketUtils.newObjectParameter(getRepositoryModel().name, ticketId);
item.add(new LinkPanel("dependencyLink", "list subject", "#"+ticketId, TicketsPage.class, tp));
item.add(new AjaxButton("removeDependencyLink") {
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
String ticketIdStr = addDependencyModel.getObject();
if (!StringUtil.isBlank(ticketIdStr)) {
- try {
- long ticketId = Long.parseLong(ticketIdStr);
- if (app().tickets().hasTicket(repositoryModel, ticketId)) {
- List<String> list = (List<String>) dependenciesModel.getObject();
- list.add(String.valueOf(ticketId));
- addDependencyModel.setObject("");
- }
- } catch (NumberFormatException e) {
- // TODO : not allowed
-
+ if (checkCycle(ticketIdStr)) {
+ List<String> list = (List<String>) dependenciesModel.getObject();
+ list.add(ticketIdStr.trim());
+ addDependencyModel.setObject("");
}
}
target.addComponent(form);
}
});
-
-
}
+
+ private boolean checkCycle(String ticketId) {
+ Set<Long> tickets = new HashSet<Long>();
+ if (baseTicketId != null) {
+ tickets.add(baseTicketId);
+ }
+ return checkCycle(tickets, ticketId);
+ }
+
+ private boolean checkCycle(Set<Long> tickets, String ticketIdStr) {
+ try {
+ long ticketId = Long.parseLong(ticketIdStr);
+ if (tickets.contains(ticketId)) {
+ return false;
+ }
+ ITicketService ticketService = app().tickets();
+ RepositoryModel r = getRepositoryModel();
+ if (ticketService.hasTicket(r, ticketId)) {
+ TicketModel ticket = ticketService.getTicket(r, ticketId);
+ tickets.add(ticketId);
+ for (String subTicketIdStr : ticket.getDependencies()) {
+ if (!checkCycle(tickets, subTicketIdStr)) {
+ return false;
+ }
+ }
+ tickets.remove(ticketId);
+ return true;
+ } else {
+ return false;
+ }
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+
+ protected abstract RepositoryModel getRepositoryModel();
}