import javax.swing.*;
import javax.swing.event.TableModelEvent;
+import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
-import javax.swing.table.JTableHeader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
return ((ListTableModel<Item>)getModel()).getItems();
}
+ public void resortKeepSelection() {
+ final int column = getSelectedColumn();
+ if (column != -1) {
+ SortableColumnModel model = getListTableModel();
+ Collection selection = getSelection();
+ model.sortByColumn(column);
+ setSelection(selection);
+ }
+ }
+
protected void onHeaderClicked(int column) {
SortableColumnModel model = getListTableModel();
Collection selection = getSelection();
--- /dev/null
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * 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.intellij.util;
+
+public interface AsynchConsumer<T> extends Consumer<T> {
+ void finished();
+}
--- /dev/null
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * 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.intellij.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class BufferedListConsumer<T> implements Consumer<List<T>> {
+ private final int mySize;
+ private final List<T> myBuffer;
+ private final Consumer<List<T>> myConsumer;
+
+ public BufferedListConsumer(int size, Consumer<List<T>> consumer) {
+ mySize = size;
+ myBuffer = new ArrayList<T>();
+ myConsumer = consumer;
+ }
+
+ public void consumeOne(final T t) {
+ consume(Collections.singletonList(t));
+ }
+
+ public void consume(List<T> list) {
+ myBuffer.addAll(list);
+ if (mySize <= myBuffer.size()) {
+ myConsumer.consume(new ArrayList<T>(myBuffer));
+ myBuffer.clear();
+ }
+ }
+
+ public void flush() {
+ if (! myBuffer.isEmpty()) {
+ myConsumer.consume(new ArrayList<T>(myBuffer));
+ myBuffer.clear();
+ }
+ }
+}
*/
package com.intellij.util.ui;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
public class ListTableModel<Item> extends TableViewModel<Item> implements ItemRemovable {
private ColumnInfo[] myColumnInfos;
fireTableRowsInserted(myItems.size() - 1, myItems.size() - 1);
}
+ public void addRows(final Collection<Item> items) {
+ myItems.addAll(items);
+ fireTableRowsInserted(myItems.size() - items.size(), myItems.size() - 1);
+// resort();
+ }
+
public Object getItem(final int rowIndex) {
return getItems().get(rowIndex);
}
import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings;
import com.intellij.openapi.vcs.versionBrowser.ChangesBrowserSettingsEditor;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
+import com.intellij.util.AsynchConsumer;
import org.jetbrains.annotations.Nullable;
import java.util.List;
VcsCommittedListsZipper getZipper();
List<T> getCommittedChanges(U settings, RepositoryLocation location, final int maxCount) throws VcsException;
+
+ void loadCommittedChanges(U settings, RepositoryLocation location, final int maxCount, final AsynchConsumer<CommittedChangeList> consumer) throws VcsException;
+
ChangeListColumn[] getColumns();
@Nullable
--- /dev/null
+/*
+ * Copyright 2000-2010 JetBrains s.r.o.
+ *
+ * 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.intellij.openapi.vcs.changes.committed;
+
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.project.Project;
+
+import java.awt.*;
+
+public abstract class AbstractCalledLater implements Runnable {
+ private final Project myProject;
+ private final ModalityState myState;
+
+ protected AbstractCalledLater(final Project project, final ModalityState modalityState) {
+ myProject = project;
+ myState = modalityState;
+ }
+
+ protected AbstractCalledLater(Project project, Component component) {
+ myProject = project;
+ myState = ModalityState.stateForComponent(component);
+ }
+
+ public void callMe() {
+ final Application application = ApplicationManager.getApplication();
+ if (application.isDispatchThread()) {
+ run();
+ } else {
+ application.invokeLater(this, myState, myProject.getDisposed());
+ }
+ }
+}
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
+import com.intellij.util.AsynchConsumer;
import javax.swing.*;
import java.awt.*;
+import java.util.List;
/**
* @author max
private CommittedChangesTableModel myChanges;
private Mode myMode;
private CommittedChangesBrowser myCommittedChangesBrowser;
+ private AsynchConsumer<List<CommittedChangeList>> myAppender;
public enum Mode { Simple, Browse, Choose }
myMode = mode;
setTitle(VcsBundle.message("dialog.title.changes.browser"));
setCancelButtonText(CommonBundle.getCloseButtonText());
- if ((mode != Mode.Choose) && (ModalityState.NON_MODAL.equals(ModalityState.current()))) {
+ final ModalityState currentState = ModalityState.current();
+ if ((mode != Mode.Choose) && (ModalityState.NON_MODAL.equals(currentState))) {
setModal(false);
}
+ myAppender = new AsynchConsumer<List<CommittedChangeList>>() {
+
+ public void finished() {
+ new AbstractCalledLater(myProject, ModalityState.stateForComponent(myCommittedChangesBrowser)) {
+ public void run() {
+ myCommittedChangesBrowser.stopLoading();
+ }
+ }.callMe();
+ }
+
+ public void consume(final List<CommittedChangeList> committedChangeLists) {
+ new AbstractCalledLater(myProject, ModalityState.stateForComponent(myCommittedChangesBrowser)) {
+ public void run() {
+ final boolean selectFirst = (myChanges.getRowCount() == 0) && (!committedChangeLists.isEmpty());
+ myChanges.addRows(committedChangeLists);
+ if (selectFirst) {
+ myCommittedChangesBrowser.selectFirstIfAny();
+ } else {
+ myCommittedChangesBrowser.resortKeepSelection();
+ }
+ }
+ }.callMe();
+ }
+ };
init();
}
+ public AsynchConsumer<List<CommittedChangeList>> getAppender() {
+ return myAppender;
+ }
+
+ public void startLoading() {
+ myCommittedChangesBrowser.startLoading();
+ }
+
protected String getDimensionServiceKey() {
return "VCS.ChangesBrowserDialog";
}
*/
public class CommittedChangesBrowser extends JPanel {
private final Project myProject;
+ // left view
private final TableView<CommittedChangeList> myChangeListsView;
+ // right view
private final ChangesBrowser myChangesView;
private CommittedChangesTableModel myTableModel;
private final JEditorPane myCommitMessageArea;
private CommittedChangeList mySelectedChangeList;
private final JPanel myLeftPanel;
+ private JPanel myLoadingLabelPanel;
public CommittedChangesBrowser(final Project project, final CommittedChangesTableModel tableModel) {
super(new BorderLayout());
commitPanel.add(separator, BorderLayout.NORTH);
myLeftPanel = new JPanel(new GridBagLayout());
- myLeftPanel.add(new JScrollPane(myChangeListsView), new GridBagConstraints(0, 0, 2, 1, 1, 1, GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(2,2,2,2), 0, 0));
+ final JLabel loadingLabel = new JLabel("Loading...");
+
+ myLoadingLabelPanel = new JPanel(new BorderLayout()) {
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(myLoadingLabelPanel.getWidth(), loadingLabel.getHeight());
+ }
+ };
+ myLoadingLabelPanel.setBackground(UIUtil.getToolTipBackground());
+ myLoadingLabelPanel.add(loadingLabel, BorderLayout.NORTH);
+
+ final JPanel listContainer = new JPanel(new GridBagLayout());
+ final GridBagConstraints innerGb =
+ new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0);
+ ++ innerGb.gridy;
+ innerGb.weighty = 0;
+ innerGb.fill = GridBagConstraints.HORIZONTAL;
+ if (myTableModel.isAsynchLoad()) {
+ listContainer.add(myLoadingLabelPanel, innerGb);
+ }
+ ++ innerGb.gridy;
+ innerGb.weighty = 1;
+ innerGb.fill = GridBagConstraints.BOTH;
+ listContainer.add(new JScrollPane(myChangeListsView), innerGb);
+
+ final GridBagConstraints gb =
+ new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTH, GridBagConstraints.BOTH, new Insets(1, 1, 1, 1), 0, 0);
+
+ myLeftPanel.add(listContainer, gb);
if (tableModel instanceof CommittedChangesNavigation) {
final CommittedChangesNavigation navigation = (CommittedChangesNavigation) tableModel;
JSplitPane leftSplitter = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
leftSplitter.setTopComponent(myLeftPanel);
leftSplitter.setBottomComponent(commitPanel);
- leftSplitter.setDividerLocation(0.6);
- leftSplitter.setResizeWeight(0.5);
+ leftSplitter.setDividerLocation(0.8);
+ leftSplitter.setResizeWeight(0.8);
JSplitPane splitter = new JSplitPane();
splitter.setLeftComponent(leftSplitter);
splitter.setRightComponent(myChangesView);
+ splitter.setDividerLocation(0.5);
+ splitter.setResizeWeight(0.5);
add(splitter, BorderLayout.CENTER);
myChangesView.getDiffAction().registerCustomShortcutSet(CommonShortcuts.getDiff(), myChangeListsView);
}
- private void selectFirstIfAny() {
+ public void selectFirstIfAny() {
if (myTableModel.getRowCount() > 0) {
TableUtil.selectRows(myChangeListsView, new int[]{0});
}
}
+ public void resortKeepSelection() {
+ if (myTableModel.getRowCount() > 0) {
+ myChangeListsView.resortKeepSelection();
+ }
+ }
+
public void addToolBar(JComponent toolBar) {
myLeftPanel.add(toolBar, BorderLayout.NORTH);
}
public void setTableContextMenu(final ActionGroup group) {
PopupHandler.installPopupHandler(myChangeListsView, group, ActionPlaces.UNKNOWN, ActionManager.getInstance());
}
+
+ public void startLoading() {
+ }
+
+ public void stopLoading() {
+ myLoadingLabelPanel.setVisible(false);
+ myLoadingLabelPanel.repaint();
+ }
}
import java.util.List;
public class CommittedChangesTableModel extends ListTableModel<CommittedChangeList> {
+ private final boolean myAsynchLoad;
private static final ChangeListColumn[] ourDefaultColumns = new ChangeListColumn[] { ChangeListColumn.DATE, ChangeListColumn.NAME };
- public CommittedChangesTableModel(final List<CommittedChangeList> changeLists) {
+ public CommittedChangesTableModel(final List<CommittedChangeList> changeLists, boolean asynchLoad) {
super(buildColumnInfos(ourDefaultColumns), changeLists, 0);
+ myAsynchLoad = asynchLoad;
}
- public CommittedChangesTableModel(final List<CommittedChangeList> changeLists, final ChangeListColumn[] columns) {
+ public CommittedChangesTableModel(final List<CommittedChangeList> changeLists, final ChangeListColumn[] columns, boolean asynchLoad) {
super(buildColumnInfos(columns), changeLists, 0);
+ myAsynchLoad = asynchLoad;
}
public void sortByChangesColumn(final ChangeListColumn column, int sortingType) {
return myColumn;
}
}
+
+ public boolean isAsynchLoad() {
+ return myAsynchLoad;
+ }
}
import com.intellij.openapi.vcs.versionBrowser.ChangesBrowserSettingsEditor;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.openapi.vcs.versionBrowser.DateFilterComponent;
+import com.intellij.util.AsynchConsumer;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
throw new UnsupportedOperationException();
}
+ public void loadCommittedChanges(CompositeChangeBrowserSettings settings,
+ RepositoryLocation location,
+ int maxCount,
+ AsynchConsumer<CommittedChangeList> consumer) throws VcsException {
+ throw new UnsupportedOperationException();
+ }
+
public ChangeListColumn[] getColumns() {
Set<ChangeListColumn> columns = new LinkedHashSet<ChangeListColumn>();
for(AbstractVcs vcs: myBaseVcss) {
package com.intellij.openapi.vcs.impl;
import com.intellij.ide.actions.CloseTabToolbarAction;
-import com.intellij.ide.errorTreeView.HotfixData;
import com.intellij.ide.errorTreeView.ErrorTreeElementKind;
+import com.intellij.ide.errorTreeView.HotfixData;
import com.intellij.ide.errorTreeView.SimpleErrorData;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
+import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Getter;
-import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.annotate.Annotater;
import com.intellij.openapi.vcs.annotate.AnnotationProvider;
import com.intellij.openapi.vcs.annotate.FileAnnotation;
+import com.intellij.openapi.vcs.changes.BackgroundFromStartOption;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.committed.*;
import com.intellij.openapi.vcs.changes.ui.*;
import com.intellij.ui.content.ContentFactory;
import com.intellij.ui.content.ContentManager;
import com.intellij.ui.content.MessageView;
+import com.intellij.util.AsynchConsumer;
+import com.intellij.util.BufferedListConsumer;
import com.intellij.util.Consumer;
import com.intellij.util.ContentsUtil;
import com.intellij.util.ui.ConfirmationDialog;
}
public void showChangesBrowser(List<CommittedChangeList> changelists, @Nls String title) {
- showChangesBrowser(new CommittedChangesTableModel(changelists), title, false, null);
+ showChangesBrowser(new CommittedChangesTableModel(changelists, false), title, false, null);
+ }
+
+ private ChangesBrowserDialog createChangesBrowserDialog(CommittedChangesTableModel changelists,
+ String title,
+ boolean showSearchAgain,
+ @Nullable final Component parent) {
+ final ChangesBrowserDialog.Mode mode = showSearchAgain ? ChangesBrowserDialog.Mode.Browse : ChangesBrowserDialog.Mode.Simple;
+ final ChangesBrowserDialog dlg = parent != null
+ ? new ChangesBrowserDialog(myProject, parent, changelists, mode)
+ : new ChangesBrowserDialog(myProject, changelists, mode);
+ if (title != null) {
+ dlg.setTitle(title);
+ }
+ return dlg;
}
private void showChangesBrowser(CommittedChangesTableModel changelists,
if (myProject.isDefault() || (ProjectLevelVcsManager.getInstance(myProject).getAllActiveVcss().length == 0) ||
(! ModalityState.NON_MODAL.equals(ModalityState.current()))) {
final List<CommittedChangeList> versions = new ArrayList<CommittedChangeList>();
- final List<VcsException> exceptions = new ArrayList<VcsException>();
- final Ref<CommittedChangesTableModel> tableModelRef = new Ref<CommittedChangesTableModel>();
- final ChangeBrowserSettings settings1 = settings;
- final boolean done = ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
- public void run() {
- try {
- versions.addAll(provider.getCommittedChanges(settings1, location, 0));
- }
- catch (VcsException e) {
- exceptions.add(e);
- }
- tableModelRef.set(new CommittedChangesTableModel(versions, provider.getColumns()));
- }
- }, VcsBundle.message("browse.changes.progress.title"), true, myProject);
+ if (parent == null || !parent.isValid()) {
+ parent = WindowManager.getInstance().suggestParentWindow(myProject);
+ }
+ final CommittedChangesTableModel model = new CommittedChangesTableModel(versions, true);
+ final ChangesBrowserDialog dlg = createChangesBrowserDialog(model, title, filterUI != null, parent);
- if (!done) return;
+ final AsynchronousListsLoader task = new AsynchronousListsLoader(myProject, provider, location, settings, dlg);
+ ProgressManager.getInstance().run(task);
+ dlg.show();
+ dlg.startLoading();
+ task.cancel();
- if (!exceptions.isEmpty()) {
+ final List<VcsException> exceptions = task.getExceptions();
+ if (! exceptions.isEmpty()) {
Messages.showErrorDialog(myProject, VcsBundle.message("browse.changes.error.message", exceptions.get(0).getMessage()),
VcsBundle.message("browse.changes.error.title"));
return;
}
- if (versions.isEmpty()) {
+ if (! task.isRevisionsReturned()) {
Messages.showInfoMessage(myProject, VcsBundle.message("browse.changes.nothing.found"),
VcsBundle.message("browse.changes.nothing.found.title"));
- return;
- }
-
- if (parent == null || !parent.isValid()) {
- parent = WindowManager.getInstance().suggestParentWindow(myProject);
}
- showChangesBrowser(tableModelRef.get(), title, filterUI != null, parent);
}
else {
+ // todo
openCommittedChangesTab(provider, location, settings, 0, title);
}
}
return null;
}
final ChangesBrowserDialog dlg = new ChangesBrowserDialog(myProject, new CommittedChangesTableModel((List<CommittedChangeList>)changes,
- provider.getColumns()),
+ provider.getColumns(), false),
ChangesBrowserDialog.Mode.Choose);
dlg.show();
if (dlg.isOK()) {
}
}
+ private static class AsynchronousListsLoader extends Task.Backgroundable {
+ private final CommittedChangesProvider myProvider;
+ private final RepositoryLocation myLocation;
+ private final ChangeBrowserSettings mySettings;
+ private final ChangesBrowserDialog myDlg;
+ private final List<VcsException> myExceptions;
+ private volatile boolean myCanceled;
+ private boolean myRevisionsReturned;
+
+ private AsynchronousListsLoader(@Nullable Project project, final CommittedChangesProvider provider,
+ final RepositoryLocation location, final ChangeBrowserSettings settings, final ChangesBrowserDialog dlg) {
+ super(project, VcsBundle.message("browse.changes.progress.title"), true, BackgroundFromStartOption.getInstance());
+ myProvider = provider;
+ myLocation = location;
+ mySettings = settings;
+ myDlg = dlg;
+ myExceptions = new LinkedList<VcsException>();
+ }
+
+ public void cancel() {
+ myCanceled = true;
+ }
+
+ @Override
+ public void run(@NotNull final ProgressIndicator indicator) {
+ final AsynchConsumer<List<CommittedChangeList>> appender = myDlg.getAppender();
+ final BufferedListConsumer<CommittedChangeList> bufferedListConsumer = new BufferedListConsumer<CommittedChangeList>(10, appender);
+
+ final Application application = ApplicationManager.getApplication();
+ try {
+ myProvider.loadCommittedChanges(mySettings, myLocation, 0, new AsynchConsumer<CommittedChangeList>() {
+ public void consume(CommittedChangeList committedChangeList) {
+ myRevisionsReturned = true;
+ bufferedListConsumer.consumeOne(committedChangeList);
+ if (myCanceled) {
+ indicator.cancel();
+ }
+ }
+
+ public void finished() {
+ bufferedListConsumer.flush();
+ appender.finished();
+
+ if (! myRevisionsReturned) {
+ application.invokeLater(new Runnable() {
+ public void run() {
+ myDlg.close(-1);
+ }
+ }, ModalityState.stateForComponent(myDlg.getWindow()));
+ }
+ }
+ });
+ }
+ catch (VcsException e) {
+ myExceptions.add(e);
+ application.invokeLater(new Runnable() {
+ public void run() {
+ myDlg.close(-1);
+ }
+ }, ModalityState.stateForComponent(myDlg.getWindow()));
+ }
+ }
+
+ public List<VcsException> getExceptions() {
+ return myExceptions;
+ }
+
+ public boolean isRevisionsReturned() {
+ return myRevisionsReturned;
+ }
+ }
}
import com.intellij.cvsSupport2.history.CvsRevisionNumber;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
import org.netbeans.lib.cvsclient.command.log.Revision;
import org.netbeans.lib.cvsclient.command.log.SymbolicName;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.NonNls;
import java.util.*;
return result;
}
- private void addRevision(RevisionWrapper revision) {
+ public CvsChangeList addRevision(RevisionWrapper revision) {
final Revision cvsRevision = revision.getRevision();
CvsChangeList version = findOrCreateVersionFor(cvsRevision.getMessage(),
revision.getTime(),
revision.getFile());
version.addFileRevision(revision);
+ return version;
}
private CvsChangeList findOrCreateVersionFor(final String message, final long date, final String author,
return result;
}
+ @Nullable
+ public RevisionWrapper revisionWrapperFromLog(final LogInformationWrapper log) {
+ final String file = log.getFile();
+ if (CvsChangeList.isAncestor(myRootPath, file)) {
+ for (Revision revision : log.getRevisions()) {
+ if (revision != null) {
+ if (revision.getState().equals(CvsChangeList.DEAD_STATE) &&
+ revision.getMessage().indexOf(INITIALLY_ADDED_ON_BRANCH) >= 0) {
+ // ignore dead revision (otherwise it'll get stuck in incoming changes forever - it's considered a deletion and
+ // the file is never actually deleted)
+ continue;
+ }
+ String branchName = getBranchName(revision, log.getSymbolicNames());
+ return new RevisionWrapper(stripAttic(file), revision, branchName);
+ }
+ }
+ }
+ return null;
+ }
+
public void addLogs(final List<LogInformationWrapper> logs) {
List<RevisionWrapper> revisionWrappers = new ArrayList<RevisionWrapper>();
for (LogInformationWrapper log : logs) {
- final String file = log.getFile();
- if (CvsChangeList.isAncestor(myRootPath, file)) {
- for (Revision revision : log.getRevisions()) {
- if (revision != null) {
- if (revision.getState().equals(CvsChangeList.DEAD_STATE) &&
- revision.getMessage().indexOf(INITIALLY_ADDED_ON_BRANCH) >= 0) {
- // ignore dead revision (otherwise it'll get stuck in incoming changes forever - it's considered a deletion and
- // the file is never actually deleted)
- continue;
- }
- String branchName = getBranchName(revision, log.getSymbolicNames());
- revisionWrappers.add(new RevisionWrapper(stripAttic(file), revision, branchName));
- }
- }
+ final RevisionWrapper revisionWrapper = revisionWrapperFromLog(log);
+ if (revisionWrapper != null) {
+ revisionWrappers.add(revisionWrapper);
}
}
import com.intellij.openapi.vcs.versionBrowser.ChangesBrowserSettingsEditor;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.AsynchConsumer;
+import com.intellij.util.Consumer;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
return loadCommittedChanges(settings, cvsLocation.getModuleName(), cvsLocation.getEnvironment(), cvsLocation.getRootFile());
}
+ public void loadCommittedChanges(ChangeBrowserSettings settings,
+ RepositoryLocation location,
+ int maxCount,
+ final AsynchConsumer<CommittedChangeList> consumer)
+ throws VcsException {
+ try {
+ CvsRepositoryLocation cvsLocation = (CvsRepositoryLocation) location;
+ final String module = cvsLocation.getModuleName();
+ final CvsEnvironment connectionSettings = cvsLocation.getEnvironment();
+ if (connectionSettings.isOffline()) {
+ return;
+ }
+ final CvsChangeListsBuilder builder = new CvsChangeListsBuilder(module, connectionSettings, myProject, cvsLocation.getRootFile());
+ Date dateTo = settings.getDateBeforeFilter();
+ Date dateFrom = settings.getDateAfterFilter();
+ if (dateFrom == null) {
+ final Calendar calendar = Calendar.getInstance();
+ calendar.set(1970, 2, 2);
+ dateFrom = calendar.getTime();
+ }
+ final ChangeBrowserSettings.Filter filter = settings.createFilter();
+ final CvsResult executionResult = runRLogOperation(connectionSettings, module, dateFrom, dateTo, new Consumer<LogInformationWrapper>() {
+ public void consume(LogInformationWrapper wrapper) {
+ final RevisionWrapper revisionWrapper = builder.revisionWrapperFromLog(wrapper);
+ final CvsChangeList changeList = builder.addRevision(revisionWrapper);
+ if (filter.accepts(changeList)) {
+ consumer.consume(changeList);
+ }
+ }
+ });
+
+ if (executionResult.isCanceled()) {
+ throw new ProcessCanceledException();
+ }
+ else if (!executionResult.hasNoErrors()) {
+ throw executionResult.composeError();
+ }
+ }
+ finally {
+ consumer.finished();
+ }
+ }
+
private List<CvsChangeList> loadCommittedChanges(final ChangeBrowserSettings settings,
final String module,
final CvsEnvironment connectionSettings,
}
}
+ private CvsResult runRLogOperation(final CvsEnvironment settings,
+ final String module,
+ final Date dateFrom,
+ final Date dateTo,
+ final Consumer<LogInformationWrapper> consumer) {
+ final CvsResult executionResult = runRLogOperationImpl(settings, module, dateFrom, dateTo, consumer);
+
+ for (VcsException error : executionResult.getErrors()) {
+ for (String message : error.getMessages()) {
+ if (message.indexOf(INVALID_OPTION_S) >= 0) {
+ LoadHistoryOperation.doesNotSuppressEmptyHeaders(settings);
+ // try only once
+ return runRLogOperationImpl(settings, module, dateFrom, dateTo, consumer);
+ }
+ }
+ }
+ return executionResult;
+ }
+
+ private CvsResult runRLogOperationImpl(final CvsEnvironment settings,
+ final String module,
+ final Date dateFrom,
+ final Date dateTo,
+ final Consumer<LogInformationWrapper> consumer) {
+ LoadHistoryOperation operation = new LoadHistoryOperation(settings, module, dateFrom, dateTo, null) {
+ @Override
+ protected void wrapperAdded(final LogInformationWrapper wrapper) {
+ consumer.consume(wrapper);
+ }
+ };
+
+ CvsOperationExecutor executor = new CvsOperationExecutor(myProject);
+ executor.performActionSync(new CommandCvsHandler(CvsBundle.message("browse.changes.load.history.progress.title"), operation),
+ CvsOperationExecutorCallback.EMPTY);
+
+ return executor.getResult();
+ }
+
private CvsResult runRLogOperation(final CvsEnvironment settings,
final String module,
final Date dateFrom,
public LoadHistoryOperation(CvsEnvironment environment, String module,
@NotNull Date dateFrom,
@Nullable Date dateTo,
- final List<LogInformationWrapper> log) {
+ @Nullable final List<LogInformationWrapper> log) {
super(environment);
- myLog = log;
+ myLog = log == null ? new ArrayList<LogInformationWrapper>() : log;
myModule = module;
myDateFrom = dateFrom;
myDateTo = dateTo;
LogInformationWrapper wrapper = LogInformationWrapper.wrap(myEnvironment.getRepository(), logInfo);
if (wrapper != null) {
myLog.add(wrapper);
+ wrapperAdded(wrapper);
}
}
}
+ protected void wrapperAdded(final LogInformationWrapper wrapper) {
+ }
+
public boolean runInReadThread() {
return false;
}
return getPossibleBase(file, n - 1, path);
}
- public static List<CommittedChangeList> getLocalCommittedChanges(final Project project,
+ public static void getLocalCommittedChanges(final Project project,
final VirtualFile root,
- final Consumer<GitSimpleHandler> parametersSpecifier)
+ final Consumer<GitSimpleHandler> parametersSpecifier,
+ final Consumer<CommittedChangeList> consumer)
throws VcsException {
final List<CommittedChangeList> rc = new ArrayList<CommittedChangeList>();
StringScanner s = new StringScanner(output);
while (s.hasMoreData() && s.startsWith('\u000C')) {
s.nextLine();
- rc.add(GitChangeUtils.parseChangeList(project, root, s));
+ consumer.consume(GitChangeUtils.parseChangeList(project, root, s));
}
if (s.hasMoreData()) {
throw new IllegalStateException("More input is avaialble: " + s.line());
}
+ }
+
+ public static List<CommittedChangeList> getLocalCommittedChanges(final Project project,
+ final VirtualFile root,
+ final Consumer<GitSimpleHandler> parametersSpecifier)
+ throws VcsException {
+ final List<CommittedChangeList> rc = new ArrayList<CommittedChangeList>();
+
+ getLocalCommittedChanges(project, root, parametersSpecifier, new Consumer<CommittedChangeList>() {
+ public void consume(CommittedChangeList committedChangeList) {
+ rc.add(committedChangeList);
+ }
+ });
+
return rc;
}
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.AsynchConsumer;
import com.intellij.util.Consumer;
import git4idea.GitBranch;
import git4idea.GitRemote;
import java.io.DataOutput;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
return null;
}
+ public void loadCommittedChanges(ChangeBrowserSettings settings,
+ RepositoryLocation location,
+ int maxCount,
+ AsynchConsumer<CommittedChangeList> consumer)
+ throws VcsException {
+ try {
+ getCommittedChangesImpl(settings, location, maxCount, consumer);
+ }
+ finally {
+ consumer.finished();
+ }
+ }
+
/**
* {@inheritDoc}
*/
public List<CommittedChangeList> getCommittedChanges(ChangeBrowserSettings settings, RepositoryLocation location, final int maxCount)
throws VcsException {
+
+ final List<CommittedChangeList> result = new ArrayList<CommittedChangeList>();
+
+ getCommittedChangesImpl(settings, location, maxCount, new Consumer<CommittedChangeList>() {
+ public void consume(CommittedChangeList committedChangeList) {
+ result.add(committedChangeList);
+ }
+ });
+
+ return result;
+ }
+
+ private void getCommittedChangesImpl(ChangeBrowserSettings settings, RepositoryLocation location, final int maxCount,
+ final Consumer<CommittedChangeList> consumer)
+ throws VcsException {
GitRepositoryLocation l = (GitRepositoryLocation)location;
final Long beforeRev = settings.getChangeBeforeFilter();
final Long afterRev = settings.getChangeBeforeFilter();
throw new VcsException("The repository does not exists anymore: " + l.getRoot());
}
- return GitUtil.getLocalCommittedChanges(myProject, root, new Consumer<GitSimpleHandler>() {
+ GitUtil.getLocalCommittedChanges(myProject, root, new Consumer<GitSimpleHandler>() {
public void consume(GitSimpleHandler h) {
if (!StringUtil.isEmpty(author)) {
h.addParameters("--author=" + author);
h.addParameters(GitUtil.formatLongRev(afterRev) + "..");
}
}
- });
+ }, consumer);
}
-
/**
* {@inheritDoc}
*/
import com.intellij.openapi.vcs.versionBrowser.ChangesBrowserSettingsEditor;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.AsynchConsumer;
import com.intellij.util.Consumer;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.messages.MessageBusConnection;
}
}
+ public void loadCommittedChanges(ChangeBrowserSettings settings,
+ RepositoryLocation location,
+ int maxCount,
+ final AsynchConsumer<CommittedChangeList> consumer)
+ throws VcsException {
+ try {
+ final SvnRepositoryLocation svnLocation = (SvnRepositoryLocation) location;
+ final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
+ if (progress != null) {
+ progress.setText(SvnBundle.message("progress.text.changes.collecting.changes"));
+ progress.setText2(SvnBundle.message("progress.text2.changes.establishing.connection", location));
+ }
+
+ final String repositoryRoot;
+ try {
+ final SVNRepository repository = myVcs.createRepository(svnLocation.getURL());
+ repositoryRoot = repository.getRepositoryRoot(true).toString();
+ repository.closeSession();
+ }
+ catch (SVNException e) {
+ throw new VcsException(e);
+ }
+
+ final ChangeBrowserSettings.Filter filter = settings.createFilter();
+
+ getCommittedChangesImpl(settings, svnLocation.getURL(), new String[]{""}, maxCount, new Consumer<SVNLogEntry>() {
+ public void consume(final SVNLogEntry svnLogEntry) {
+ final SvnChangeList cl = new SvnChangeList(myVcs, svnLocation, svnLogEntry, repositoryRoot);
+ if (filter.accepts(cl)) {
+ consumer.consume(cl);
+ }
+ }
+ });
+ }
+ finally {
+ consumer.finished();
+ }
+ }
+
public List<SvnChangeList> getCommittedChanges(ChangeBrowserSettings settings, final RepositoryLocation location, final int maxCount) throws VcsException {
final SvnRepositoryLocation svnLocation = (SvnRepositoryLocation) location;
final ArrayList<SvnChangeList> result = new ArrayList<SvnChangeList>();
revisionAfter = SVNRevision.create(1);
}
+ // todo log in committed provider
logger.doLog(SVNURL.parseURIEncoded(url), filterUrls, revisionBefore, revisionBefore, revisionAfter,
settings.STOP_ON_COPY, true, maxCount,
new ISVNLogEntryHandler() {
public SvnCommittedChangesTableModel(final SvnRepositoryLocation location, final Project project, final VirtualFile vcsRoot,
final ChangeListColumn[] columns) throws VcsException {
- super(new ArrayList<CommittedChangeList>(), columns);
+ super(new ArrayList<CommittedChangeList>(), columns, false);
myMediator = new SvnRevisionsNavigationMediator(location, project, vcsRoot);
setItems(myMediator.getCurrent());
}
SVNLogClient client = myVcs.createLogClient();
final boolean supports15 = SvnUtil.checkRepositoryVersion15(myVcs, root);
supports15Ref.set(supports15);
+ // todo log in history provider
client.doLog(myURL, new String[] {}, SVNRevision.UNDEFINED, SVNRevision.HEAD, SVNRevision.create(1), false, true, supports15, 0, null,
new RepositoryLogEntryHandler(url, SVNRevision.UNDEFINED, relativeUrl, result));
}