public void initComponent() { if (!ApplicationManager.getApplication().isUnitTestMode()) { myCacheRefreshTimer = UIUtil.createNamedTimer( "TaskManager refresh", myConfig.updateInterval * 60 * 1000, new ActionListener() { public void actionPerformed(ActionEvent e) { if (myConfig.updateEnabled && !myUpdating) { updateIssues(null); } } }); myCacheRefreshTimer.setInitialDelay(0); StartupManager.getInstance(myProject) .registerPostStartupActivity( new Runnable() { public void run() { myCacheRefreshTimer.start(); } }); } // make sure that the default task is exist LocalTask defaultTask = findTask(LocalTaskImpl.DEFAULT_TASK_ID); if (defaultTask == null) { defaultTask = createDefaultTask(); addTask(defaultTask); } // search for active task LocalTask activeTask = null; final List<LocalTask> tasks = getLocalTasks(); Collections.sort(tasks, TASK_UPDATE_COMPARATOR); for (LocalTask task : tasks) { if (activeTask == null) { if (task.isActive()) { activeTask = task; } } else { task.setActive(false); } } if (activeTask == null) { activeTask = defaultTask; } myActiveTask = activeTask; doActivate(myActiveTask, false); myDispatcher.getMulticaster().taskActivated(myActiveTask); }
@Override public LocalTask put(String key, LocalTask task) { LocalTask result = super.put(key, task); if (size() > myConfig.taskHistoryLength) { ArrayList<LocalTask> list = new ArrayList<LocalTask>(values()); Collections.sort(list, TASK_UPDATE_COMPARATOR); for (LocalTask oldest : list) { if (!oldest.isDefault()) { remove(oldest); break; } } } return result; }
/** @author Dmitry Avdeev */ @State( name = "TaskManager", storages = {@Storage(file = StoragePathMacros.WORKSPACE_FILE)}) public class TaskManagerImpl extends TaskManager implements ProjectComponent, PersistentStateComponent<TaskManagerImpl.Config>, ChangeListDecorator { private static final Logger LOG = Logger.getInstance("#com.intellij.tasks.impl.TaskManagerImpl"); private static final DecimalFormat LOCAL_TASK_ID_FORMAT = new DecimalFormat("LOCAL-00000"); public static final Comparator<Task> TASK_UPDATE_COMPARATOR = new Comparator<Task>() { public int compare(Task o1, Task o2) { int i = Comparing.compare(o2.getUpdated(), o1.getUpdated()); return i == 0 ? Comparing.compare(o2.getCreated(), o1.getCreated()) : i; } }; private static final Convertor<Task, String> KEY_CONVERTOR = new Convertor<Task, String>() { @Override public String convert(Task o) { return o.getId(); } }; static final String TASKS_NOTIFICATION_GROUP = "Task Group"; private final Project myProject; private final WorkingContextManager myContextManager; private final Map<String, Task> myIssueCache = Collections.synchronizedMap(new LinkedHashMap<String, Task>()); private final Map<String, LocalTask> myTasks = Collections.synchronizedMap( new LinkedHashMap<String, LocalTask>() { @Override public LocalTask put(String key, LocalTask task) { LocalTask result = super.put(key, task); if (size() > myConfig.taskHistoryLength) { ArrayList<LocalTask> list = new ArrayList<LocalTask>(values()); Collections.sort(list, TASK_UPDATE_COMPARATOR); for (LocalTask oldest : list) { if (!oldest.isDefault()) { remove(oldest); break; } } } return result; } }); @NotNull private LocalTask myActiveTask = createDefaultTask(); private Timer myCacheRefreshTimer; private volatile boolean myUpdating; private final Config myConfig = new Config(); private final ChangeListAdapter myChangeListListener; private final ChangeListManager myChangeListManager; private final List<TaskRepository> myRepositories = new ArrayList<TaskRepository>(); private final EventDispatcher<TaskListener> myDispatcher = EventDispatcher.create(TaskListener.class); private Set<TaskRepository> myBadRepositories = new ConcurrentHashSet<TaskRepository>(); public TaskManagerImpl( Project project, WorkingContextManager contextManager, final ChangeListManager changeListManager) { myProject = project; myContextManager = contextManager; myChangeListManager = changeListManager; myChangeListListener = new ChangeListAdapter() { @Override public void changeListRemoved(ChangeList list) { LocalTask task = getAssociatedTask((LocalChangeList) list); if (task != null) { for (ChangeListInfo info : task.getChangeLists()) { if (Comparing.equal(info.id, ((LocalChangeList) list).getId())) { info.id = ""; } } } } @Override public void defaultListChanged(ChangeList oldDefaultList, ChangeList newDefaultList) { final LocalTask associatedTask = getAssociatedTask((LocalChangeList) newDefaultList); if (associatedTask != null && !getActiveTask().equals(associatedTask)) { ApplicationManager.getApplication() .invokeLater( new Runnable() { public void run() { activateTask(associatedTask, true); } }, myProject.getDisposed()); } } }; } @Override public TaskRepository[] getAllRepositories() { return myRepositories.toArray(new TaskRepository[myRepositories.size()]); } public <T extends TaskRepository> void setRepositories(List<T> repositories) { Set<TaskRepository> set = new HashSet<TaskRepository>(myRepositories); set.removeAll(repositories); myBadRepositories.removeAll(set); // remove all changed reps myIssueCache.clear(); myRepositories.clear(); myRepositories.addAll(repositories); reps: for (T repository : repositories) { if (repository.isShared() && repository.getUrl() != null) { List<TaskProjectConfiguration.SharedServer> servers = getProjectConfiguration().servers; TaskRepositoryType type = repository.getRepositoryType(); for (TaskProjectConfiguration.SharedServer server : servers) { if (repository.getUrl().equals(server.url) && type.getName().equals(server.type)) { continue reps; } } TaskProjectConfiguration.SharedServer server = new TaskProjectConfiguration.SharedServer(); server.type = type.getName(); server.url = repository.getUrl(); servers.add(server); } } } @Override public void removeTask(LocalTask task) { if (task.isDefault()) return; if (myActiveTask.equals(task)) { activateTask(myTasks.get(LocalTaskImpl.DEFAULT_TASK_ID), true); } myTasks.remove(task.getId()); myDispatcher.getMulticaster().taskRemoved(task); myContextManager.removeContext(task); } @Override public void addTaskListener(TaskListener listener) { myDispatcher.addListener(listener); } @Override public void removeTaskListener(TaskListener listener) { myDispatcher.removeListener(listener); } @NotNull @Override public LocalTask getActiveTask() { return myActiveTask; } @Nullable @Override public LocalTask findTask(String id) { return myTasks.get(id); } @NotNull @Override public List<Task> getIssues(@Nullable final String query) { return getIssues(query, true); } @Override public List<Task> getIssues(@Nullable final String query, final boolean forceRequest) { return getIssues(query, 50, 0, forceRequest, true, new EmptyProgressIndicator()); } @Override public List<Task> getIssues( @Nullable String query, int max, long since, boolean forceRequest, final boolean withClosed, @NotNull final ProgressIndicator cancelled) { List<Task> tasks = getIssuesFromRepositories(query, max, since, forceRequest, cancelled); if (tasks == null) return getCachedIssues(withClosed); myIssueCache.putAll(ContainerUtil.newMapFromValues(tasks.iterator(), KEY_CONVERTOR)); return ContainerUtil.filter( tasks, new Condition<Task>() { @Override public boolean value(final Task task) { return withClosed || !task.isClosed(); } }); } @Override public List<Task> getCachedIssues() { return getCachedIssues(true); } @Override public List<Task> getCachedIssues(final boolean withClosed) { return ContainerUtil.filter( myIssueCache.values(), new Condition<Task>() { @Override public boolean value(final Task task) { return withClosed || !task.isClosed(); } }); } @Nullable @Override public Task updateIssue(@NotNull String id) { for (TaskRepository repository : getAllRepositories()) { if (repository.extractId(id) == null) { continue; } try { Task issue = repository.findTask(id); if (issue != null) { LocalTask localTask = findTask(id); if (localTask != null) { localTask.updateFromIssue(issue); return localTask; } return issue; } } catch (Exception e) { LOG.info(e); } } return null; } @Override public List<LocalTask> getLocalTasks() { return getLocalTasks(true); } @Override public List<LocalTask> getLocalTasks(final boolean withClosed) { synchronized (myTasks) { return ContainerUtil.filter( myTasks.values(), new Condition<LocalTask>() { @Override public boolean value(final LocalTask task) { return withClosed || !isLocallyClosed(task); } }); } } @Override public LocalTask addTask(Task issue) { LocalTaskImpl task = issue instanceof LocalTaskImpl ? (LocalTaskImpl) issue : new LocalTaskImpl(issue); addTask(task); return task; } @Override public LocalTaskImpl createLocalTask(@NotNull String summary) { return createTask(LOCAL_TASK_ID_FORMAT.format(myConfig.localTasksCounter++), summary); } private static LocalTaskImpl createTask(@NotNull String id, @NotNull String summary) { LocalTaskImpl task = new LocalTaskImpl(id, summary); Date date = new Date(); task.setCreated(date); task.setUpdated(date); return task; } @Override public LocalTask activateTask(@NotNull final Task origin, boolean clearContext) { LocalTask activeTask = getActiveTask(); if (origin.equals(activeTask)) return activeTask; saveActiveTask(); if (clearContext) { myContextManager.clearContext(); } myContextManager.restoreContext(origin); final LocalTask task = doActivate(origin, true); return restoreVcsContext(task); } private LocalTask restoreVcsContext(LocalTask task) { if (!isVcsEnabled()) return task; List<ChangeListInfo> changeLists = task.getChangeLists(); if (!changeLists.isEmpty()) { ChangeListInfo info = changeLists.get(0); LocalChangeList changeList = myChangeListManager.getChangeList(info.id); if (changeList == null) { changeList = myChangeListManager.addChangeList(info.name, info.comment); info.id = changeList.getId(); } myChangeListManager.setDefaultChangeList(changeList); } List<BranchInfo> branches = task.getBranches(false); VcsTaskHandler.TaskInfo info = fromBranches(branches); VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(myProject); for (VcsTaskHandler handler : handlers) { handler.switchToTask(info); } return task; } private static VcsTaskHandler.TaskInfo fromBranches(List<BranchInfo> branches) { MultiMap<String, String> map = new MultiMap<String, String>(); for (BranchInfo branch : branches) { map.putValue(branch.name, branch.repository); } return new VcsTaskHandler.TaskInfo(map); } public void createBranch(LocalTask task, LocalTask previousActive, String name) { VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(myProject); for (VcsTaskHandler handler : handlers) { VcsTaskHandler.TaskInfo info = handler.getActiveTask(); if (previousActive != null) { addBranches(previousActive, info, false); } addBranches(task, info, true); addBranches(task, handler.startNewTask(name), false); } } public void mergeBranch(LocalTask task) { VcsTaskHandler.TaskInfo original = fromBranches(task.getBranches(true)); VcsTaskHandler.TaskInfo feature = fromBranches(task.getBranches(false)); VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(myProject); for (VcsTaskHandler handler : handlers) { handler.closeTask(feature, original); } } private static void addBranches(LocalTask task, VcsTaskHandler.TaskInfo info, boolean original) { List<BranchInfo> branchInfos = BranchInfo.fromTaskInfo(info, original); for (BranchInfo branchInfo : branchInfos) { task.addBranch(branchInfo); } } private void saveActiveTask() { myContextManager.saveContext(myActiveTask); myActiveTask.setUpdated(new Date()); } private LocalTask doActivate(Task origin, boolean explicitly) { final LocalTaskImpl task = origin instanceof LocalTaskImpl ? (LocalTaskImpl) origin : new LocalTaskImpl(origin); if (explicitly) { task.setUpdated(new Date()); } myActiveTask.setActive(false); task.setActive(true); addTask(task); if (task.isIssue()) { StartupManager.getInstance(myProject) .runWhenProjectIsInitialized( new Runnable() { public void run() { ProgressManager.getInstance() .run( new com.intellij.openapi.progress.Task.Backgroundable( myProject, "Updating " + task.getId()) { public void run(@NotNull ProgressIndicator indicator) { updateIssue(task.getId()); } }); } }); } LocalTask oldActiveTask = myActiveTask; boolean isChanged = !task.equals(oldActiveTask); myActiveTask = task; if (isChanged) { myDispatcher.getMulticaster().taskDeactivated(oldActiveTask); myDispatcher.getMulticaster().taskActivated(task); } return task; } private void addTask(LocalTaskImpl task) { myTasks.put(task.getId(), task); myDispatcher.getMulticaster().taskAdded(task); } @Override public boolean testConnection(final TaskRepository repository) { TestConnectionTask task = new TestConnectionTask("Test connection") { public void run(@NotNull ProgressIndicator indicator) { indicator.setText("Connecting to " + repository.getUrl() + "..."); indicator.setFraction(0); indicator.setIndeterminate(true); try { myConnection = repository.createCancellableConnection(); if (myConnection != null) { Future<Exception> future = ApplicationManager.getApplication().executeOnPooledThread(myConnection); while (true) { try { myException = future.get(100, TimeUnit.MILLISECONDS); return; } catch (TimeoutException ignore) { try { indicator.checkCanceled(); } catch (ProcessCanceledException e) { myException = e; myConnection.cancel(); return; } } catch (Exception e) { myException = e; return; } } } else { try { repository.testConnection(); } catch (Exception e) { LOG.info(e); myException = e; } } } catch (Exception e) { myException = e; } } }; ProgressManager.getInstance().run(task); Exception e = task.myException; if (e == null) { myBadRepositories.remove(repository); Messages.showMessageDialog( myProject, "Connection is successful", "Connection", Messages.getInformationIcon()); } else if (!(e instanceof ProcessCanceledException)) { String message = e.getMessage(); if (e instanceof UnknownHostException) { message = "Unknown host: " + message; } if (message == null) { LOG.error(e); message = "Unknown error"; } Messages.showErrorDialog(myProject, StringUtil.capitalize(message), "Error"); } return e == null; } @SuppressWarnings({"unchecked"}) @NotNull public Config getState() { myConfig.tasks = ContainerUtil.map( myTasks.values(), new Function<Task, LocalTaskImpl>() { public LocalTaskImpl fun(Task task) { return new LocalTaskImpl(task); } }); myConfig.servers = XmlSerializer.serialize(getAllRepositories()); return myConfig; } @SuppressWarnings({"unchecked"}) public void loadState(Config config) { XmlSerializerUtil.copyBean(config, myConfig); myTasks.clear(); for (LocalTaskImpl task : config.tasks) { addTask(task); } myRepositories.clear(); Element element = config.servers; List<TaskRepository> repositories = loadRepositories(element); myRepositories.addAll(repositories); } public static ArrayList<TaskRepository> loadRepositories(Element element) { ArrayList<TaskRepository> repositories = new ArrayList<TaskRepository>(); for (TaskRepositoryType repositoryType : TaskRepositoryType.getRepositoryTypes()) { for (Object o : element.getChildren()) { if (((Element) o).getName().equals(repositoryType.getName())) { try { @SuppressWarnings({"unchecked"}) TaskRepository repository = (TaskRepository) XmlSerializer.deserialize((Element) o, repositoryType.getRepositoryClass()); if (repository != null) { repository.setRepositoryType(repositoryType); repositories.add(repository); } } catch (XmlSerializationException e) { // ignore LOG.error(e.getMessage()); } } } } return repositories; } public void projectOpened() { TaskProjectConfiguration projectConfiguration = getProjectConfiguration(); servers: for (TaskProjectConfiguration.SharedServer server : projectConfiguration.servers) { if (server.type == null || server.url == null) { continue; } for (TaskRepositoryType<?> repositoryType : TaskRepositoryType.getRepositoryTypes()) { if (repositoryType.getName().equals(server.type)) { for (TaskRepository repository : myRepositories) { if (!repositoryType.equals(repository.getRepositoryType())) { continue; } if (server.url.equals(repository.getUrl())) { continue servers; } } TaskRepository repository = repositoryType.createRepository(); repository.setUrl(server.url); myRepositories.add(repository); } } } myContextManager.pack(200, 50); // make sure the task is associated with default changelist LocalTask defaultTask = findTask(LocalTaskImpl.DEFAULT_TASK_ID); LocalChangeList defaultList = myChangeListManager.findChangeList(LocalChangeList.DEFAULT_NAME); if (defaultList != null && defaultTask != null) { ChangeListInfo listInfo = new ChangeListInfo(defaultList); if (!defaultTask.getChangeLists().contains(listInfo)) { defaultTask.addChangelist(listInfo); } } // remove already not existing changelists from tasks changelists for (LocalTask localTask : getLocalTasks()) { for (Iterator<ChangeListInfo> iterator = localTask.getChangeLists().iterator(); iterator.hasNext(); ) { final ChangeListInfo changeListInfo = iterator.next(); if (myChangeListManager.getChangeList(changeListInfo.id) == null) { iterator.remove(); } } } myChangeListManager.addChangeListListener(myChangeListListener); } private TaskProjectConfiguration getProjectConfiguration() { return ServiceManager.getService(myProject, TaskProjectConfiguration.class); } public void projectClosed() {} @NotNull public String getComponentName() { return "Task Manager"; } public void initComponent() { if (!ApplicationManager.getApplication().isUnitTestMode()) { myCacheRefreshTimer = UIUtil.createNamedTimer( "TaskManager refresh", myConfig.updateInterval * 60 * 1000, new ActionListener() { public void actionPerformed(ActionEvent e) { if (myConfig.updateEnabled && !myUpdating) { updateIssues(null); } } }); myCacheRefreshTimer.setInitialDelay(0); StartupManager.getInstance(myProject) .registerPostStartupActivity( new Runnable() { public void run() { myCacheRefreshTimer.start(); } }); } // make sure that the default task is exist LocalTask defaultTask = findTask(LocalTaskImpl.DEFAULT_TASK_ID); if (defaultTask == null) { defaultTask = createDefaultTask(); addTask(defaultTask); } // search for active task LocalTask activeTask = null; final List<LocalTask> tasks = getLocalTasks(); Collections.sort(tasks, TASK_UPDATE_COMPARATOR); for (LocalTask task : tasks) { if (activeTask == null) { if (task.isActive()) { activeTask = task; } } else { task.setActive(false); } } if (activeTask == null) { activeTask = defaultTask; } myActiveTask = activeTask; doActivate(myActiveTask, false); myDispatcher.getMulticaster().taskActivated(myActiveTask); } private static LocalTaskImpl createDefaultTask() { return new LocalTaskImpl(LocalTaskImpl.DEFAULT_TASK_ID, "Default task"); } public void disposeComponent() { if (myCacheRefreshTimer != null) { myCacheRefreshTimer.stop(); } myChangeListManager.removeChangeListListener(myChangeListListener); } public void updateIssues(final @Nullable Runnable onComplete) { TaskRepository first = ContainerUtil.find( getAllRepositories(), new Condition<TaskRepository>() { public boolean value(TaskRepository repository) { return repository.isConfigured(); } }); if (first == null) { myIssueCache.clear(); if (onComplete != null) { onComplete.run(); } return; } myUpdating = true; if (ApplicationManager.getApplication().isUnitTestMode()) { doUpdate(onComplete); } else { ApplicationManager.getApplication() .executeOnPooledThread( new Runnable() { public void run() { doUpdate(onComplete); } }); } } private void doUpdate(@Nullable Runnable onComplete) { try { List<Task> issues = getIssuesFromRepositories( null, myConfig.updateIssuesCount, 0, false, new EmptyProgressIndicator()); if (issues == null) return; synchronized (myIssueCache) { myIssueCache.clear(); for (Task issue : issues) { myIssueCache.put(issue.getId(), issue); } } // update local tasks synchronized (myTasks) { for (Map.Entry<String, LocalTask> entry : myTasks.entrySet()) { Task issue = myIssueCache.get(entry.getKey()); if (issue != null) { entry.getValue().updateFromIssue(issue); } } } } finally { if (onComplete != null) { onComplete.run(); } myUpdating = false; } } @Nullable private List<Task> getIssuesFromRepositories( @Nullable String request, int max, long since, boolean forceRequest, @NotNull final ProgressIndicator cancelled) { List<Task> issues = null; for (final TaskRepository repository : getAllRepositories()) { if (!repository.isConfigured() || (!forceRequest && myBadRepositories.contains(repository))) { continue; } try { Task[] tasks = repository.getIssues(request, max, since, cancelled); myBadRepositories.remove(repository); if (issues == null) issues = new ArrayList<Task>(tasks.length); if (!repository.isSupported(TaskRepository.NATIVE_SEARCH) && request != null) { List<Task> filteredTasks = TaskSearchSupport.filterTasks(request, ContainerUtil.list(tasks)); ContainerUtil.addAll(issues, filteredTasks); } else { ContainerUtil.addAll(issues, tasks); } } catch (ProcessCanceledException ignored) { // OK } catch (Exception e) { String reason = ""; // Fix to IDEA-111810 if (e.getClass() == Exception.class) { // probably contains some message meaningful to end-user reason = e.getMessage(); } //noinspection InstanceofCatchParameter if (e instanceof SocketTimeoutException) { LOG.warn("Socket timeout from " + repository); } else { LOG.warn("Cannot connect to " + repository, e); } myBadRepositories.add(repository); if (forceRequest) { notifyAboutConnectionFailure(repository, reason); } } } return issues; } private void notifyAboutConnectionFailure(final TaskRepository repository, String details) { Notifications.Bus.register(TASKS_NOTIFICATION_GROUP, NotificationDisplayType.BALLOON); String content = "<p><a href=\"\">Configure server...</a></p>"; if (!StringUtil.isEmpty(details)) { content = "<p>" + details + "</p>" + content; } Notifications.Bus.notify( new Notification( TASKS_NOTIFICATION_GROUP, "Cannot connect to " + repository.getUrl(), content, NotificationType.WARNING, new NotificationListener() { public void hyperlinkUpdate( @NotNull Notification notification, @NotNull HyperlinkEvent event) { TaskRepositoriesConfigurable configurable = new TaskRepositoriesConfigurable(myProject); ShowSettingsUtil.getInstance().editConfigurable(myProject, configurable); if (!ArrayUtil.contains(repository, getAllRepositories())) { notification.expire(); } } }), myProject); } @Override public boolean isVcsEnabled() { return ProjectLevelVcsManager.getInstance(myProject).getAllActiveVcss().length > 0; } @Override public AbstractVcs getActiveVcs() { AbstractVcs[] vcss = ProjectLevelVcsManager.getInstance(myProject).getAllActiveVcss(); if (vcss.length == 0) return null; for (AbstractVcs vcs : vcss) { if (vcs.getType() == VcsType.distributed) { return vcs; } } return vcss[0]; } @Override public boolean isLocallyClosed(final LocalTask localTask) { if (isVcsEnabled()) { List<ChangeListInfo> lists = localTask.getChangeLists(); if (lists.isEmpty()) return true; for (ChangeListInfo list : lists) { if (StringUtil.isEmpty(list.id)) { return true; } } } return false; } @Nullable @Override public LocalTask getAssociatedTask(LocalChangeList list) { for (LocalTask task : getLocalTasks()) { for (ChangeListInfo changeListInfo : task.getChangeLists()) { if (changeListInfo.id.equals(list.getId())) { return task; } } } return null; } @Override public void trackContext(LocalChangeList changeList) { ChangeListInfo changeListInfo = new ChangeListInfo(changeList); String changeListName = changeList.getName(); LocalTaskImpl task = createLocalTask(changeListName); task.addChangelist(changeListInfo); addTask(task); if (changeList.isDefault()) { activateTask(task, false); } } @Override public void disassociateFromTask(LocalChangeList changeList) { ChangeListInfo changeListInfo = new ChangeListInfo(changeList); for (LocalTask localTask : getLocalTasks()) { if (localTask.getChangeLists().contains(changeListInfo)) { localTask.removeChangelist(changeListInfo); } } } public void decorateChangeList( LocalChangeList changeList, ColoredTreeCellRenderer cellRenderer, boolean selected, boolean expanded, boolean hasFocus) { LocalTask task = getAssociatedTask(changeList); if (task != null && task.isIssue()) { cellRenderer.setIcon(task.getIcon()); } } public void createChangeList(LocalTask task, String name) { String comment = TaskUtil.getChangeListComment(task); createChangeList(task, name, comment); } private void createChangeList(LocalTask task, String name, @Nullable String comment) { LocalChangeList changeList = myChangeListManager.findChangeList(name); if (changeList == null) { changeList = myChangeListManager.addChangeList(name, comment); } else { final LocalTask associatedTask = getAssociatedTask(changeList); if (associatedTask != null) { associatedTask.removeChangelist(new ChangeListInfo(changeList)); } changeList.setComment(comment); } task.addChangelist(new ChangeListInfo(changeList)); myChangeListManager.setDefaultChangeList(changeList); } public String getChangelistName(Task task) { if (task.isIssue() && myConfig.changelistNameFormat != null) { return TaskUtil.formatTask(task, myConfig.changelistNameFormat); } return task.getSummary(); } public String suggestBranchName(Task task) { if (task.isIssue() && StringUtil.isNotEmpty(task.getNumber())) { return task.getId().replace(' ', '-'); } else { String summary = task.getSummary(); List<String> words = StringUtil.getWordsIn(summary); String[] strings = ArrayUtil.toStringArray(words); return StringUtil.join(strings, 0, Math.min(2, strings.length), "-"); } } @TestOnly public ChangeListAdapter getChangeListListener() { return myChangeListListener; } public static class Config { @Property(surroundWithTag = false) @AbstractCollection(surroundWithTag = false, elementTag = "task") public List<LocalTaskImpl> tasks = new ArrayList<LocalTaskImpl>(); public int localTasksCounter = 1; public int taskHistoryLength = 50; public boolean updateEnabled = true; public int updateInterval = 20; public int updateIssuesCount = 100; // create task options public boolean clearContext = true; public boolean createChangelist = true; public boolean createBranch = true; // close task options public boolean closeIssue = true; public boolean commitChanges = true; public boolean mergeBranch = true; public boolean saveContextOnCommit = true; public boolean trackContextForNewChangelist = false; public boolean markAsInProgress = false; public String changelistNameFormat = "{id} {summary}"; public boolean searchClosedTasks = false; @Tag("servers") public Element servers = new Element("servers"); } private abstract class TestConnectionTask extends com.intellij.openapi.progress.Task.Modal { protected Exception myException; @Nullable protected TaskRepository.CancellableConnection myConnection; public TestConnectionTask(String title) { super(TaskManagerImpl.this.myProject, title, true); } @Override public void onCancel() { if (myConnection != null) { myConnection.cancel(); } } } }