SVN: svn tree conflicts are show in details pane; accept theirs, accept mine variants; tests for all conflict types

This commit is contained in:
irengrig
2012-05-10 17:38:45 +04:00
parent e880417be2
commit 2c4ee95b5f
49 changed files with 3666 additions and 373 deletions
@@ -229,6 +229,11 @@ public class InitialConfigurationDialog extends DialogWrapper {
@Override
public void dataChanged() {}
@Override
public boolean isStillValid(Object o) {
return false;
}
@Override
public void refresh() {
updateColorSchemePreview(false);
@@ -31,21 +31,31 @@ import java.awt.*;
public abstract class PanelWithActionsAndCloseButton extends JPanel implements DataProvider {
protected final ContentManager myContentManager;
private final String myHelpId;
private final boolean myVerticalToolbar;
private boolean myCloseEnabled;
private final DefaultActionGroup myToolbarGroup = new DefaultActionGroup(null, false);
public PanelWithActionsAndCloseButton(@NotNull ContentManager contentManager, @NonNls String helpId) {
public PanelWithActionsAndCloseButton(ContentManager contentManager, @NonNls String helpId) {
this(contentManager, helpId, true);
}
public PanelWithActionsAndCloseButton(ContentManager contentManager, @NonNls String helpId, final boolean verticalToolbar) {
super(new BorderLayout());
myContentManager = contentManager;
myHelpId = helpId;
myVerticalToolbar = verticalToolbar;
myCloseEnabled = true;
myContentManager.addContentManagerListener(new ContentManagerAdapter(){
public void contentRemoved(ContentManagerEvent event) {
if (event.getContent().getComponent() == PanelWithActionsAndCloseButton.this) {
dispose();
myContentManager.removeContentManagerListener(this);
if (myContentManager != null) {
myContentManager.addContentManagerListener(new ContentManagerAdapter(){
public void contentRemoved(ContentManagerEvent event) {
if (event.getContent().getComponent() == PanelWithActionsAndCloseButton.this) {
dispose();
myContentManager.removeContentManagerListener(this);
}
}
}
});
});
}
}
@@ -53,18 +63,26 @@ public abstract class PanelWithActionsAndCloseButton extends JPanel implements D
return myHelpId;
}
protected void disableClose() {
myCloseEnabled = false;
}
protected void init(){
addActionsTo(myToolbarGroup);
myToolbarGroup.add(new MyCloseAction());
myToolbarGroup.add(ActionManager.getInstance().getAction(IdeActions.ACTION_CONTEXT_HELP));
ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.FILEHISTORY_VIEW_TOOLBAR, myToolbarGroup, false);
ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.FILEHISTORY_VIEW_TOOLBAR, myToolbarGroup, ! myVerticalToolbar);
JComponent centerPanel = createCenterPanel();
toolbar.setTargetComponent(centerPanel);
add(toolbar.getComponent(), BorderLayout.WEST);
add(centerPanel, BorderLayout.CENTER);
if (myVerticalToolbar) {
add(toolbar.getComponent(), BorderLayout.WEST);
} else {
add(toolbar.getComponent(), BorderLayout.NORTH);
}
}
public Object getData(String dataId) {
@@ -81,11 +99,18 @@ public abstract class PanelWithActionsAndCloseButton extends JPanel implements D
protected void dispose() {}
private class MyCloseAction extends CloseTabToolbarAction {
@Override
public void update(AnActionEvent e) {
super.update(e);
e.getPresentation().setVisible(myCloseEnabled);
}
public void actionPerformed(AnActionEvent e) {
Content content = myContentManager.getContent(PanelWithActionsAndCloseButton.this);
if (content != null) {
myContentManager.removeContent(content, true);
if (myContentManager != null) {
Content content = myContentManager.getContent(PanelWithActionsAndCloseButton.this);
if (content != null) {
myContentManager.removeContent(content, true);
}
}
}
}
@@ -73,6 +73,8 @@ public class DualView extends JPanel {
private final Storage.PropertiesComponentStorage myTreeStorage;
private final PropertyChangeListener myPropertyChangeListener;
private boolean myZipByHeight;
public DualView(Object root, DualViewColumnInfo[] columns, @NonNls String columnServiceKey, Project project) {
super(new CardLayout());
@@ -484,4 +486,22 @@ public class DualView extends JPanel {
return result;
}
}
@Override
public Dimension getPreferredSize() {
final Dimension was = super.getPreferredSize();
if (! myZipByHeight) return was;
final int tableHeight = myFlatView.getTableHeader().getHeight() + myFlatView.getTableViewModel().getRowCount() *
myFlatView.getRowHeight();
return new Dimension(was.width, tableHeight);
}
@Override
public Dimension getMinimumSize() {
return myZipByHeight ? getPreferredSize() : super.getMinimumSize();
}
public void setZipByHeight(boolean zipByHeight) {
myZipByHeight = zipByHeight;
}
}
@@ -113,11 +113,12 @@ public class TableView<Item> extends BaseTableView implements ItemsProvider, Sel
column.setPreferredWidth(width);
column.setMinWidth(width);
}
else if ((maxStringValue = columnInfo.getMaxStringValue()) != null) {
else if ((maxStringValue = columnInfo.getMaxStringValue(this)) != null) {
int width = getFontMetrics(getFont()).stringWidth(maxStringValue) + columnInfo.getAdditionalWidth();
width = Math.max(width, headerSize.width);
column.setPreferredWidth(width);
column.setMaxWidth(width);
column.setMinWidth(width);
}
else if ((preferredValue = columnInfo.getPreferredStringValue()) != null) {
int width = getFontMetrics(getFont()).stringWidth(preferredValue) + columnInfo.getAdditionalWidth();
@@ -9,10 +9,11 @@ import javax.swing.*;
* Date: 8/12/11
* Time: 6:47 PM
*/
public interface RefreshablePanel<T> extends Disposable {
public interface RefreshablePanel<Data> extends Disposable {
boolean refreshDataSynch();
void dataChanged();
void refresh();
JPanel getPanel();
void away();
boolean isStillValid(Data data);
}
@@ -0,0 +1,97 @@
/*
* Copyright 2000-2012 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;
import com.intellij.openapi.util.Disposer;
import com.intellij.ui.components.JBTabbedPane;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 4/25/12
* Time: 4:53 PM
*/
public class TabbedRefreshablePanel implements RefreshablePanel {
private final JBTabbedPane myPane;
private final JPanel myPanel;
private final List<RefreshablePanel> myPanels;
public TabbedRefreshablePanel() {
myPanels = new ArrayList<RefreshablePanel>();
myPane = new JBTabbedPane();
myPanel = new JPanel(new BorderLayout());
myPanel.add(myPane, BorderLayout.CENTER);
}
public void addTab(final String title, final RefreshablePanel panel) {
myPanels.add(panel);
myPane.add(title, panel.getPanel());
}
@Override
public boolean refreshDataSynch() {
for (RefreshablePanel panel : myPanels) {
if (! panel.refreshDataSynch()) return false;
}
return true;
}
@Override
public boolean isStillValid(Object o) {
for (RefreshablePanel panel : myPanels) {
if (! panel.isStillValid(o)) return false;
}
return true;
}
@Override
public void dataChanged() {
for (RefreshablePanel panel : myPanels) {
panel.dataChanged();
}
}
@Override
public void refresh() {
for (RefreshablePanel panel : myPanels) {
panel.refresh();
}
}
@Override
public JPanel getPanel() {
return myPanel;
}
@Override
public void away() {
for (RefreshablePanel panel : myPanels) {
panel.away();
}
}
@Override
public void dispose() {
for (RefreshablePanel panel : myPanels) {
Disposer.dispose(panel);
}
}
}
@@ -42,6 +42,7 @@
interface="com.intellij.openapi.vcs.actions.VcsQuickListContentProvider"/>
<extensionPoint name="patch.extension" interface="com.intellij.openapi.diff.impl.patch.PatchEP" area="IDEA_PROJECT"/>
<extensionPoint name="vcsChangesViewRefresher" interface="com.intellij.openapi.vcs.changes.ChangesViewRefresher"/>
<extensionPoint name="vcschangedetails" interface="com.intellij.openapi.vcs.changes.VcsChangeDetailsProvider" area="IDEA_PROJECT"/>
</extensionPoints>
@@ -39,6 +39,9 @@ import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
import com.intellij.testFramework.fixtures.TestFixtureBuilder;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import com.intellij.util.containers.Convertor;
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
@@ -62,57 +65,8 @@ public abstract class AbstractVcsTestCase {
protected IdeaProjectTestFixture myProjectFixture;
protected boolean myInitChangeListManager = true;
protected ProcessOutput runClient(String exeName, @Nullable String stdin, @Nullable final File workingDir, String[] commandLine) throws IOException {
final List<String> arguments = new ArrayList<String>();
final File client = new File(myClientBinaryPath, SystemInfo.isWindows ? exeName + ".exe" : exeName);
if (client.exists()) {
arguments.add(client.toString());
}
else {
// assume client is in path
arguments.add(exeName);
}
Collections.addAll(arguments, commandLine);
if (myTraceClient) {
System.out.println("*** running:\n" + arguments);
if (StringUtil.isNotEmpty(stdin)) {
System.out.println("*** stdin:\n" + stdin);
}
}
final ProcessBuilder builder = new ProcessBuilder().command(arguments);
if (workingDir != null) {
builder.directory(workingDir);
}
Process clientProcess = builder.start();
if (stdin != null) {
OutputStream outputStream = clientProcess.getOutputStream();
try {
byte[] bytes = stdin.getBytes();
outputStream.write(bytes);
}
finally {
outputStream.close();
}
}
CapturingProcessHandler handler = new CapturingProcessHandler(clientProcess, CharsetToolkit.getDefaultSystemCharset());
ProcessOutput result = handler.runProcess(60*1000);
if (myTraceClient || result.isTimeout()) {
System.out.println("*** result: " + result.getExitCode());
final String out = result.getStdout().trim();
if (out.length() > 0) {
System.out.println("*** output:\n" + out);
}
final String err = result.getStderr().trim();
if (err.length() > 0) {
System.out.println("*** error:\n" + err);
}
}
if (result.isTimeout()) {
throw new RuntimeException("Timeout waiting for VCS client to finish execution");
}
return result;
protected TestClientRunner createClientRunner() {
return new TestClientRunner(myTraceClient, myClientBinaryPath);
}
public void setVcsMappings(VcsDirectoryMapping... mappings) {
@@ -221,6 +175,25 @@ public abstract class AbstractVcsTestCase {
return result.get();
}
protected void clearDirInCommand(final VirtualFile dir, final Processor<VirtualFile> filter) {
new WriteCommandAction.Simple(myProject) {
@Override
protected void run() throws Throwable {
try {
final VirtualFile[] children = dir.getChildren();
for (VirtualFile child : children) {
if (filter != null && filter.process(child)) {
child.delete(null);
}
}
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
}.execute();
}
protected void tearDownProject() throws Exception {
if (myProject != null) {
((ProjectComponent) VcsDirtyScopeManager.getInstance(myProject)).projectClosed();
@@ -0,0 +1,100 @@
/*
* Copyright 2000-2012 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.testFramework;
import com.intellij.execution.process.CapturingProcessHandler;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 5/2/12
* Time: 4:51 PM
*/
public class TestClientRunner {
protected boolean myTraceClient = false;
protected File myClientBinaryPath;
public TestClientRunner(boolean traceClient, File clientBinaryPath) {
myTraceClient = traceClient;
myClientBinaryPath = clientBinaryPath;
}
public ProcessOutput runClient(String exeName, @Nullable String stdin, @Nullable final File workingDir, String[] commandLine) throws
IOException {
final List<String> arguments = new ArrayList<String>();
final File client = new File(myClientBinaryPath, SystemInfo.isWindows ? exeName + ".exe" : exeName);
if (client.exists()) {
arguments.add(client.toString());
}
else {
// assume client is in path
arguments.add(exeName);
}
Collections.addAll(arguments, commandLine);
if (myTraceClient) {
System.out.println("*** running:\n" + arguments);
if (StringUtil.isNotEmpty(stdin)) {
System.out.println("*** stdin:\n" + stdin);
}
}
final ProcessBuilder builder = new ProcessBuilder().command(arguments);
if (workingDir != null) {
builder.directory(workingDir);
}
Process clientProcess = builder.start();
if (stdin != null) {
OutputStream outputStream = clientProcess.getOutputStream();
try {
byte[] bytes = stdin.getBytes();
outputStream.write(bytes);
}
finally {
outputStream.close();
}
}
CapturingProcessHandler handler = new CapturingProcessHandler(clientProcess, CharsetToolkit.getDefaultSystemCharset());
ProcessOutput result = handler.runProcess(60*1000);
if (myTraceClient || result.isTimeout()) {
System.out.println("*** result: " + result.getExitCode());
final String out = result.getStdout().trim();
if (out.length() > 0) {
System.out.println("*** output:\n" + out);
}
final String err = result.getStderr().trim();
if (err.length() > 0) {
System.out.println("*** error:\n" + err);
}
}
if (result.isTimeout()) {
throw new RuntimeException("Timeout waiting for VCS client to finish execution");
}
return result;
}
}
@@ -93,7 +93,7 @@ public abstract class ColumnInfo <Item, Aspect> {
}
@Nullable
public String getMaxStringValue() {
public String getMaxStringValue(JTable table) {
return null;
}
@@ -69,6 +69,10 @@ public class GenericDetailsLoader<Id, Data> implements Details<Id,Data>, Disposa
myValueConsumer.consume(id, data);
}
public void resetValueConsumer() {
myValueConsumer.reset();
}
@CalledInAny
@Override
public Id getCurrentlySelected() {
@@ -51,4 +51,8 @@ public class ValueConsumer<Id, Data> {
myId = id;
mySetId = null;
}
public void reset() {
mySetId = null;
}
}
@@ -89,6 +89,7 @@ public final class VcsConfiguration implements PersistentStateComponent<Element>
public Boolean SHOW_PATCH_IN_EXPLORER = null;
public boolean SHOW_FILE_HISTORY_DETAILS = true;
public boolean SHOW_VCS_ERROR_NOTIFICATIONS = true;
public boolean CHANGE_DETAILS_ON = false;
public enum StandardOption {
ADD(VcsBundle.message("vcs.command.name.add")),
@@ -95,6 +95,10 @@ public class Change {
return myOtherLayers;
}
public boolean isTreeConflict() {
return false;
}
public boolean hasOtherLayers() {
return ! myOtherLayers.isEmpty();
}
@@ -158,6 +158,11 @@ public class SelectFilesToAddTextsToPatchPanel implements RefreshablePanel {
return false;
}
@Override
public boolean isStillValid(Object o) {
return false;
}
@Override
public JPanel getPanel() {
if (myPanel == null) {
@@ -91,6 +91,10 @@ public class PatchApplier<BinaryType extends FilePatch> {
});
}
public void setIgnoreContentRootsCheck() {
myVerifier.setIgnoreContentRootsCheck(true);
}
public PatchApplier(final Project project, final VirtualFile baseDirectory, final List<FilePatch> patches,
final LocalChangeList targetChangeList, final CustomBinaryPatchApplier<BinaryType> customForBinaries,
final CommitContext commitContext) {
@@ -55,6 +55,7 @@ public class PathsVerifier<BinaryType extends FilePatch> {
private DelayedPrecheckContext myDelayedPrecheckContext;
private List<FilePath> myAddedPaths;
private List<FilePath> myDeletedPaths;
private boolean myIgnoreContentRootsCheck;
public PathsVerifier(final Project project, final VirtualFile baseDirectory, final List<FilePatch> patches, BaseMapper baseMapper) {
myProject = project;
@@ -314,6 +315,7 @@ public class PathsVerifier<BinaryType extends FilePatch> {
}
protected boolean checkModificationValid(final VirtualFile file, final String name) {
if (ApplicationManager.getApplication().isUnitTestMode() && myIgnoreContentRootsCheck) return true;
// security check to avoid overwriting system files with a patch
if ((file == null) || (!inContent(file)) || (myVcsManager.getVcsRootFor(file) == null)) {
setErrorMessage("File to patch found outside content root: " + name);
@@ -587,4 +589,8 @@ public class PathsVerifier<BinaryType extends FilePatch> {
return mySkipDeleted.keySet();
}
}
public void setIgnoreContentRootsCheck(boolean ignoreContentRootsCheck) {
myIgnoreContentRootsCheck = ignoreContentRootsCheck;
}
}
@@ -43,7 +43,7 @@ import javax.swing.*;
* Date: 9/7/11
* Time: 3:13 PM
*/
public abstract class AbstractRefreshablePanel<T> implements RefreshablePanel {
public abstract class AbstractRefreshablePanel<T> implements RefreshablePanel<Change> {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.AbstractRefreshablePanel");
protected final Ticket myTicket;
private final DetailsPanel myDetailsPanel;
@@ -124,6 +124,11 @@ public abstract class AbstractRefreshablePanel<T> implements RefreshablePanel {
return myDetailsPanel.getPanel();
}
@Override
public boolean isStillValid(Change data) {
return true;
}
private class Loader extends ModalityIgnorantBackgroundableTask {
private final Ticket myTicketCopy;
private T myT;
@@ -59,7 +59,7 @@ public class FragmentedDiffRequestFromChange {
}
public static boolean canCreateRequest(Change change) {
if (ChangesUtil.isTextConflictingChange(change)) return false;
if (ChangesUtil.isTextConflictingChange(change) || change.isTreeConflict()) return false;
if (ShowDiffAction.isBinaryChange(change)) return false;
final FilePath filePath = ChangesUtil.getFilePath(change);
if (filePath.isDirectory()) return false;
@@ -38,7 +38,7 @@ import javax.swing.*;
* Date: 8/17/11
* Time: 7:08 PM
*/
public class ShortDiffDetails implements RefreshablePanel, Disposable {
public class ShortDiffDetails implements RefreshablePanel<Change>, Disposable {
private final Project myProject;
private final VcsChangeDetailsManager myVcsChangeDetailsManager;
private final Getter<Change[]> myMaster;
@@ -66,6 +66,11 @@ public class ShortDiffDetails implements RefreshablePanel, Disposable {
};
}
@Override
public boolean isStillValid(Change change) {
return true;
}
@Override
public boolean refreshDataSynch() {
Change selected = myDetailsLoader.getCurrentlySelected();
@@ -150,7 +155,8 @@ public class ShortDiffDetails implements RefreshablePanel, Disposable {
myDetailsCache.put(filePath, pair);
} else if (old != pair) {
if (pair != null) {
Disposer.dispose(pair);
myDetailsCache.put(filePath, pair);
Disposer.dispose(old);
}
}
}
@@ -174,6 +180,11 @@ public class ShortDiffDetails implements RefreshablePanel, Disposable {
final FilePath filePath = ChangesUtil.getFilePath(change);
RefreshablePanel details = myDetailsCache.get(filePath);
if (details != null && ! details.isStillValid(change)) {
Disposer.dispose(details);
details = null;
myDetailsLoader.resetValueConsumer();
}
if (details != null) {
myDetailsConsumer.consume(change, details);
} else {
@@ -24,9 +24,11 @@ import com.intellij.openapi.diff.DiffPanel;
import com.intellij.openapi.diff.ex.DiffPanelEx;
import com.intellij.openapi.diff.ex.DiffPanelOptions;
import com.intellij.openapi.diff.impl.DiffPanelImpl;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.progress.BackgroundTaskQueue;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.VcsKey;
@@ -41,6 +43,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -51,7 +54,7 @@ import java.util.Map;
* Time: 5:36 PM
*/
public class VcsChangeDetailsManager {
private final Map<VcsKey, VcsChangeDetailsProvider> myProviderMap = new HashMap<VcsKey, VcsChangeDetailsProvider>();
private final List<VcsChangeDetailsProvider> myProviders = new ArrayList<VcsChangeDetailsProvider>();
private final List<VcsChangeDetailsProvider> myDedicatedList;
private final Project myProject;
private final BackgroundTaskQueue myQueue;
@@ -61,8 +64,11 @@ public class VcsChangeDetailsManager {
myQueue = new BackgroundTaskQueue(myProject, "Loading change details");
myDedicatedList = new ArrayList<VcsChangeDetailsProvider>();
myDedicatedList.add(new BinaryDetailsProviderNew(project, myQueue));
myDedicatedList.add(new FragmentedDiffDetailsProvider(myProject, myQueue));
myDedicatedList.add(new BinaryDetailsProviderNew(project));
myDedicatedList.add(new FragmentedDiffDetailsProvider(myProject));
VcsChangeDetailsProvider[] extensions = Extensions.getExtensions(VcsChangeDetailsProvider.EP_NAME, myProject);
myProviders.addAll(Arrays.asList(extensions));
Disposer.register(project, new Disposable() {
@Override
@@ -76,16 +82,40 @@ public class VcsChangeDetailsManager {
for (VcsChangeDetailsProvider provider : myDedicatedList) {
if (provider.canComment(change)) return true;
}
for (VcsChangeDetailsProvider provider : myProviders) {
if (provider.canComment(change)) return true;
}
return false;
}
@Nullable
public RefreshablePanel getPanel(final Change change, JComponent parent) {
final List<Pair<String, RefreshablePanel>> panels = new ArrayList<Pair<String, RefreshablePanel>>();
for (VcsChangeDetailsProvider convertor : myDedicatedList) {
if (! convertor.canComment(change)) continue;
RefreshablePanel panel = convertor.comment(change, parent);
RefreshablePanel panel = convertor.comment(change, parent, myQueue);
if (panel != null) {
return panel;
panels.add(new Pair<String, RefreshablePanel>("Diff", panel));
break; // only one of dedicated for now
}
}
for (VcsChangeDetailsProvider provider : myProviders) {
if (provider.canComment(change)) {
RefreshablePanel panel = provider.comment(change, parent, myQueue);
if (panel != null) {
panels.add(new Pair<String, RefreshablePanel>(provider.getName(), panel));
}
}
}
if (! panels.isEmpty()) {
if (panels.size() == 1) {
return panels.get(0).getSecond();
} else {
TabbedRefreshablePanel tabbedRefreshablePanel = new TabbedRefreshablePanel();
for (Pair<String, RefreshablePanel> panel : panels) {
tabbedRefreshablePanel.addTab(panel.getFirst(), panel.getSecond());
}
return tabbedRefreshablePanel;
}
}
return null;
@@ -97,11 +127,9 @@ public class VcsChangeDetailsManager {
private static class BinaryDetailsProviderNew implements VcsChangeDetailsProvider {
private final Project myProject;
private final BackgroundTaskQueue myQueue;
private BinaryDetailsProviderNew(Project project, final BackgroundTaskQueue queue) {
private BinaryDetailsProviderNew(Project project) {
myProject = project;
myQueue = queue;
}
@Override
@@ -111,17 +139,22 @@ public class VcsChangeDetailsManager {
@Override
public boolean canComment(Change change) {
FilePath path = ChangesUtil.getFilePath(change);
if (path != null && path.isDirectory()) return false;
return ShowDiffAction.isBinaryChangeAndCanShow(myProject, change);
return canBeShownInBinaryDiff(change, myProject);
}
@Override
public RefreshablePanel comment(Change change, JComponent parent) {
return new BinaryDiffDetailsPanel(myProject, myQueue, change);
public RefreshablePanel comment(Change change, JComponent parent, BackgroundTaskQueue queue) {
return new BinaryDiffDetailsPanel(myProject, queue, change);
}
}
private static boolean canBeShownInBinaryDiff(Change change, final Project project) {
FilePath path = ChangesUtil.getFilePath(change);
if (path != null && path.isDirectory()) return false;
if (change.isTreeConflict()) return false;
return ShowDiffAction.isBinaryChangeAndCanShow(project, change);
}
private static class BinaryDiffDetailsPanel extends AbstractRefreshablePanel<ValueWithVcsException<List<BeforeAfter<DiffContent>>>> {
private final BinaryDiffRequestFromChange myRequestFromChange;
private final Project myProject;
@@ -144,6 +177,11 @@ public class VcsChangeDetailsManager {
o.setRequestFocusOnNewContent(false);
}
@Override
public boolean isStillValid(Change data) {
return canBeShownInBinaryDiff(data, myProject);
}
@Override
protected void refreshPresentation() {
}
@@ -211,11 +249,9 @@ public class VcsChangeDetailsManager {
private static class FragmentedDiffDetailsProvider implements VcsChangeDetailsProvider {
private final Project myProject;
private final BackgroundTaskQueue myQueue;
private FragmentedDiffDetailsProvider(Project project, final BackgroundTaskQueue queue) {
private FragmentedDiffDetailsProvider(Project project) {
myProject = project;
myQueue = queue;
}
@Override
@@ -229,8 +265,8 @@ public class VcsChangeDetailsManager {
}
@Override
public RefreshablePanel comment(Change change, JComponent parent) {
return new FragmentedDiffDetailsPanel(myProject, myQueue, change, parent);
public RefreshablePanel comment(Change change, JComponent parent, BackgroundTaskQueue queue) {
return new FragmentedDiffDetailsPanel(myProject, queue, change, parent);
}
}
@@ -256,6 +292,11 @@ public class VcsChangeDetailsManager {
myDiffPanel.refreshPresentation();
}
@Override
public boolean isStillValid(Change data) {
return FragmentedDiffRequestFromChange.canCreateRequest(data);
}
@Override
protected ValueWithVcsException<PreparedFragmentedContent> loadImpl() throws VcsException {
return new ValueWithVcsException<PreparedFragmentedContent>() {
@@ -17,6 +17,7 @@ package com.intellij.openapi.vcs.changes;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.progress.BackgroundTaskQueue;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.CalledInAwt;
import com.intellij.openapi.vcs.CalledInBackground;
@@ -36,5 +37,5 @@ public interface VcsChangeDetailsProvider {
@CalledInAwt
boolean canComment(final Change change);
@CalledInAwt
RefreshablePanel comment(final Change change, JComponent parent);
RefreshablePanel comment(final Change change, JComponent parent, BackgroundTaskQueue queue);
}
@@ -72,10 +72,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import javax.swing.table.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreePath;
@@ -109,7 +106,8 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
private final AnnotationProvider myAnnotationProvider;
private VcsHistorySession myHistorySession;
private final FilePath myFilePath;
private final FileHistoryRefresher myRefresher;
private final FileHistoryRefresherI myRefresherI;
private VcsFileRevision myBottomRevisionForShowDiff;
private final DualView myDualView;
private final Alarm myUpdateAlarm;
@@ -122,6 +120,7 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
@NonNls private static final String VCS_HISTORY_ACTIONS_GROUP = "VcsHistoryActionsGroup";
private final Map<VcsRevisionNumber, Integer> myRevisionsOrder;
private boolean myIsStaticAndEmbedded;
private final Comparator<VcsFileRevision> myRevisionsInOrderComparator = new Comparator<VcsFileRevision>() {
@Override
@@ -151,6 +150,11 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
public String getPreferredStringValue() {
return "123.4567";
}
@Override
public String getMaxStringValue(JTable table) {
return getMaxValue(getName(), table);
}
};
private static final DualViewColumnInfo DATE = new VcsColumnInfo<String>(VcsBundle.message("column.name.revision.date")) {
@@ -168,6 +172,11 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
public String getPreferredStringValue() {
return DateFormatUtil.formatPrettyDateTime(Clock.getTime());
}
@Override
public String getMaxStringValue(JTable table) {
return getMaxValue(getName(), table);
}
};
private final Splitter myDetailsSplitter = new Splitter(false, 0.5f);
@@ -254,6 +263,11 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
public String getPreferredStringValue() {
return "author_author";
}
@Override
public String getMaxStringValue(JTable table) {
return getMaxValue(getName(), table);
}
};
private Splitter mySplitter;
@@ -325,6 +339,11 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
public TableCellRenderer getRenderer(VcsFileRevision p0) {
return myRenderer;
}
@Override
public String getMaxStringValue(JTable table) {
return getMaxValue(getName(), table);
}
}
private final Map<VcsFileRevision, VirtualFile> myRevisionToVirtualFile = new HashMap<VcsFileRevision, VirtualFile>();
@@ -332,12 +351,20 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
public FileHistoryPanelImpl(AbstractVcs vcs,
FilePath filePath, VcsHistorySession session,
VcsHistoryProvider provider,
ContentManager contentManager, final FileHistoryRefresher refresher) {
super(contentManager, provider.getHelpId() != null ? provider.getHelpId() : "reference.versionControl.toolwindow.history");
ContentManager contentManager, final FileHistoryRefresherI refresherI) {
this(vcs, filePath, session, provider, contentManager, refresherI, false);
}
public FileHistoryPanelImpl(AbstractVcs vcs,
FilePath filePath, VcsHistorySession session,
VcsHistoryProvider provider,
ContentManager contentManager, final FileHistoryRefresherI refresherI, final boolean isStaticEmbedded) {
super(contentManager, provider.getHelpId() != null ? provider.getHelpId() : "reference.versionControl.toolwindow.history", ! isStaticEmbedded);
myIsStaticAndEmbedded = false;
myVcs = vcs;
myProvider = provider;
myAnnotationProvider = myVcs.getCachingAnnotationProvider();
myRefresher = refresher;
myRefresherI = refresherI;
myHistorySession = session;
myFilePath = filePath;
@@ -373,6 +400,9 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
listener.install(myDualView.getTreeView());
createDualView();
if (isStaticEmbedded) {
setIsStaticAndEmbedded(isStaticEmbedded);
}
myPopupActions = createPopupActions();
@@ -521,6 +551,7 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
wrapWithTreeElements(myHistorySession.getRevisionList())), myTargetSelection);
}
myDualView.getFlatView().updateColumnSizes();
myDualView.expandAll();
myDualView.repaint();
}
@@ -689,7 +720,7 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
}
private void setupDetails() {
boolean showDetails = getConfiguration().SHOW_FILE_HISTORY_DETAILS;
boolean showDetails = ! myIsStaticAndEmbedded && getConfiguration().SHOW_FILE_HISTORY_DETAILS;
if (showDetails) {
myDualView.setViewBorder(IdeBorderFactory.createBorder(SideBorder.LEFT | SideBorder.BOTTOM));
}
@@ -717,7 +748,7 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
getConfiguration().FILE_HISTORY_SPLITTER_PROPORTION = newProportion.floatValue();
}
private float getSplitterProportion() {
protected float getSplitterProportion() {
return getConfiguration().FILE_HISTORY_SPLITTER_PROPORTION;
}
@@ -779,18 +810,20 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
}
}
result.add(new RefreshFileHistoryAction());
result.add(new ToggleAction("Show Details", "Display details panel", IconLoader.getIcon("/actions/showSource.png")) {
@Override
public boolean isSelected(AnActionEvent e) {
return getConfiguration().SHOW_FILE_HISTORY_DETAILS;
}
if (! myIsStaticAndEmbedded) {
result.add(new ToggleAction("Show Details", "Display details panel", IconLoader.getIcon("/actions/showSource.png")) {
@Override
public boolean isSelected(AnActionEvent e) {
return getConfiguration().SHOW_FILE_HISTORY_DETAILS;
}
@Override
public void setSelected(AnActionEvent e, boolean state) {
getConfiguration().SHOW_FILE_HISTORY_DETAILS = state;
setupDetails();
}
});
@Override
public void setSelected(AnActionEvent e, boolean state) {
getConfiguration().SHOW_FILE_HISTORY_DETAILS = state;
setupDetails();
}
});
}
if (!popup && supportsTree()) {
result.add(new MyShowAsTreeAction());
@@ -809,7 +842,8 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
mySplitter.revalidate();
mySplitter.repaint();
myRefresher.run(true);
myRefresherI.run(true);
myDualView.getFlatView().updateColumnSizes();
}
}.callMe();
}
@@ -855,7 +889,8 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
final int selectedRow = flatView.getSelectedRow();
if (selectedRow == (flatView.getRowCount() - 1)) {
// no previous
showDifferences(myVcs.getProject(), VcsFileRevision.NULL, getFirstSelectedRevision());
showDifferences(myVcs.getProject(), myBottomRevisionForShowDiff != null ? myBottomRevisionForShowDiff : VcsFileRevision.NULL,
getFirstSelectedRevision());
} else {
showDifferences(myVcs.getProject(), flatView.getRow(selectedRow + 1), getFirstSelectedRevision());
}
@@ -1395,7 +1430,7 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
}
}
protected void dispose() {
public void dispose() {
super.dispose();
myDualView.dispose();
myUpdateAlarm.dispose();
@@ -1515,8 +1550,10 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
return myBaseColumn.getEditor(item.myRevision);
}
public String getMaxStringValue() {
return myBaseColumn.getMaxStringValue();
public String getMaxStringValue(JTable table) {
final String superValue = myBaseColumn.getMaxStringValue(table);
if (superValue != null) return superValue;
return getMaxValue(myBaseColumn.getName(), table);
}
public int getAdditionalWidth() {
@@ -1557,6 +1594,34 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
return myFilePath.getVirtualFileParent();
}
private static String getMaxValue(String name, JTable table) {
if (table.getRowCount() == 0) return null;
final Enumeration<TableColumn> columns = table.getColumnModel().getColumns();
int idx = 0;
while (columns.hasMoreElements()) {
TableColumn column = columns.nextElement();
if (name.equals(column.getHeaderValue())) {
break;
}
++ idx;
}
if (idx >= table.getColumnModel().getColumnCount() - 1) return null;
final FontMetrics fm = table.getFontMetrics(table.getFont().deriveFont(Font.BOLD));
final Object header = table.getColumnModel().getColumn(idx).getHeaderValue();
double maxValue = fm.stringWidth((String)header);
String value = (String)header;
for (int i = 0; i < table.getRowCount(); i++) {
final Object at = table.getValueAt(i, idx);
if (at instanceof String) {
final int newWidth = fm.stringWidth((String)at);
if (newWidth > maxValue) {
maxValue = newWidth;
value = (String) at;
}
}
}
return value + "ww";
}
private class MyTreeCellRenderer implements TreeCellRenderer {
private final TreeCellRenderer myDefaultCellRenderer;
@@ -1650,4 +1715,21 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton {
++ cnt;
}
}
public void setIsStaticAndEmbedded(boolean isStaticAndEmbedded) {
myIsStaticAndEmbedded = isStaticAndEmbedded;
myDualView.setZipByHeight(isStaticAndEmbedded);
myDualView.getFlatView().updateColumnSizes();
if (myIsStaticAndEmbedded) {
disableClose();
myDualView.getFlatView().getTableHeader().setBorder(IdeBorderFactory.createBorder(SideBorder.TOP));
myDualView.getTreeView().getTableHeader().setBorder(IdeBorderFactory.createBorder(SideBorder.TOP));
myDualView.getFlatView().setBorder(null);
myDualView.getTreeView().setBorder(null);
}
}
public void setBottomRevisionForShowDiff(VcsFileRevision bottomRevisionForShowDiff) {
myBottomRevisionForShowDiff = bottomRevisionForShowDiff;
}
}
@@ -24,7 +24,7 @@ import com.intellij.openapi.vcs.annotate.AnnotationProvider;
* @author irengrig
* @author Kirill Likhodedov
*/
public class FileHistoryRefresher {
public class FileHistoryRefresher implements FileHistoryRefresherI {
private final FileHistorySessionPartner mySessionPartner;
private final VcsHistoryProvider myVcsHistoryProvider;
private final FilePath myPath;
@@ -47,6 +47,7 @@ public class FileHistoryRefresher {
/**
* @param refresh if true, than this is a refresh. If false, the history is shown for the first time.
*/
@Override
public void run(boolean isRefresh) {
final VcsHistoryProviderBackgroundableProxy proxy = new VcsHistoryProviderBackgroundableProxy(
myVcs, myVcsHistoryProvider, myVcs.getDiffProvider());
@@ -59,6 +60,7 @@ public class FileHistoryRefresher {
* Was the refresher called for the first time or via refresh.
* @return
*/
@Override
public boolean isFirstTime() {
return !myIsRefresh;
}
@@ -0,0 +1,14 @@
package com.intellij.openapi.vcs.history;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 4/27/12
* Time: 11:47 AM
* To change this template use File | Settings | File Templates.
*/
public interface FileHistoryRefresherI {
void run(boolean isRefresh);
boolean isFirstTime();
}
@@ -46,7 +46,7 @@ public class FileHistorySessionPartner implements VcsAppendableHistorySessionPar
private final FilePath myPath;
private final String myRepositoryPath;
private final AbstractVcs myVcs;
private final FileHistoryRefresher myRefresher;
private final FileHistoryRefresherI myRefresherI;
private volatile VcsAbstractHistorySession mySession;
private final BufferedListConsumer<VcsFileRevision> myBuffer;
@@ -54,13 +54,13 @@ public class FileHistorySessionPartner implements VcsAppendableHistorySessionPar
final FilePath path,
final String repositoryPath,
final AbstractVcs vcs,
final FileHistoryRefresher refresher) {
final FileHistoryRefresherI refresherI) {
myVcsHistoryProvider = vcsHistoryProvider;
myAnnotationProvider = annotationProvider;
myPath = path;
myRepositoryPath = repositoryPath;
myVcs = vcs;
myRefresher = refresher;
myRefresherI = refresherI;
myBuffer = new BufferedListConsumer<VcsFileRevision>(5, new Consumer<List<VcsFileRevision>>() {
public void consume(List<VcsFileRevision> vcsFileRevisions) {
mySession.getRevisionList().addAll(vcsFileRevisions);
@@ -83,7 +83,7 @@ public class FileHistorySessionPartner implements VcsAppendableHistorySessionPar
ContentManager contentManager = ProjectLevelVcsManagerEx.getInstanceEx(myVcs.getProject()).getContentManager();
final VcsHistorySession copy = mySession.copyWithCachedRevision();
myFileHistoryPanel = new FileHistoryPanelImpl(myVcs, myPath, copy, myVcsHistoryProvider,
contentManager, myRefresher);
contentManager, myRefresherI);
}
return myFileHistoryPanel;
}
@@ -93,7 +93,7 @@ public class FileHistorySessionPartner implements VcsAppendableHistorySessionPar
if (myFileHistoryPanel == null) {
ContentManager contentManager = ProjectLevelVcsManagerEx.getInstanceEx(myVcs.getProject()).getContentManager();
myFileHistoryPanel = new FileHistoryPanelImpl(myVcs, myPath, copy, myVcsHistoryProvider,
contentManager, myRefresher);
contentManager, myRefresherI);
} else {
myFileHistoryPanel.getHistoryPanelRefresh().consume(copy);
}
@@ -117,7 +117,7 @@ public class FileHistorySessionPartner implements VcsAppendableHistorySessionPar
ToolWindow toolWindow = ToolWindowManager.getInstance(myVcs.getProject()).getToolWindow(ToolWindowId.VCS);
assert toolWindow != null : "Version Control ToolWindow should be available at this point.";
if (myRefresher.isFirstTime()) {
if (myRefresherI.isFirstTime()) {
toolWindow.activate(null);
}
}
@@ -123,8 +123,8 @@ public class AbstractVcsHelperImpl extends AbstractVcsHelper {
public void showFileHistory(final VcsHistoryProvider vcsHistoryProvider, final AnnotationProvider annotationProvider, final FilePath path,
final String repositoryPath, final AbstractVcs vcs) {
final FileHistoryRefresher refresher = new FileHistoryRefresher(vcsHistoryProvider, annotationProvider, path, repositoryPath, vcs);
refresher.run(false);
final FileHistoryRefresherI refresherI = new FileHistoryRefresher(vcsHistoryProvider, annotationProvider, path, repositoryPath, vcs);
refresherI.run(false);
}
public void showRollbackChangesDialog(List<Change> changes) {
@@ -100,7 +100,7 @@ public class MultipleFileMergeDialog extends DialogWrapper {
}
@Override
public String getMaxStringValue() {
public String getMaxStringValue(JTable table) {
return VcsBundle.message("multiple.file.merge.type.binary");
}
@@ -90,7 +90,7 @@ public class CustomizeKeywordSubstitutionDialog extends DialogWrapper {
}
@Override
public String getMaxStringValue() {
public String getMaxStringValue(JTable table) {
return KeywordSubstitutionWrapper.KEYWORD_EXPANSION_LOCKER.toString();
}
};
@@ -118,7 +118,7 @@ public class CustomizeKeywordSubstitutionDialog extends DialogWrapper {
}
@Override
public String getMaxStringValue() {
public String getMaxStringValue(JTable table) {
return getName();
}
};
@@ -40,6 +40,7 @@ import git4idea.i18n.GitBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
@@ -420,7 +421,7 @@ public class GitMergeProvider implements MergeProvider2 {
}
@Override
public String getMaxStringValue() {
public String getMaxStringValue(JTable table) {
return GitBundle.message("merge.tool.column.status.modified");
}
@@ -197,7 +197,7 @@ public class GitCommitListPanel extends JPanel implements TypeSafeDataProvider {
}
@Override
public String getMaxStringValue() {
public String getMaxStringValue(JTable table) {
return myMaxString;
}
@@ -21,6 +21,7 @@ import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.AbstractVcsTestCase;
import com.intellij.testFramework.TestClientRunner;
import com.intellij.ui.GuiUtils;
import com.intellij.util.ui.UIUtil;
import com.intellij.vcsUtil.VcsUtil;
@@ -185,7 +186,7 @@ public abstract class HgTest extends AbstractVcsTestCase {
* @param commandLine command and parameters (e.g. 'status, -m').
*/
protected ProcessOutput runHg(@Nullable File workingDir, String... commandLine) throws IOException {
return runClient(HG_EXECUTABLE, null, workingDir, commandLine);
return createClientRunner().runClient(HG_EXECUTABLE, null, workingDir, commandLine);
}
protected File fillFile(File aParentDir, String[] filePath, String fileContents) throws FileNotFoundException {
+1
View File
@@ -112,6 +112,7 @@
<vcsCheckinHandlerFactory implementation="org.jetbrains.idea.svn.checkin.SvnCheckinHandlerFactory"/>
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
<checkoutProvider implementation="org.jetbrains.idea.svn.checkout.SvnCheckoutProvider"/>
<vcschangedetails implementation="org.jetbrains.idea.svn.treeConflict.TreeConflictDetailsProvider"/>
<applicationService serviceInterface="org.jetbrains.idea.svn.SvnApplicationSettings"
serviceImplementation="org.jetbrains.idea.svn.SvnApplicationSettings"/>
<projectService serviceImplementation="org.jetbrains.idea.svn.SvnConfiguration"/>
@@ -19,11 +19,16 @@ import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ContentRevision;
import org.tmatesoft.svn.core.internal.wc.SVNTreeConflictUtil;
import org.tmatesoft.svn.core.wc.SVNTreeConflictDescription;
import javax.swing.*;
public class ConflictedSvnChange extends Change {
private final ConflictState myConflictState;
// also used if not move/rename
private SVNTreeConflictDescription myBeforeDescription;
private SVNTreeConflictDescription myAfterDescription;
// +-
private final FilePath myTreeConflictMarkHolder;
@@ -35,7 +40,8 @@ public class ConflictedSvnChange extends Change {
}
public ConflictedSvnChange(ContentRevision beforeRevision, ContentRevision afterRevision, FileStatus fileStatus,
final ConflictState conflictState, final FilePath treeConflictMarkHolder) {
final ConflictState conflictState,
final FilePath treeConflictMarkHolder) {
super(beforeRevision, afterRevision, fileStatus);
myConflictState = conflictState;
myTreeConflictMarkHolder = treeConflictMarkHolder;
@@ -45,6 +51,27 @@ public class ConflictedSvnChange extends Change {
return myConflictState;
}
@Override
public boolean isTreeConflict() {
return myConflictState.isTree();
}
public SVNTreeConflictDescription getBeforeDescription() {
return myBeforeDescription;
}
public void setBeforeDescription(SVNTreeConflictDescription beforeDescription) {
myBeforeDescription = beforeDescription;
}
public SVNTreeConflictDescription getAfterDescription() {
return myAfterDescription;
}
public void setAfterDescription(SVNTreeConflictDescription afterDescription) {
myAfterDescription = afterDescription;
}
@Override
public Icon getAdditionalIcon() {
return myConflictState.getIcon();
@@ -54,7 +81,22 @@ public class ConflictedSvnChange extends Change {
public String getDescription() {
final String description = myConflictState.getDescription();
if (description != null) {
return SvnBundle.message("svn.changeview.item.in.conflict.text", description);
final StringBuilder sb = new StringBuilder(SvnBundle.message("svn.changeview.item.in.conflict.text", description));
if (myBeforeDescription != null) {
sb.append('\n');
if (myAfterDescription != null) {
sb.append("before: ");
}
sb.append(SVNTreeConflictUtil.getHumanReadableConflictDescription(myBeforeDescription));
}
if (myAfterDescription != null) {
sb.append('\n');
if (myBeforeDescription != null) {
sb.append("after: ");
}
sb.append(SVNTreeConflictUtil.getHumanReadableConflictDescription(myAfterDescription));
}
return sb.toString();
}
return description;
}
@@ -322,14 +322,26 @@ class SvnChangeProviderContext implements StatusReceiver {
Change createMovedChange(final ContentRevision before, final ContentRevision after, final SVNStatus copiedStatus,
final SVNStatus deletedStatus) throws SVNException {
// todo no convertion needed for the contents status?
return patchWithPropertyChange(new ConflictedSvnChange(before, after, ConflictState.mergeState(getState(copiedStatus), getState(deletedStatus)),
((copiedStatus != null) && (copiedStatus.getTreeConflict() != null)) ? after.getFile() : before.getFile()), copiedStatus, deletedStatus);
final ConflictedSvnChange conflictedSvnChange =
new ConflictedSvnChange(before, after, ConflictState.mergeState(getState(copiedStatus), getState(deletedStatus)),
((copiedStatus != null) && (copiedStatus.getTreeConflict() != null)) ? after.getFile() : before.getFile());
if (deletedStatus != null) {
conflictedSvnChange.setBeforeDescription(deletedStatus.getTreeConflict());
}
if (copiedStatus != null) {
conflictedSvnChange.setAfterDescription(copiedStatus.getTreeConflict());
}
return patchWithPropertyChange(conflictedSvnChange, copiedStatus, deletedStatus);
}
private Change createChange(final ContentRevision before, final ContentRevision after, final FileStatus fStatus, final SVNStatus svnStatus)
throws SVNException {
return patchWithPropertyChange(new ConflictedSvnChange(before, after, correctContentsStatus(fStatus, svnStatus),
getState(svnStatus), after == null ? before.getFile() : after.getFile()), svnStatus, null);
final ConflictedSvnChange conflictedSvnChange = new ConflictedSvnChange(before, after, correctContentsStatus(fStatus, svnStatus),
getState(svnStatus), after == null ? before.getFile() : after.getFile());
if (svnStatus != null) {
conflictedSvnChange.setBeforeDescription(svnStatus.getTreeConflict());
}
return patchWithPropertyChange(conflictedSvnChange, svnStatus, null);
}
private FileStatus correctContentsStatus(final FileStatus fs, final SVNStatus svnStatus) throws SVNException {
@@ -16,7 +16,6 @@
package org.jetbrains.idea.svn.history;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.IconLoader;
@@ -25,7 +24,9 @@ import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.annotate.ShowAllAffectedGenericAction;
import com.intellij.openapi.vcs.changes.ChangesUtil;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.issueLinks.TableLinkMouseListener;
import com.intellij.openapi.vcs.history.*;
import com.intellij.openapi.vfs.VirtualFile;
@@ -43,6 +44,8 @@ import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.*;
import org.tmatesoft.svn.util.SVNLogType;
@@ -58,7 +61,7 @@ import java.util.List;
import java.util.Map;
public class SvnHistoryProvider
implements VcsHistoryProvider, VcsCacheableHistorySessionFactory<Boolean, SvnHistoryProvider.MyHistorySession> {
implements VcsHistoryProvider, VcsCacheableHistorySessionFactory<Boolean, SvnHistorySession> {
private final SvnVcs myVcs;
public SvnHistoryProvider(SvnVcs vcs) {
@@ -73,8 +76,8 @@ public class SvnHistoryProvider
final ColumnInfo[] columns;
final Consumer<VcsFileRevision> listener;
final JComponent addComp;
if (((MyHistorySession)session).isSupports15()) {
final MergeSourceColumnInfo mergeSourceColumn = new MergeSourceColumnInfo((MyHistorySession)session);
if (((SvnHistorySession)session).isSupports15()) {
final MergeSourceColumnInfo mergeSourceColumn = new MergeSourceColumnInfo((SvnHistorySession)session);
columns = new ColumnInfo[]{new CopyFromColumnInfo(), mergeSourceColumn};
final JPanel panel = new JPanel(new BorderLayout());
@@ -119,83 +122,21 @@ public class SvnHistoryProvider
}
@Override
public FilePath getUsedFilePath(MyHistorySession session) {
public FilePath getUsedFilePath(SvnHistorySession session) {
return session.getCommittedPath();
}
@Override
public Boolean getAddinionallyCachedData(MyHistorySession session) {
public Boolean getAddinionallyCachedData(SvnHistorySession session) {
return session.isSupports15();
}
@Override
public MyHistorySession createFromCachedData(Boolean aBoolean,
public SvnHistorySession createFromCachedData(Boolean aBoolean,
@NotNull List<VcsFileRevision> revisions,
@NotNull FilePath filePath,
VcsRevisionNumber currentRevision) {
return new MyHistorySession(revisions, filePath, aBoolean, currentRevision, false);
}
class MyHistorySession extends VcsAbstractHistorySession {
private final FilePath myCommittedPath;
private final boolean mySupports15;
private MyHistorySession(final List<VcsFileRevision> revisions, final FilePath committedPath, final boolean supports15,
@Nullable final VcsRevisionNumber currentRevision, boolean skipRefreshOnStart) {
super(revisions, currentRevision);
myCommittedPath = committedPath;
mySupports15 = supports15;
if (!skipRefreshOnStart) {
shouldBeRefreshed();
}
}
public HistoryAsTreeProvider getHistoryAsTreeProvider() {
return null;
}
@Nullable
public VcsRevisionNumber calcCurrentRevisionNumber() {
if (myCommittedPath == null) {
return null;
}
if (myCommittedPath.isNonLocal()) {
// technically, it does not make sense, since there's no "current" revision for non-local history (if look how it's used)
// but ok, lets keep it for now
return new SvnRevisionNumber(SVNRevision.HEAD);
}
try {
SVNWCClient wcClient = myVcs.createWCClient();
SVNInfo info = wcClient.doInfo(new File(myCommittedPath.getPath()), SVNRevision.UNDEFINED);
if (info != null) {
return new SvnRevisionNumber(info.getCommittedRevision());
}
else {
return null;
}
}
catch (SVNException e) {
return null;
}
}
public FilePath getCommittedPath() {
return myCommittedPath;
}
@Override
public boolean isContentAvailable(final VcsFileRevision revision) {
return !myCommittedPath.isDirectory();
}
public boolean isSupports15() {
return mySupports15;
}
@Override
public VcsHistorySession copy() {
return new MyHistorySession(getRevisionList(), myCommittedPath, mySupports15, getCurrentRevisionNumber(), true);
}
return new SvnHistorySession(myVcs, revisions, filePath, aBoolean, currentRevision, false);
}
@Nullable
@@ -208,14 +149,32 @@ public class SvnHistoryProvider
}
public void reportAppendableHistory(FilePath path, final VcsAppendableHistorySessionPartner partner) throws VcsException {
final FilePath committedPath = ChangesUtil.getCommittedPath(myVcs.getProject(), path);
reportAppendableHistory(path, partner, null, null, 0, null, false);
}
public void reportAppendableHistory(FilePath path, final VcsAppendableHistorySessionPartner partner,
@Nullable final SVNRevision from, @Nullable final SVNRevision to, final int limit,
SVNRevision peg, final boolean forceBackwards) throws VcsException {
FilePath committedPath = path;
Change change = ChangeListManager.getInstance(myVcs.getProject()).getChange(path);
if (change != null) {
final ContentRevision beforeRevision = change.getBeforeRevision();
final ContentRevision afterRevision = change.getAfterRevision();
if (beforeRevision != null && afterRevision != null && !beforeRevision.getFile().equals(afterRevision.getFile()) &&
afterRevision.getFile().equals(path)) {
committedPath = beforeRevision.getFile();
}
if (peg == null && change.getBeforeRevision() != null) {
peg = ((SvnRevisionNumber) change.getBeforeRevision().getRevisionNumber()).getRevision();
}
}
final LogLoader logLoader;
if (path.isNonLocal()) {
logLoader = new RepositoryLoader(myVcs, path);
logLoader = new RepositoryLoader(myVcs, path, from, to, limit, peg, forceBackwards);
}
else {
logLoader = new LocalLoader(myVcs, path);
logLoader = new LocalLoader(myVcs, path, from, to, limit, peg);
}
try {
@@ -229,9 +188,8 @@ public class SvnHistoryProvider
}
logLoader.initSupports15();
final MyHistorySession historySession =
new MyHistorySession(Collections.<VcsFileRevision>emptyList(), committedPath, Boolean.TRUE.equals(logLoader.mySupport15), null,
false);
final SvnHistorySession historySession =
new SvnHistorySession(myVcs, Collections.<VcsFileRevision>emptyList(), committedPath, Boolean.TRUE.equals(logLoader.mySupport15), null, false);
final Ref<Boolean> sessionReported = new Ref<Boolean>();
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
@@ -253,56 +211,26 @@ public class SvnHistoryProvider
logLoader.check();
}
@Nullable
private void getRevisionsList(final FilePath file, final Ref<Boolean> supports15Ref,
final Consumer<VcsFileRevision> consumer) throws VcsException {
final VcsException[] exception = new VcsException[1];
Runnable command = new Runnable() {
public void run() {
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
if (indicator != null) {
indicator.setText(SvnBundle.message("progress.text2.collecting.history", file.getName()));
}
try {
if (!file.isNonLocal()) {
collectLogEntries(indicator, file, exception, consumer, supports15Ref);
}
else {
collectLogEntriesForRepository(indicator, file, consumer, supports15Ref);
}
}
catch (SVNCancelException ex) {
throw new ProcessCanceledException(ex);
}
catch (SVNException e) {
exception[0] = new VcsException(e);
}
catch (VcsException e) {
exception[0] = e;
}
}
};
command.run();
if (exception[0] != null) {
throw exception[0];
}
}
private static abstract class LogLoader {
protected String myUrl;
protected boolean mySupport15;
protected final SvnVcs myVcs;
protected final FilePath myFile;
protected final SVNRevision myFrom;
protected final SVNRevision myTo;
protected final int myLimit;
protected final SVNRevision myPeg;
protected Consumer<VcsFileRevision> myConsumer;
protected final ProgressIndicator myPI;
protected VcsException myException;
protected LogLoader(SvnVcs vcs, FilePath file) {
protected LogLoader(SvnVcs vcs, FilePath file, SVNRevision from, SVNRevision to, int limit, SVNRevision peg) {
myVcs = vcs;
myFile = file;
myFrom = from;
myTo = to;
myLimit = limit;
myPeg = peg;
myPI = ProgressManager.getInstance().getProgressIndicator();
}
@@ -327,8 +255,8 @@ public class SvnHistoryProvider
private static class LocalLoader extends LogLoader {
private SVNInfo myInfo;
private LocalLoader(SvnVcs vcs, FilePath file) {
super(vcs, file);
private LocalLoader(SvnVcs vcs, FilePath file, SVNRevision from, SVNRevision to, int limit, SVNRevision peg) {
super(vcs, file, from, to, limit, peg);
}
@Override
@@ -370,8 +298,9 @@ public class SvnHistoryProvider
SVNLogClient client = myVcs.createLogClient();
try {
client
.doLog(new File[]{new File(myFile.getIOFile().getAbsolutePath())}, SVNRevision.HEAD, SVNRevision.create(1), SVNRevision.UNDEFINED,
false, true, mySupport15, 0, null,
.doLog(new File[]{new File(myFile.getIOFile().getAbsolutePath())},
myFrom == null ? SVNRevision.HEAD : myFrom, myTo == null ? SVNRevision.create(1) : myTo, myPeg,
false, true, mySupport15, myLimit, null,
new MyLogEntryHandler(myVcs, myUrl, pegRevision, relativeUrl, myConsumer, repoRootURL, myFile.getCharset()));
}
catch (SVNCancelException e) {
@@ -386,47 +315,18 @@ public class SvnHistoryProvider
}
}
private void collectLogEntries(final ProgressIndicator indicator, FilePath file, VcsException[] exception,
final Consumer<VcsFileRevision> result, final Ref<Boolean> supports15Ref) throws SVNException,
VcsException {
SVNWCClient wcClient = myVcs.createWCClient();
SVNInfo info = wcClient.doInfo(new File(file.getIOFile().getAbsolutePath()), SVNRevision.UNDEFINED);
wcClient.setEventHandler(new ISVNEventHandler() {
public void handleEvent(SVNEvent event, double progress) throws SVNException {
}
public void checkCancelled() throws SVNCancelException {
indicator.checkCanceled();
}
});
if (info == null || info.getRepositoryRootURL() == null) {
exception[0] = new VcsException("File ''{0}'' is not under version control" + file.getIOFile());
return;
}
final String url = info.getURL() == null ? null : info.getURL().toString();
String relativeUrl = url;
final SVNURL repoRootURL = info.getRepositoryRootURL();
final String root = repoRootURL.toString();
if (url != null && url.startsWith(root)) {
relativeUrl = url.substring(root.length());
}
if (indicator != null) {
indicator.setText2(SvnBundle.message("progress.text2.changes.establishing.connection", url));
}
final SVNRevision pegRevision = info.getRevision();
SVNLogClient client = myVcs.createLogClient();
final boolean supports15 = SvnUtil.checkRepositoryVersion15(myVcs, url);
supports15Ref.set(supports15);
client.doLog(new File[]{new File(file.getIOFile().getAbsolutePath())}, SVNRevision.HEAD, SVNRevision.create(1), SVNRevision.UNDEFINED,
false, true, supports15, 0, null,
new MyLogEntryHandler(myVcs, url, pegRevision, relativeUrl, result, repoRootURL, file.getCharset()));
}
private static class RepositoryLoader extends LogLoader {
private RepositoryLoader(SvnVcs vcs, FilePath file) {
super(vcs, file);
private final boolean myForceBackwards;
private RepositoryLoader(SvnVcs vcs,
FilePath file,
SVNRevision from,
SVNRevision to,
int limit,
SVNRevision peg,
boolean forceBackwards) {
super(vcs, file, from, to, limit, peg);
myForceBackwards = forceBackwards;
}
@Override
@@ -439,20 +339,27 @@ public class SvnHistoryProvider
if (myPI != null) {
myPI.setText2(SvnBundle.message("progress.text2.changes.establishing.connection", myUrl));
}
if (myForceBackwards) {
loadBackwards();
return;
}
SVNWCClient wcClient = myVcs.createWCClient();
try {
final SVNURL svnurl = SVNURL.parseURIEncoded(myUrl);
SVNInfo info = null;
info = wcClient.doInfo(svnurl, SVNRevision.UNDEFINED, SVNRevision.HEAD);
SVNRevision operationalFrom = myFrom == null ? SVNRevision.HEAD : myFrom;
info = wcClient.doInfo(svnurl, myPeg, operationalFrom);
final String root = info.getRepositoryRootURL().toString();
String relativeUrl = myUrl;
if (myUrl.startsWith(root)) {
relativeUrl = myUrl.substring(root.length());
}
SVNLogClient client = myVcs.createLogClient();
client
.doLog(svnurl, new String[]{}, SVNRevision.UNDEFINED, SVNRevision.HEAD, SVNRevision.create(1), false, true, mySupport15, 0, null,
new RepositoryLogEntryHandler(myVcs, myUrl, SVNRevision.UNDEFINED, relativeUrl, myConsumer, info.getRepositoryRootURL()));
client.doLog(svnurl, new String[]{}, myPeg,
operationalFrom, myTo == null ? SVNRevision.create(1) : myTo, false, true, mySupport15, myLimit, null,
new RepositoryLogEntryHandler(myVcs, myUrl, SVNRevision.UNDEFINED, relativeUrl, myConsumer,
info.getRepositoryRootURL()));
}
catch (SVNCancelException e) {
//
@@ -464,56 +371,57 @@ public class SvnHistoryProvider
myException = e;
}
}
}
private void collectLogEntriesForRepository(final ProgressIndicator indicator, FilePath file, final Consumer<VcsFileRevision> result,
final Ref<Boolean> supports15Ref) throws SVNException, VcsException {
final String url = file.getPath().replace('\\', '/');
if (indicator != null) {
indicator.setText2(SvnBundle.message("progress.text2.changes.establishing.connection", url));
private void loadBackwards() {
try {
final SVNURL svnurl = SVNURL.parseURIEncoded(myUrl);
SVNRevision operationalFrom = myFrom == null ? SVNRevision.HEAD : myFrom;
final SVNURL rootURL = getRepositoryRoot(svnurl, operationalFrom);
final String root = rootURL.toString();
String relativeUrl = myUrl;
if (myUrl.startsWith(root)) {
relativeUrl = myUrl.substring(root.length());
}
SVNLogClient client = myVcs.createLogClient();
final RepositoryLogEntryHandler repositoryLogEntryHandler =
new RepositoryLogEntryHandler(myVcs, myUrl, SVNRevision.UNDEFINED, relativeUrl, myConsumer, rootURL);
repositoryLogEntryHandler.setThrowCancelOnMeetPathCreation(true);
SVNRevision current = operationalFrom;
client.doLog(rootURL, new String[]{}, current, myTo, current, false, true, mySupport15, myLimit, null, repositoryLogEntryHandler);
}
catch (SVNCancelException e) {
//
}
catch (SVNException e) {
myException = new VcsException(e);
}
catch (VcsException e) {
myException = e;
}
}
SVNWCClient wcClient = myVcs.createWCClient();
final SVNURL svnurl = SVNURL.parseURIEncoded(url);
SVNInfo info = wcClient.doInfo(svnurl, SVNRevision.UNDEFINED, SVNRevision.HEAD);
final String root = info.getRepositoryRootURL().toString();
String relativeUrl = url;
if (url.startsWith(root)) {
relativeUrl = url.substring(root.length());
private SVNURL getRepositoryRoot(SVNURL svnurl, SVNRevision operationalFrom) throws SVNException {
final SVNWCClient wcClient = myVcs.createWCClient();
try {
final SVNInfo info;
info = wcClient.doInfo(svnurl, myPeg, operationalFrom);
return info.getRepositoryRootURL();
}
catch (SVNException e) {
final SVNInfo info;
info = wcClient.doInfo(svnurl, SVNRevision.UNDEFINED, SVNRevision.UNDEFINED);
return info.getRepositoryRootURL();
}
}
SVNLogClient client = myVcs.createLogClient();
final boolean supports15 = SvnUtil.checkRepositoryVersion15(myVcs, root);
supports15Ref.set(supports15);
// todo log in history provider
client.doLog(svnurl, new String[]{}, SVNRevision.UNDEFINED, SVNRevision.HEAD, SVNRevision.create(1), false, true, supports15, 0, null,
new RepositoryLogEntryHandler(myVcs, url, SVNRevision.UNDEFINED, relativeUrl, result, info.getRepositoryRootURL()));
}
public String getHelpId() {
return null;
}
@Nullable
private VcsRevisionNumber getCurrentRevision(FilePath file) {
if (file.isNonLocal()) {
// technically, it does not make sense, since there's no "current" revision for non-local history (if look how it's used)
// but ok, lets keep it for now
return new SvnRevisionNumber(SVNRevision.HEAD);
}
try {
SVNWCClient wcClient = myVcs.createWCClient();
SVNInfo info = wcClient.doInfo(new File(file.getPath()).getAbsoluteFile(), SVNRevision.UNDEFINED);
if (info != null) {
return new SvnRevisionNumber(info.getRevision());
}
else {
return null;
}
}
catch (SVNException e) {
return null;
}
}
public AnAction[] getAdditionalActions(final Runnable refresher) {
return new AnAction[]{new ShowAllAffectedGenericAction(), new MergeSourceDetailsAction()};
}
@@ -533,6 +441,11 @@ public class SvnHistoryProvider
protected final String myUrl;
private final SvnMergeSourceTracker myTracker;
protected SVNURL myRepositoryRoot;
private boolean myThrowCancelOnMeetPathCreation;
public void setThrowCancelOnMeetPathCreation(boolean throwCancelOnMeetPathCreation) {
myThrowCancelOnMeetPathCreation = throwCancelOnMeetPathCreation;
}
public MyLogEntryHandler(SvnVcs vcs, final String url,
final SVNRevision pegRevision,
@@ -575,6 +488,7 @@ public class SvnHistoryProvider
path = SVNPathUtil.removeTail(path);
}
}
if (entryPath == null) return; // skip this revision: no our path in it
final int mergeLevel = svnLogEntryIntegerPair.getSecond();
final SvnFileRevision revision = createRevision(logEntry, copyPath, entryPath);
@@ -590,6 +504,9 @@ public class SvnHistoryProvider
myResult.consume(revision);
myPrevious = revision;
}
if (myThrowCancelOnMeetPathCreation && myUrl.equals(revision.getURL()) && entryPath.getType() == 'A') {
throw new SVNCancelException();
}
}
});
@@ -662,7 +579,7 @@ public class SvnHistoryProvider
private class MergeSourceColumnInfo extends ColumnInfo<VcsFileRevision, String> {
private final MergeSourceRenderer myRenderer;
private MergeSourceColumnInfo(final MyHistorySession session) {
private MergeSourceColumnInfo(final SvnHistorySession session) {
super("Merge Sources");
myRenderer = new MergeSourceRenderer(session);
}
@@ -743,7 +660,7 @@ public class SvnHistoryProvider
private MergeSourceDetailsLinkListener myListener;
private final VirtualFile myFile;
private MergeSourceRenderer(final MyHistorySession session) {
private MergeSourceRenderer(final SvnHistorySession session) {
myFile = session.getCommittedPath().getVirtualFile();
}
@@ -850,7 +767,7 @@ public class SvnHistoryProvider
}
@Override
public String getMaxStringValue() {
public String getMaxStringValue(JTable table) {
return SvnBundle.message("copy.column.title");
}
@@ -0,0 +1,104 @@
/*
* Copyright 2000-2012 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 org.jetbrains.idea.svn.history;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.history.*;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnRevisionNumber;
import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.wc.SVNInfo;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.SVNWCClient;
import java.io.File;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 4/27/12
* Time: 12:24 PM
* To change this template use File | Settings | File Templates.
*/
public class SvnHistorySession extends VcsAbstractHistorySession {
private final SvnVcs myVcs;
private final FilePath myCommittedPath;
private final boolean mySupports15;
public SvnHistorySession(SvnVcs vcs, final List<VcsFileRevision> revisions, final FilePath committedPath, final boolean supports15,
@Nullable final VcsRevisionNumber currentRevision, boolean skipRefreshOnStart) {
super(revisions, currentRevision);
myVcs = vcs;
myCommittedPath = committedPath;
mySupports15 = supports15;
if (!skipRefreshOnStart) {
shouldBeRefreshed();
}
}
public HistoryAsTreeProvider getHistoryAsTreeProvider() {
return null;
}
@Nullable
public VcsRevisionNumber calcCurrentRevisionNumber() {
if (myCommittedPath == null) {
return null;
}
if (myCommittedPath.isNonLocal()) {
// technically, it does not make sense, since there's no "current" revision for non-local history (if look how it's used)
// but ok, lets keep it for now
return new SvnRevisionNumber(SVNRevision.HEAD);
}
return getCurrentCommittedRevision(myVcs, new File(myCommittedPath.getPath()));
}
public static VcsRevisionNumber getCurrentCommittedRevision(final SvnVcs vcs, final File file) {
try {
SVNWCClient wcClient = vcs.createWCClient();
SVNInfo info = wcClient.doInfo(file, SVNRevision.UNDEFINED);
if (info != null) {
return new SvnRevisionNumber(info.getCommittedRevision());
}
else {
return null;
}
}
catch (SVNException e) {
return null;
}
}
public FilePath getCommittedPath() {
return myCommittedPath;
}
@Override
public boolean isContentAvailable(final VcsFileRevision revision) {
return !myCommittedPath.isDirectory();
}
public boolean isSupports15() {
return mySupports15;
}
@Override
public VcsHistorySession copy() {
return new SvnHistorySession(myVcs, getRevisionList(), myCommittedPath, mySupports15, getCurrentRevisionNumber(), true);
}
}
@@ -0,0 +1,149 @@
/*
* Copyright 2000-2012 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 org.jetbrains.idea.svn.treeConflict;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnRevisionNumber;
import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.wc.*;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 5/2/12
* Time: 1:03 PM
*/
public class SvnTreeConflictResolver {
private final SvnVcs myVcs;
private final FilePath myPath;
private VcsRevisionNumber myCommittedRevision;
private final FilePath myRevertPath;
private final VcsDirtyScopeManager myDirtyScopeManager;
public SvnTreeConflictResolver(SvnVcs vcs, FilePath path, VcsRevisionNumber committedRevision, final @Nullable FilePath revertPath) {
myVcs = vcs;
myPath = path;
myCommittedRevision = committedRevision;
myRevertPath = revertPath;
myDirtyScopeManager = VcsDirtyScopeManager.getInstance(myVcs.getProject());
}
public void resolveSelectTheirsFull(SVNTreeConflictDescription d) throws VcsException {
updatetoTheirsFull();
pathDirty(myPath);
revertAdditional();
}
private void pathDirty(final FilePath path) {
if (path.isDirectory()) {
myDirtyScopeManager.dirDirtyRecursively(path);
}
else {
myDirtyScopeManager.fileDirty(path);
}
}
private void revertAdditional() throws VcsException {
if (myRevertPath == null) return;
final File ioFile = myRevertPath.getIOFile();
SVNWCClient client = myVcs.createWCClient();
try {
client.doRevert(new File[]{ioFile}, SVNDepth.INFINITY, null);
}
catch (SVNException e) {
throw new VcsException(e);
}
pathDirty(myRevertPath);
}
public void resolveSelectMineFull(SVNTreeConflictDescription d) throws VcsException {
SVNWCClient client = myVcs.createWCClient();
try {
client.doResolve(myPath.getIOFile(), SVNDepth.INFINITY, SVNConflictChoice.MERGED);
}
catch (SVNException e) {
throw new VcsException(e);
}
pathDirty(myPath);
revertAdditional();
}
private void updatetoTheirsFull() throws VcsException {
try {
final File ioFile = myPath.getIOFile();
SVNWCClient client = myVcs.createWCClient();
SVNStatusClient statusClient = myVcs.createStatusClient();
SVNStatus status = statusClient.doStatus(ioFile, false);
if (myCommittedRevision == null) {
myCommittedRevision = new SvnRevisionNumber(status.getCommittedRevision());
}
if (status == null || SVNStatusType.STATUS_UNVERSIONED.equals(status.getNodeStatus())) {
client.doRevert(new File[]{ioFile}, SVNDepth.INFINITY, null);
//updateIoFile(ioFile, SVNRevision.HEAD);
return;
// FileUtil.delete(ioFile);
} else if (SVNStatusType.STATUS_ADDED.equals(status.getNodeStatus())) {
client.doRevert(new File[]{ioFile}, SVNDepth.INFINITY, null);
//updateIoFile(ioFile, SVNRevision.HEAD);
/*client.doRevert(new File[]{ioFile}, SVNDepth.INFINITY, null);
FileUtil.delete(ioFile);*/
return;
} else {
final Set<File> usedToBeAdded = new HashSet<File>();
if (myPath.isDirectory()) {
statusClient.doStatus(ioFile, SVNRevision.UNDEFINED, SVNDepth.INFINITY, false, false, false, false,
new ISVNStatusHandler() {
@Override
public void handleStatus(SVNStatus status) throws SVNException {
if (status != null && SVNStatusType.STATUS_ADDED.equals(status.getNodeStatus())) {
usedToBeAdded.add(status.getFile());
}
}
}, null);
}
client.doRevert(new File[]{ioFile}, SVNDepth.INFINITY, null);
}
/*if (myPath.isDirectory()) {
if (myCommittedRevision != null) {
updateIoFile(ioFile, ((SvnRevisionNumber) myCommittedRevision).getRevision());
}
updateIoFile(ioFile, SVNRevision.HEAD);
}*/
}
catch (SVNException e1) {
throw new VcsException(e1);
}
}
private void updateIoFile(File ioFile, final SVNRevision revision) throws SVNException {
if (! ioFile.exists()) {
myVcs.createUpdateClient().doUpdate(ioFile.getParentFile(), revision, SVNDepth.INFINITY, true, false);
} else {
myVcs.createUpdateClient().doUpdate(ioFile, revision, SVNDepth.INFINITY, false, false);
}
}
}
@@ -0,0 +1,55 @@
/*
* Copyright 2000-2012 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 org.jetbrains.idea.svn.treeConflict;
import com.intellij.openapi.progress.BackgroundTaskQueue;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.RefreshablePanel;
import com.intellij.openapi.vcs.changes.VcsChangeDetailsProvider;
import org.jetbrains.idea.svn.ConflictedSvnChange;
import javax.swing.*;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 4/25/12
* Time: 5:04 PM
*/
public class TreeConflictDetailsProvider implements VcsChangeDetailsProvider {
private final Project myProject;
public TreeConflictDetailsProvider(Project project) {
myProject = project;
}
@Override
public String getName() {
return "Subversion Tree Conflict";
}
@Override
public boolean canComment(Change change) {
if (change instanceof ConflictedSvnChange && ((ConflictedSvnChange)change).getConflictState().isTree()) return true;
return false;
}
@Override
public RefreshablePanel comment(Change change, JComponent parent, BackgroundTaskQueue queue) {
return new TreeConflictRefreshablePanel(myProject, "Loading tree conflict details", queue, change);
}
}
@@ -0,0 +1,681 @@
/*
* Copyright 2000-2012 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 org.jetbrains.idea.svn.treeConflict;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.progress.BackgroundTaskQueue;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.history.*;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.util.BeforeAfter;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.VcsBackgroundTask;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.ConflictedSvnChange;
import org.jetbrains.idea.svn.SvnRevisionNumber;
import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.history.SvnHistoryProvider;
import org.jetbrains.idea.svn.history.SvnHistorySession;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.internal.wc.SVNConflictVersion;
import org.tmatesoft.svn.core.internal.wc.SVNTreeConflictUtil;
import org.tmatesoft.svn.core.wc.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 4/25/12
* Time: 5:33 PM
*/
public class TreeConflictRefreshablePanel extends AbstractRefreshablePanel {
private final ConflictedSvnChange myChange;
private final SvnVcs myVcs;
private VcsRevisionNumber myCommittedRevision;
private FilePath myPath;
private final List<Disposable> myChildDisposables;
public TreeConflictRefreshablePanel(Project project, String loadingTitle, BackgroundTaskQueue queue, Change change) {
super(project, loadingTitle, queue);
myVcs = SvnVcs.getInstance(project);
assert change instanceof ConflictedSvnChange;
myChange = (ConflictedSvnChange) change;
myPath = ChangesUtil.getFilePath(myChange);
myChildDisposables = new ArrayList<Disposable>();
}
@Override
public boolean isStillValid(final Change change) {
return change.isTreeConflict() && change instanceof ConflictedSvnChange &&
descriptionsEqual(((ConflictedSvnChange)change).getBeforeDescription(), myChange.getBeforeDescription());
}
private boolean descriptionsEqual(SVNTreeConflictDescription d1, SVNTreeConflictDescription d2) {
if (d1.isPropertyConflict() != d2.isPropertyConflict()) return false;
if (d1.isTextConflict() != d2.isTextConflict()) return false;
if (d1.isTreeConflict() != d2.isTreeConflict()) return false;
if (! d1.getOperation().equals(d2.getOperation())) return false;
if (! d1.getConflictAction().equals(d2.getConflictAction())) return false;
if (! Comparing.equal(d1.getConflictReason(), d2.getConflictReason())) return false;
if (! Comparing.equal(d1.getPath(), d2.getPath())) return false;
if (! Comparing.equal(d1.getNodeKind(), d2.getNodeKind())) return false;
if (! compareConflictVersion(d1.getSourceLeftVersion(), d2.getSourceLeftVersion())) return false;
if (! compareConflictVersion(d1.getSourceRightVersion(), d2.getSourceRightVersion())) return false;
return true;
}
private boolean compareConflictVersion(SVNConflictVersion v1, SVNConflictVersion v2) {
if (v1 == null && v2 == null) return true;
if (v1 == null && v2 != null || v1 != null && v2 == null) return false;
if (! v1.getKind().equals(v2.getKind())) return false;
if (! v1.getPath().equals(v2.getPath())) return false;
if (v1.getPegRevision() != v2.getPegRevision()) return false;
if (! Comparing.equal(v1.getRepositoryRoot(), v2.getRepositoryRoot())) return false;
return true;
}
@Override
protected void refreshPresentation() {
}
@Override
protected Object loadImpl() throws VcsException {
return new BeforeAfter<BeforeAfter<ConflictSidePresentation>>(processDescription(myChange.getBeforeDescription()),
processDescription(myChange.getAfterDescription()));
}
private BeforeAfter<ConflictSidePresentation> processDescription(SVNTreeConflictDescription description) throws VcsException {
if (description == null) return null;
if (myChange.getBeforeRevision() != null) {
myCommittedRevision = SvnHistorySession.getCurrentCommittedRevision(myVcs, myPath.getIOFile());
}
final SVNRevision pegFromLeft = description.getSourceLeftVersion() == null ?
null : SVNRevision.create(description.getSourceLeftVersion().getPegRevision());
ConflictSidePresentation rightSide = createSide(description.getSourceRightVersion(), pegFromLeft, false);
final SidesProcessorMarker marker;
ConflictSidePresentation leftSide;
if (description.getSourceLeftVersion() != null && description.getSourceRightVersion() != null &&
! Comparing.equal(description.getSourceLeftVersion().getPath(), description.getSourceRightVersion().getPath())) {
leftSide = createSide(description.getSourceLeftVersion(), pegFromLeft, true);
marker = new TwoSidesProcessor((AbstractConflictSide) leftSide, (AbstractConflictSide) rightSide, UniversalComparator.getInstance());
} else {
leftSide = EmptyConflictSide.getInstance();
if (rightSide instanceof AbstractConflictSide) {
marker = new OneSideProcessor(
description.getSourceLeftVersion() == null ? SVNRevision.create(1) : SVNRevision.create(description.getSourceLeftVersion().getPegRevision()), (AbstractConflictSide) rightSide);
} else {
marker = SidesProcessorMarker.EMPTY;
}
}
marker.run();
myChildDisposables.add(leftSide);
myChildDisposables.add(rightSide);
return new BeforeAfter<ConflictSidePresentation>(leftSide, rightSide);
}
private static class UniversalComparator<Object> implements Comparator<Object> {
private final static UniversalComparator ourComparator = new UniversalComparator();
public static UniversalComparator getInstance() {
return ourComparator;
}
@Override
public int compare(Object o1, Object o2) {
long number1 = get(o1).getNumber();
long number2 = get(o2).getNumber();
return number1 < number2 ? -1 : (number1 == number2 ? 0 : 1);
}
private SVNRevision get(final Object o) {
if (o instanceof VcsFileRevision) {
return ((SvnRevisionNumber) ((VcsFileRevision) o).getRevisionNumber()).getRevision();
}
if (o instanceof CommittedChangeList) {
return SVNRevision.create(((CommittedChangeList) o).getNumber());
}
assert true;
return null;
}
}
private ConflictSidePresentation createSide(SVNConflictVersion version, final SVNRevision pegFromLeft, final boolean isLeft) throws VcsException {
if (version == null) return EmptyConflictSide.getInstance();
SvnRevisionNumber number = null;
if (myChange.getBeforeRevision() != null) {
number = (SvnRevisionNumber) myCommittedRevision;
if (isLeft && number.getRevision().isValid() && number.getRevision().getNumber() == version.getPegRevision()) {
return EmptyConflictSide.getInstance();
}
}
// todo temporally
/*if (SVNNodeKind.DIR.equals(version.getKind())) {
return new HistoryAsBrowseChangesConflictSide(myVcs.getProject(), version);
} else {
return new HistoryConflictSide(myVcs, version);
}*/
return new HistoryConflictSide(myVcs, version, number == null ? pegFromLeft : number.getRevision());
}
@Override
protected JPanel dataToPresentation(Object o) {
final BeforeAfter<BeforeAfter<ConflictSidePresentation>> ba = (BeforeAfter<BeforeAfter<ConflictSidePresentation>>) o;
final JPanel wrapper = new JPanel(new BorderLayout());
final JPanel main = new JPanel(new GridBagLayout());
final GridBagConstraints gb = new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL,
new Insets(1, 1, 1, 1), 0, 0);
final String pathComment = myCommittedRevision == null ? "" :
(new StringBuilder(" (current: ")
.append(myChange.getBeforeRevision().getRevisionNumber().asString()).append(", committed: ")
.append(myCommittedRevision.asString()).append(")").toString());
final JLabel name = new JLabel(myPath.getName() + pathComment);
name.setFont(name.getFont().deriveFont(Font.BOLD));
gb.insets.top = 5;
main.add(name, gb);
++ gb.gridy;
gb.insets.top = 10;
appendDescription(myChange.getBeforeDescription(), main, gb, ba.getBefore(), myPath.isDirectory());
appendDescription(myChange.getAfterDescription(), main, gb, ba.getAfter(), myPath.isDirectory());
wrapper.add(main, BorderLayout.NORTH);
return wrapper;
}
private void appendDescription(SVNTreeConflictDescription description,
JPanel main,
GridBagConstraints gb,
BeforeAfter<ConflictSidePresentation> ba, boolean directory) {
if (description == null) return;
JLabel descriptionLbl = new JLabel(SVNTreeConflictUtil.getHumanReadableConflictDescription(description));
descriptionLbl.setForeground(Color.red);
main.add(descriptionLbl, gb);
++ gb.gridy;
//buttons
gb.insets.top = 0;
addResolveButtons(description, main, gb);
addSide(main, gb, ba.getBefore(), description.getSourceLeftVersion(), "Left", directory);
addSide(main, gb, ba.getAfter(), description.getSourceRightVersion(), "Right", directory);
}
private void addResolveButtons(SVNTreeConflictDescription description, JPanel main, GridBagConstraints gb) {
JPanel wrapper = new JPanel(new FlowLayout(FlowLayout.LEFT));
final JButton both = new JButton("Both");
final JButton merge = new JButton("Merge");
final JButton left = new JButton("Mine");
final JButton right = new JButton("Theirs");
enableAndSetListener(createBoth(description), both);
enableAndSetListener(createMerge(description), merge);
enableAndSetListener(createLeft(description), left);
enableAndSetListener(createRight(description), right);
/*wrapper.add(both);
wrapper.add(merge);*/
wrapper.add(left);
wrapper.add(right);
main.add(wrapper, gb);
++ gb.gridy;
}
private ActionListener createRight(final SVNTreeConflictDescription description) {
return new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ProgressManager.getInstance().run(
new VcsBackgroundTask<SVNTreeConflictDescription>(myVcs.getProject(), "Accept theirs for: " + myPath,
BackgroundFromStartOption.getInstance(), Collections.singletonList(description),
true) {
@Override
protected void process(SVNTreeConflictDescription d) throws VcsException {
new SvnTreeConflictResolver(myVcs, myPath, myCommittedRevision, null).resolveSelectTheirsFull(d);
}
});
}
};
}
private void acceptOne(final SVNTreeConflictDescription description, final SVNConflictChoice choice, final String title) {
ProgressManager.getInstance().run(new VcsBackgroundTask<SVNTreeConflictDescription>(myVcs.getProject(), title + myPath,
BackgroundFromStartOption.getInstance(), Collections.singletonList(description), true) {
@Override
protected void process(SVNTreeConflictDescription d) throws VcsException {
try {
myVcs.createWCClient().doResolve(d.getPath(), SVNDepth.INFINITY, choice);
}
catch (SVNException e1) {
throw new VcsException(e1);
}
VcsDirtyScopeManager dirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject);
if (myPath.isDirectory()) {
dirtyScopeManager.dirDirtyRecursively(myPath);
} else {
dirtyScopeManager.fileDirty(myPath);
}
}
});
}
private ActionListener createLeft(final SVNTreeConflictDescription description) {
return new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ProgressManager.getInstance().run(
new VcsBackgroundTask<SVNTreeConflictDescription>(myVcs.getProject(), "Accept theirs for: " + myPath,
BackgroundFromStartOption.getInstance(), Collections.singletonList(description),
true) {
@Override
protected void process(SVNTreeConflictDescription d) throws VcsException {
new SvnTreeConflictResolver(myVcs, myPath, myCommittedRevision, null).resolveSelectMineFull(d);
}
});
}
};
}
private ActionListener createMerge(SVNTreeConflictDescription description) {
return null; //To change body of created methods use File | Settings | File Templates.
}
private ActionListener createBoth(SVNTreeConflictDescription description) {
return null; //To change body of created methods use File | Settings | File Templates.
}
private void enableAndSetListener(final ActionListener al, final JButton b) {
if (al == null) {
b.setEnabled(false);
}
else {
b.addActionListener(al);
}
}
private void addSide(JPanel main,
GridBagConstraints gb,
ConflictSidePresentation before,
SVNConflictVersion leftVersion, final String name, boolean directory) {
final String leftPresentation = leftVersion == null ? name + ": (" + (directory ? "directory" : "file") +
(myChange.getBeforeRevision() == null ? ") added" : ") unversioned") :
(name + ": " + FileUtil.toSystemIndependentName(SVNTreeConflictUtil.getHumanReadableConflictVersion(leftVersion)));
gb.insets.top = 10;
main.add(new JLabel(leftPresentation), gb);
++ gb.gridy;
gb.insets.top = 0;
if (before != null) {
JPanel panel = before.createPanel();
if (panel != null) {
//gb.fill = GridBagConstraints.HORIZONTAL;
main.add(panel, gb);
//gb.fill = GridBagConstraints.NONE;
++ gb.gridy;
}
}
}
@Override
protected void disposeImpl() {
for (Disposable disposable : myChildDisposables) {
Disposer.dispose(disposable);
}
}
@Override
public void away() {
}
private interface ConflictSidePresentation extends Disposable {
JPanel createPanel();
}
private static class EmptyConflictSide implements ConflictSidePresentation {
private final static EmptyConflictSide ourInstance = new EmptyConflictSide();
public static EmptyConflictSide getInstance() {
return ourInstance;
}
@Override
public JPanel createPanel() {
return null;
}
@Override
public void dispose() {
}
}
private static abstract class AbstractConflictSide<T> implements ConflictSidePresentation {
protected final Project myProject;
protected final SVNConflictVersion myVersion;
private AbstractConflictSide(Project project, SVNConflictVersion version) {
myProject = project;
myVersion = version;
}
public abstract List<T> step(StopMarker marker) throws VcsException;
public abstract void cutTo(final T t);
}
private interface StopMarker {
<T> boolean isEof(final List<T> list);
}
private static class ToRevision implements StopMarker {
private final SVNRevision myRevision;
private ToRevision(SVNRevision revision) {
myRevision = revision;
}
public SVNRevision getRevision() {
return myRevision;
}
@Override
public <T> boolean isEof(List<T> list) {
// should be ok, check would have be like an assertion -> we asked until the revision
return true;
}
}
private static class Portion implements StopMarker {
private final static int ourStep = 10;
public static int getOurStep() {
return ourStep;
}
@Override
public <T> boolean isEof(List<T> list) {
return list.size() < ourStep;
}
}
private static class NoLimit implements StopMarker {
private final static NoLimit ourInstance = new NoLimit();
public static NoLimit getInstance() {
return ourInstance;
}
@Override
public <T> boolean isEof(List<T> list) {
// we loaded all
return true;
}
}
private interface SidesProcessorMarker extends ThrowableRunnable<VcsException> {
SidesProcessorMarker EMPTY = new SidesProcessorMarker() {
@Override
public void run() {
}
};
}
private static class OneSideProcessor<T> implements SidesProcessorMarker {
private final AbstractConflictSide<T> mySide;
private final SVNRevision myLimitingRevision;
private OneSideProcessor(SVNRevision limitingRevision, AbstractConflictSide<T> side) {
myLimitingRevision = limitingRevision;
mySide = side;
}
@Override
public void run() throws VcsException {
mySide.step(new ToRevision(myLimitingRevision));
}
}
private static class TwoSidesProcessor<Left, Right> implements SidesProcessorMarker {
private final AbstractConflictSide<Left> myLeft;
private final AbstractConflictSide<Right> myRight;
private final Comparator myComparator;
private TwoSidesProcessor(@NotNull AbstractConflictSide<Left> left, @NotNull AbstractConflictSide<Right> right,
final Comparator comparator) {
myLeft = left;
myRight = right;
myComparator = comparator;
}
@Override
public void run() throws VcsException {
final SteppableSide<Left> left = new SteppableSide<Left>(myLeft);
final SteppableSide<Right> right = new SteppableSide<Right>(myRight);
left.init();
right.init();
while (! left.isEof() || ! right.isEof()) {
while (left.hasNext() && right.hasNext()) {
Left leftItem = left.get();
Right rightItem = right.get();
int compare = myComparator.compare(leftItem, rightItem);
if (compare == 0) {
myLeft.cutTo(leftItem);
myRight.cutTo(rightItem);
return;
} else if (compare < 0) {
left.step();
} else {
right.step();
}
}
boolean loadLeft = ! left.hasNext();
left.loadStep(loadLeft, right.isEof());
right.loadStep(! loadLeft, left.isEof());
}
}
private static class SteppableSide<T> {
private List<T> myList;
private int myIdx;
private boolean myEof;
private AbstractConflictSide mySide;
private SteppableSide(AbstractConflictSide side) {
mySide = side;
myList = Collections.emptyList();
myEof = false;
myIdx = 0;
}
public void init() throws VcsException {
loadPiece(false);
}
public boolean isEof() {
return myEof;
}
public void loadStep(final boolean forceAdvanceMe, final boolean foreignEof) throws VcsException {
if ((forceAdvanceMe || foreignEof) && ! myEof) {
loadPiece(foreignEof);
}
}
public void step() {
++ myIdx;
}
public T get() {
return myList.get(myIdx);
}
public boolean hasNext() {
return myIdx < myList.size();
}
private void loadPiece(boolean foreignEof) throws VcsException {
StopMarker stopMarker = foreignEof ? NoLimit.getInstance() : new Portion();
myList = mySide.step(stopMarker);
myEof = stopMarker.isEof(myList);
myList.clear();
myIdx = 0;
}
}
private boolean loadPiece(boolean thisEof, boolean foreignEof, final List<Left> list) throws VcsException {
//if ((loadThis || foreignEof) && ! thisEof) {
StopMarker stopMarker = foreignEof ? NoLimit.getInstance() : new Portion();
List<Left> step = myLeft.step(stopMarker);
thisEof = stopMarker.isEof(step);
list.clear();
list.addAll(step);
//}
return thisEof;
}
}
private static class HistoryConflictSide extends AbstractConflictSide<VcsFileRevision> {
private final VcsAppendableHistoryPartnerAdapter mySessionAdapter;
private final SvnHistoryProvider myProvider;
private final FilePath myPath;
private final SvnVcs myVcs;
private final SVNRevision myPeg;
private SVNRevision myRevisionTo;
private FileHistoryPanelImpl myFileHistoryPanel;
private HistoryConflictSide(SvnVcs vcs, SVNConflictVersion version, final SVNRevision peg) throws VcsException {
super(vcs.getProject(), version);
myVcs = vcs;
myPeg = peg;
try {
myPath = FilePathImpl.createNonLocal(
version.getRepositoryRoot().appendPath(FileUtil.toSystemIndependentName(version.getPath()), true).toString(), SVNNodeKind.DIR.equals(version.getKind()));
}
catch (SVNException e) {
throw new VcsException(e);
}
mySessionAdapter = new VcsAppendableHistoryPartnerAdapter();
mySessionAdapter.reportCreatedEmptySession(new SvnHistorySession(myVcs, Collections.<VcsFileRevision>emptyList(),
myPath, SvnUtil.checkRepositoryVersion15(myVcs, version.getPath()), null, true));
myProvider = (SvnHistoryProvider) myVcs.getVcsHistoryProvider();
}
@Override
public List<VcsFileRevision> step(StopMarker marker) throws VcsException {
List<VcsFileRevision> list = mySessionAdapter.getSession().getRevisionList();
int limit = 0;
SVNRevision from;
if (list.isEmpty()) {
myRevisionTo = SVNRevision.create(1);
if (marker instanceof ToRevision) {
myRevisionTo = ((ToRevision)marker).getRevision();
}
from = SVNRevision.create(myVersion.getPegRevision());
} else {
from = ((SvnRevisionNumber) list.get(list.size() - 1).getRevisionNumber()).getRevision();
}
if (marker instanceof Portion) {
limit = Portion.getOurStep();
}
VcsAppendableHistoryPartnerAdapter adapter = new VcsAppendableHistoryPartnerAdapter();
myProvider.reportAppendableHistory(myPath, adapter, myRevisionTo, from, limit, myPeg, true);
final List<VcsFileRevision> newRevisions = adapter.getSession().getRevisionList();
list.addAll(newRevisions);
return newRevisions;
}
@Override
public void cutTo(VcsFileRevision endRevision) {
List<VcsFileRevision> list = mySessionAdapter.getSession().getRevisionList();
int i = 0;
for (; i < list.size(); i++) {
final VcsFileRevision revision = list.get(i);
// it is same exactly object so ok if even equals is not overriden
if (endRevision.equals(revision)) {
break;
}
}
if (i < list.size()) {
final ArrayList<VcsFileRevision> copy = new ArrayList<VcsFileRevision>(list.subList(0, i + 1));
list.clear();
list.addAll(copy);
}
}
@Override
public void dispose() {
if (myFileHistoryPanel != null) {
myFileHistoryPanel.dispose();
}
}
@Override
public JPanel createPanel() {
// todo do not forget to call dispose
// todo remove refresh
VcsAbstractHistorySession session = mySessionAdapter.getSession();
List<VcsFileRevision> list = session.getRevisionList();
VcsFileRevision last = null;
if (! list.isEmpty() && myRevisionTo.getNumber() > 0 &&
myRevisionTo.equals(((SvnRevisionNumber) list.get(list.size() - 1).getRevisionNumber()).getRevision())) {
last = list.remove(list.size() - 1);
}
myFileHistoryPanel = new FileHistoryPanelImpl(myVcs, myPath, session, myProvider, null, new FileHistoryRefresherI() {
@Override
public void run(boolean isRefresh) {
//we will not refresh
}
@Override
public boolean isFirstTime() {
return false;
}
}, true);
myFileHistoryPanel.setBottomRevisionForShowDiff(last);
myFileHistoryPanel.setBorder(BorderFactory.createLineBorder(UIUtil.getBorderColor()));
return myFileHistoryPanel;
}
}
/*private static class HistoryAsBrowseChangesConflictSide implements AbstractConflictSide<Object> {
public HistoryAsBrowseChangesConflictSide(Project project, SVNConflictVersion version) {
//To change body of created methods use File | Settings | File Templates.
}
@Override
public JPanel createPanel() {
return null;
}
}*/
}
@@ -0,0 +1,201 @@
/*
* Copyright 2000-2012 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 org.jetbrains.idea.svn;
import com.intellij.openapi.diff.impl.patch.*;
import com.intellij.openapi.diff.impl.patch.formove.PatchApplier;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsConfiguration;
import com.intellij.openapi.vcs.VcsShowConfirmationOption;
import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Processor;
import com.intellij.util.containers.Convertor;
import junit.framework.Assert;
import org.tmatesoft.svn.core.wc.SVNInfo;
import org.tmatesoft.svn.core.wc.SVNStatusType;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 5/2/12
* Time: 2:02 PM
*/
public class ConflictCreator {
private final Project myProject;
private final VirtualFile myTheirsDir;
private final VirtualFile myMineDir;
private final TreeConflictData.Data myData;
private final SvnClientRunner myClientRunner;
public ConflictCreator(final Project project,
VirtualFile dir,
VirtualFile mineDir,
TreeConflictData.Data data,
final SvnClientRunner clientRunner) {
myProject = project;
myTheirsDir = dir;
myMineDir = mineDir;
myData = data;
myClientRunner = clientRunner;
}
public void create() throws PatchSyntaxException, IOException {
// local changes, do not commit
for (TreeConflictData.FileData data : myData.getLeftFiles()) {
applyFileData(myMineDir, data);
}
final PatchReader reader = new PatchReader(myData.getTheirsPatch());
final List<TextFilePatch> patches = reader.readAllPatches();
final List<FilePatch> filePatchList = new ArrayList<FilePatch>(patches);
for (Iterator<FilePatch> iterator = filePatchList.iterator(); iterator.hasNext(); ) {
final FilePatch patch = iterator.next();
if (patch.isDeletedFile()) {
myClientRunner.delete(myTheirsDir, patch.getBeforeName());
iterator.remove();
}
}
if (! filePatchList.isEmpty()) {
PatchApplier<BinaryFilePatch> applier = new PatchApplier<BinaryFilePatch>(myProject, myTheirsDir, filePatchList, (LocalChangeList) null, null, null);
applier.setIgnoreContentRootsCheck();
applier.execute();
Assert.assertEquals(0, applier.getRemainingPatches().size());
}
try {
Thread.sleep(10);
}
catch (InterruptedException e) {
//
}
SvnVcs vcs = SvnVcs.getInstance(myProject);
for (TextFilePatch patch : patches) {
if (patch.isNewFile() || ! Comparing.equal(patch.getAfterName(), patch.getBeforeName())) {
final String afterName = patch.getAfterName();
final String[] parts = afterName.split("/");
String subPath = "";
for (String part : parts) {
final String path = subPath + part;
SVNInfo info = vcs.getInfo(new File(myTheirsDir.getPath(), path));
if (info == null || info.getURL() == null) {
myClientRunner.add(myTheirsDir, path);
}
subPath += part + "/";
}
if (! patch.isNewFile()) {
myClientRunner.delete(myTheirsDir, patch.getBeforeName());
}
}
}
final IOException[] ioe = new IOException[1];
VfsUtil.processFilesRecursively(myTheirsDir, new Processor<VirtualFile>() {
@Override
public boolean process(VirtualFile file) {
if (file.isDirectory() && file.getChildren().length == 0) {
try {
myClientRunner.delete(myTheirsDir, file.getPath());
}
catch (IOException e) {
ioe[0] = e;
}
}
return true;
}
}, new Convertor<VirtualFile, Boolean>() {
@Override
public Boolean convert(VirtualFile o) {
return ! SvnUtil.isAdminDirectory(o);
}
});
/*FileUtil.processFilesRecursively(new File(myTheirsDir.getPath()), new Processor<File>() {
@Override
public boolean process(File file) {
if (file.isDirectory() && file.listFiles().length == 0) {
try {
myClientRunner.delete(myTheirsDir, file.getPath());
}
catch (IOException e) {
ioe[0] = e;
}
}
return true;
}
});*/
if (ioe[0] != null) {
throw ioe[0];
}
// this will commit all patch changes
myClientRunner.checkin(myTheirsDir);
// this will create the conflict
myClientRunner.update(myMineDir);
myClientRunner.update(myTheirsDir);
}
private void applyFileData(final VirtualFile root, final TreeConflictData.FileData fileData) throws IOException {
final File target = new File(root.getPath(), fileData.myRelativePath);
// we dont apply properties changes fow now
if (SVNStatusType.STATUS_MISSING.equals(fileData.myNodeStatus)) {
// delete existing only from fs
FileUtil.delete(target);
return;
} else if (SVNStatusType.STATUS_UNVERSIONED.equals(fileData.myNodeStatus)) {
// create new unversioned
createFile(root, fileData, target);
return;
} else if (SVNStatusType.STATUS_ADDED.equals(fileData.myNodeStatus)) {
if (fileData.myCopyFrom != null) {
myClientRunner.copy(root, fileData.myCopyFrom, fileData.myRelativePath);
return;
}
createFile(root, fileData, target);
myClientRunner.add(root, fileData.myRelativePath);
return;
} else if (SVNStatusType.STATUS_DELETED.equals(fileData.myNodeStatus)) {
myClientRunner.delete(root, fileData.myRelativePath);
return;
} else if (SVNStatusType.STATUS_NORMAL.equals(fileData.myNodeStatus)) {
if (SVNStatusType.STATUS_MODIFIED.equals(fileData.myContentsStatus)) {
createFile(root, fileData, target);
return;
}
}
}
private void createFile(final VirtualFile root, final TreeConflictData.FileData fileData, File target) throws IOException {
if (fileData.myIsDir) {
target.mkdirs();
} else {
FileUtil.writeToFile(target, fileData.myContents);
}
}
}
@@ -50,32 +50,6 @@ public class SvnChangesCorrectlyRefreshedTest extends SvnTestCase {
enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
}
private class SubTree {
private final VirtualFile myRootDir;
private VirtualFile mySourceDir;
private final VirtualFile myTargetDir;
private VirtualFile myS1File;
private VirtualFile myS2File;
private final List<VirtualFile> myTargetFiles;
private static final String ourS1Contents = "123";
private static final String ourS2Contents = "abc";
private SubTree(final VirtualFile base) throws Exception {
myRootDir = createDirInCommand(base, "root");
mySourceDir = createDirInCommand(myRootDir, "source");
myS1File = createFileInCommand(mySourceDir, "s1.txt", ourS1Contents);
myS2File = createFileInCommand(mySourceDir, "s2.txt", ourS2Contents);
myTargetDir = createDirInCommand(myRootDir, "target");
myTargetFiles = new ArrayList<VirtualFile>();
for (int i = 0; i < 10; i++) {
myTargetFiles.add(createFileInCommand(myTargetDir, "t" + (i+10) +".txt", ourS1Contents));
}
}
}
private static void sleep(final int millis) {
try {
Thread.sleep(millis);
@@ -0,0 +1,43 @@
/*
* Copyright 2000-2012 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 org.jetbrains.idea.svn;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.openapi.vfs.VirtualFile;
import java.io.IOException;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 5/2/12
* Time: 5:44 PM
*/
public interface SvnClientRunner {
ProcessOutput runSvn(final VirtualFile file, String... commandLine) throws IOException;
void checkin(final VirtualFile file) throws IOException;
void update(final VirtualFile file) throws IOException;
void checkout(String repoUrl, VirtualFile file) throws IOException;
void add(VirtualFile root, String path) throws IOException;
void delete(VirtualFile root, String path) throws IOException;
void copy(VirtualFile root, String path, String from) throws IOException;
}
@@ -0,0 +1,73 @@
/*
* Copyright 2000-2012 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 org.jetbrains.idea.svn;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.AbstractVcsTestCase;
import com.intellij.testFramework.TestClientRunner;
import java.io.File;
import java.io.IOException;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 5/2/12
* Time: 5:33 PM
*/
public class SvnClientRunnerImpl implements SvnClientRunner {
private final TestClientRunner myTestClientRunner;
public SvnClientRunnerImpl(final TestClientRunner testClientRunner) {
myTestClientRunner = testClientRunner;
}
@Override
public ProcessOutput runSvn(final VirtualFile file, String... commandLine) throws IOException {
return myTestClientRunner.runClient("svn", null, new File(file.getPath()), commandLine);
}
@Override
public void checkin(final VirtualFile file) throws IOException {
AbstractVcsTestCase.verify(runSvn(file, "ci", "-m", "test"));
}
@Override
public void update(final VirtualFile file) throws IOException {
AbstractVcsTestCase.verify(runSvn(file, "up", "--accept", "postpone"));
}
@Override
public void checkout(final String repoUrl, final VirtualFile file) throws IOException {
AbstractVcsTestCase.verify(runSvn(file, "co", repoUrl, "."));
}
@Override
public void add(VirtualFile root, String path) throws IOException {
AbstractVcsTestCase.verify(runSvn(root, "add", path));
}
@Override
public void delete(VirtualFile root, String path) throws IOException {
AbstractVcsTestCase.verify(runSvn(root, "delete", path));
}
@Override
public void copy(VirtualFile root, String path, String from) throws IOException {
AbstractVcsTestCase.verify(runSvn(root, "copy", path, from));
}
}
@@ -0,0 +1,317 @@
/*
* Copyright 2000-2012 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 org.jetbrains.idea.svn;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.VcsConfiguration;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.TestClientRunner;
import com.intellij.util.Processor;
import junit.framework.Assert;
import org.jetbrains.idea.svn.treeConflict.SvnTreeConflictResolver;
import org.junit.Before;
import org.junit.Test;
import org.tmatesoft.svn.core.wc.SVNInfo;
import org.tmatesoft.svn.core.wc.SVNStatus;
import org.tmatesoft.svn.core.wc.SVNStatusType;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 5/3/12
* Time: 6:14 PM
*/
public class SvnResolveTreeAcceptVariantsTest extends SvnTestCase {
private VirtualFile myTheirs;
private SvnClientRunnerImpl mySvnClientRunner;
private SvnVcs myVcs;
private VcsDirtyScopeManager myDirtyScopeManager;
private ChangeListManager myChangeListManager;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
disableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
myTheirs = myTempDirFixture.findOrCreateDir("theirs");
final TestClientRunner testClientRunner = new TestClientRunner(true, myClientBinaryPath);
mySvnClientRunner = new SvnClientRunnerImpl(testClientRunner);
clearWc(true);
myVcs = SvnVcs.getInstance(myProject);
myDirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject);
myChangeListManager = ChangeListManager.getInstance(myProject);
myTraceClient = true;
}
private void clearWc(final boolean withSvn) {
myWorkingCopyDir.refresh(false, true);
/*VfsUtil.processFilesRecursively(myWorkingCopyDir, new Processor<VirtualFile>() {
@Override
public boolean process(VirtualFile file) {
if (myWorkingCopyDir.equals(file) || SvnUtil.isAdminDirectory(file)) return true;
FileUtil.delete(new File(file.getPath()));
return true;
}
}, new Convertor<VirtualFile, Boolean>() {
@Override
public Boolean convert(VirtualFile o) {
return withSvn || ! SvnUtil.isAdminDirectory(o);
}
});*/
clearDirInCommand(myWorkingCopyDir, new Processor<VirtualFile>() {
@Override
public boolean process(VirtualFile file) {
return withSvn || ! SvnUtil.isAdminDirectory(file);
}
});
myWorkingCopyDir.refresh(false, true);
}
@Test
public void testMineFull() throws Exception {
int cnt = 0;
myWorkingCopyDir = createDirInCommand(myWorkingCopyDir, "test--");
myTheirs = createDirInCommand(myTheirs, "theirs--");
// todo debug
//final TreeConflictData.Data data = TreeConflictData.DirToDir.MINE_EDIT_THEIRS_DELETE;
for (final TreeConflictData.Data data : TreeConflictData.ourAll) {
if (myTraceClient) {
System.out.println("========= TEST " + getTestName(data) + " =========");
}
myWorkingCopyDir = createDirInCommand(myWorkingCopyDir.getParent(), "test" + cnt);
myTheirs = createDirInCommand(myTheirs.getParent(), "theirs" + cnt);
mySvnClientRunner.checkout(myRepoUrl, myTheirs);
mySvnClientRunner.checkout(myRepoUrl, myWorkingCopyDir);
createSubTree();
final ConflictCreator creator = new ConflictCreator(myProject, myTheirs, myWorkingCopyDir, data, mySvnClientRunner);
creator.create();
myDirtyScopeManager.markEverythingDirty();
myChangeListManager.ensureUpToDate(false);
myDirtyScopeManager.markEverythingDirty();
myChangeListManager.ensureUpToDate(false);
final String conflictFile = data.getConflictFile();
final File conflictIoFile = new File(myWorkingCopyDir.getPath(), conflictFile);
final FilePathImpl filePath = new FilePathImpl(conflictIoFile, conflictIoFile.isDirectory());
final Change change = myChangeListManager.getChange(filePath);
Assert.assertNotNull(change);
Assert.assertTrue(change instanceof ConflictedSvnChange);
final SvnRevisionNumber committedRevision =
change.getBeforeRevision() != null ? (SvnRevisionNumber)change.getBeforeRevision().getRevisionNumber() : null;
//SvnRevisionNumber committedRevision = new SvnRevisionNumber(SVNRevision.create(cnt * 2 + 1));
final SvnTreeConflictResolver resolver = new SvnTreeConflictResolver(myVcs, filePath, committedRevision, null);
resolver.resolveSelectMineFull(((ConflictedSvnChange)change).getBeforeDescription());
myTheirs.refresh(false, true);
myWorkingCopyDir.refresh(false, true);
checkStatusesAfterMineFullResolve(data, conflictIoFile);
++ cnt;
}
}
private void checkStatusesAfterMineFullResolve(TreeConflictData.Data data, File conflictIoFile) {
SVNStatus conflStatus = SvnUtil.getStatus(myVcs, conflictIoFile);
Assert.assertTrue(createTestFailedComment(data, conflictIoFile.getPath()) + " tree conflict resolved",
conflStatus.getTreeConflict() == null);
Collection<TreeConflictData.FileData> leftFiles = data.getLeftFiles();
for (TreeConflictData.FileData file : leftFiles) {
File exFile = new File(myWorkingCopyDir.getPath(), file.myRelativePath);
final SVNStatus status = SvnUtil.getStatus(myVcs, exFile);
boolean theirsExists = new File(myTheirs.getPath(), file.myRelativePath).exists();
if (SVNStatusType.STATUS_UNVERSIONED.equals(file.myNodeStatus)) {
Assert.assertTrue(createTestFailedComment(data, exFile.getPath()) + " (file exists)", exFile.exists());
if (theirsExists) {
// should be deleted
Assert.assertTrue(createTestFailedComment(data, exFile.getPath()) + " (unversioned)", status == null || SVNStatusType.STATUS_DELETED.equals(status.getNodeStatus()));
} else {
// unversioned
Assert.assertTrue(createTestFailedComment(data, exFile.getPath()) + " (unversioned)", status == null || SVNStatusType.STATUS_UNVERSIONED.equals(status.getNodeStatus()));
}
} else if (SVNStatusType.STATUS_DELETED.equals(file.myNodeStatus)) {
Assert.assertTrue(createTestFailedComment(data, exFile.getPath()) + " (deleted status)", status != null && file.myNodeStatus.equals(status.getNodeStatus()));
} else if (SVNStatusType.STATUS_ADDED.equals(file.myNodeStatus)) {
Assert.assertTrue(createTestFailedComment(data, exFile.getPath()) + " (file exists)", exFile.exists());
if (theirsExists) {
Assert.assertTrue(createTestFailedComment(data, exFile.getPath()) + " (added status)", status != null && SVNStatusType.STATUS_REPLACED.equals(status.getNodeStatus()));
} else {
Assert.assertTrue(createTestFailedComment(data, exFile.getPath()) + " (added status)", status != null && SVNStatusType.STATUS_ADDED.equals(status.getNodeStatus()));
}
} else {
if (SVNStatusType.STATUS_ADDED.equals(status.getNodeStatus())) {
// in theirs -> deleted
Assert.assertFalse(createTestFailedComment(data, file.myRelativePath) + " check deleted in theirs", theirsExists);
} else {
if (theirsExists) {
Assert.assertTrue(createTestFailedComment(data, exFile.getPath()) + " (normal node status)", status != null && SVNStatusType.STATUS_REPLACED.equals(status.getNodeStatus()));
} else {
Assert.assertTrue(createTestFailedComment(data, exFile.getPath()) + " (normal node status)", status != null &&
(SVNStatusType.STATUS_NORMAL.equals(status.getNodeStatus()) || SVNStatusType.STATUS_MODIFIED.equals(status.getNodeStatus())));
}
}
Assert.assertTrue(createTestFailedComment(data, exFile.getPath()) + " (modified text status)", status != null && file.myContentsStatus.equals(status.getContentsStatus()));
}
}
}
private String createTestFailedComment(final TreeConflictData.Data data, final String path) {
return "Check failed for test: " + getTestName(data) + " and file: " + path + " in: " + myWorkingCopyDir.getPath();
}
@Test
public void testTheirsFull() throws Exception {
int cnt = 0;
myWorkingCopyDir = createDirInCommand(myWorkingCopyDir, "test--");
myTheirs = createDirInCommand(myTheirs, "theirs--");
// todo debug
//final TreeConflictData.Data data = TreeConflictData.FileToFile.MINE_MOVE_THEIRS_ADD;
for (final TreeConflictData.Data data : TreeConflictData.ourAll) {
if (myTraceClient) {
System.out.println("========= TEST " + getTestName(data) + " =========");
}
myWorkingCopyDir = createDirInCommand(myWorkingCopyDir.getParent(), "test" + cnt);
myTheirs = createDirInCommand(myTheirs.getParent(), "theirs" + cnt);
mySvnClientRunner.checkout(myRepoUrl, myTheirs);
mySvnClientRunner.checkout(myRepoUrl, myWorkingCopyDir);
createSubTree();
final ConflictCreator creator = new ConflictCreator(myProject, myTheirs, myWorkingCopyDir, data, mySvnClientRunner);
creator.create();
myDirtyScopeManager.markEverythingDirty();
myChangeListManager.ensureUpToDate(false);
myDirtyScopeManager.markEverythingDirty();
myChangeListManager.ensureUpToDate(false);
final String conflictFile = data.getConflictFile();
final File conflictIoFile = new File(myWorkingCopyDir.getPath(), conflictFile);
final FilePathImpl filePath = new FilePathImpl(conflictIoFile, conflictIoFile.isDirectory());
final Change change = myChangeListManager.getChange(filePath);
Assert.assertNotNull(change);
Assert.assertTrue(change instanceof ConflictedSvnChange);
final SvnRevisionNumber committedRevision =
change.getBeforeRevision() != null ? (SvnRevisionNumber)change.getBeforeRevision().getRevisionNumber() : null;
FilePath beforePath = null;
if (change.isMoved() || change.isRenamed()) {
beforePath = change.getBeforeRevision().getFile();
}
//SvnRevisionNumber committedRevision = new SvnRevisionNumber(SVNRevision.create(cnt * 2 + 1));
final SvnTreeConflictResolver resolver = new SvnTreeConflictResolver(myVcs, filePath, committedRevision, beforePath);
resolver.resolveSelectTheirsFull(((ConflictedSvnChange) change).getBeforeDescription());
myTheirs.refresh(false, true);
myWorkingCopyDir.refresh(false, true);
VfsUtil.processFileRecursivelyWithoutIgnored(myTheirs, new Processor<VirtualFile>() {
@Override
public boolean process(VirtualFile file) {
final String relative = VfsUtil.getRelativePath(file, myTheirs, File.separatorChar);
File workingFile = new File(myWorkingCopyDir.getPath(), relative);
boolean exists = workingFile.exists();
if (! exists) {
String[] excluded = data.getExcludeFromToTheirsCheck();
if (excluded != null && Arrays.asList(excluded).contains(relative)) {
return true;
}
Assert.assertTrue("Check failed for test: " + getTestName(data) + " and file: " + relative + " in: " + myWorkingCopyDir.getPath(),
exists);
}
SVNInfo theirsInfo = myVcs.getInfo(new File(file.getPath()));
SVNInfo thisInfo = myVcs.getInfo(workingFile);
if (theirsInfo != null) {
Assert.assertEquals("Check failed for test: " + getTestName(data) + " and file: " + relative + " in: " + myWorkingCopyDir.getPath() +
", theirs: " + theirsInfo.getRevision().getNumber() + ", mine: " + thisInfo.getRevision().getNumber(),
theirsInfo.getRevision().getNumber(), thisInfo.getRevision().getNumber());
}
return true;
}
});
++ cnt;
}
}
private String getTestName(final TreeConflictData.Data data) {
Class<?>[] classes = TreeConflictData.class.getDeclaredClasses();
for (Class<?> aClass : classes) {
String s = testFields(data, aClass);
if (s != null) return aClass.getName() + "#" + s;
}
return null;
}
private String testFields(TreeConflictData.Data data, final Class clazz) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
int modifiers = field.getModifiers();
try {
if ((Modifier.STATIC & modifiers) != 0 && data == field.get(null)) {
return field.getName();
}
}
catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
return null;
}
private void createSubTree() throws Exception {
enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
clearWc(false);
mySvnClientRunner.checkin(myWorkingCopyDir);
sleep(10);
final SubTree subTree = new SubTree(myWorkingCopyDir);
mySvnClientRunner.checkin(myWorkingCopyDir);
sleep(10);
mySvnClientRunner.update(myTheirs);
mySvnClientRunner.update(myWorkingCopyDir);
sleep(10);
disableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
disableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
}
private static void sleep(final int millis) {
try {
Thread.sleep(millis);
}
catch (InterruptedException ignore) { }
}
}
@@ -32,8 +32,10 @@ import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.VcsShowConfirmationOption;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.changes.pending.MockChangeListManagerGate;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.AbstractJunitVcsTestCase;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.TestClientRunner;
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
import com.intellij.testFramework.fixtures.TempDirTestFixture;
import com.intellij.testFramework.vcs.MockChangelistBuilder;
@@ -44,6 +46,7 @@ import org.junit.Before;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
@@ -56,6 +59,7 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase {
protected String myRepoUrl;
private ChangeListManagerGate myGate;
protected AtomicSectionsAware myRefreshCopiesStub;
private TestClientRunner myRunner;
protected SvnTestCase() {
PlatformTestCase.initPlatformLangPrefix();
@@ -63,6 +67,8 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase {
@Before
public void setUp() throws Exception {
myRunner = createClientRunner();
//System.setProperty("svnkit.wc.17", "false");
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
@@ -151,7 +157,7 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase {
}
protected ProcessOutput runSvn(String... commandLine) throws IOException {
return runClient("svn", null, myWcRoot, commandLine);
return myRunner.runClient("svn", null, myWcRoot, commandLine);
}
protected void enableSilentOperation(final VcsConfiguration.StandardConfirmation op) {
@@ -191,4 +197,30 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase {
}
});
}
public class SubTree {
protected final VirtualFile myRootDir;
protected VirtualFile mySourceDir;
protected final VirtualFile myTargetDir;
protected VirtualFile myS1File;
protected VirtualFile myS2File;
protected final List<VirtualFile> myTargetFiles;
protected static final String ourS1Contents = "123";
protected static final String ourS2Contents = "abc";
protected SubTree(final VirtualFile base) throws Exception {
myRootDir = createDirInCommand(base, "root");
mySourceDir = createDirInCommand(myRootDir, "source");
myS1File = createFileInCommand(mySourceDir, "s1.txt", ourS1Contents);
myS2File = createFileInCommand(mySourceDir, "s2.txt", ourS2Contents);
myTargetDir = createDirInCommand(myRootDir, "target");
myTargetFiles = new ArrayList<VirtualFile>();
for (int i = 0; i < 10; i++) {
myTargetFiles.add(createFileInCommand(myTargetDir, "t" + (i+10) +".txt", ourS1Contents));
}
}
}
}
@@ -0,0 +1,828 @@
/*
* Copyright 2000-2012 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 org.jetbrains.idea.svn;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.openapi.vcs.VcsConfiguration;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.TestClientRunner;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.internal.wc.SVNConflictVersion;
import org.tmatesoft.svn.core.wc.SVNConflictAction;
import org.tmatesoft.svn.core.wc.SVNOperation;
import org.tmatesoft.svn.core.wc.SVNTreeConflictDescription;
import java.io.File;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 5/2/12
* Time: 2:01 PM
*/
public class SvnTreeConflictDataTest extends SvnTestCase {
private VirtualFile myTheirs;
private SvnClientRunnerImpl mySvnClientRunner;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
disableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
myTheirs = myTempDirFixture.findOrCreateDir("theirs");
final TestClientRunner testClientRunner = new TestClientRunner(true, myClientBinaryPath);
mySvnClientRunner = new SvnClientRunnerImpl(testClientRunner);
mySvnClientRunner.checkout(myRepoUrl, myTheirs);
}
@Test
public void testFile2File_MINE_UNV_THEIRS_ADD() throws Exception {
final ConflictCreator creator = new ConflictCreator(myProject, myTheirs, myWorkingCopyDir,
TreeConflictData.FileToFile.MINE_UNV_THEIRS_ADD, mySvnClientRunner);
creator.create();
final String conflictFile = TreeConflictData.FileToFile.MINE_UNV_THEIRS_ADD.getConflictFile();
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
Assert.assertNull(beforeDescription.getSourceLeftVersion());
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.FILE, version.getKind());
}
@Test
public void testFile2File_MINE_EDIT_THEIRS_DELETE() throws Exception {
final String conflictFile = createConflict(TreeConflictData.FileToFile.MINE_EDIT_THEIRS_DELETE);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.DELETE, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNotNull(leftVersion);
Assert.assertEquals(SVNNodeKind.FILE, leftVersion.getKind());
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.NONE, version.getKind());
}
private String createConflict(final TreeConflictData.Data data) throws Exception {
createSubTree();
final ConflictCreator creator = new ConflictCreator(myProject, myTheirs, myWorkingCopyDir, data, mySvnClientRunner);
creator.create();
return data.getConflictFile();
}
@Test
public void testFile2File_MINE_DELETE_THEIRS_EDIT() throws Exception {
final String conflictFile = createConflict(TreeConflictData.FileToFile.MINE_DELETE_THEIRS_EDIT);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.EDIT, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNotNull(leftVersion);
Assert.assertEquals(SVNNodeKind.FILE, leftVersion.getKind());
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.FILE, version.getKind());
}
@Test
public void testFile2File_MINE_EDIT_THEIRS_MOVE() throws Exception {
final String conflictFile = createConflict(TreeConflictData.FileToFile.MINE_EDIT_THEIRS_MOVE);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.DELETE, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNotNull(leftVersion);
Assert.assertEquals(SVNNodeKind.FILE, leftVersion.getKind());
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.NONE, version.getKind());
}
@Test
public void testFile2File_MINE_UNV_THEIRS_MOVE() throws Exception {
final String conflictFile = createConflict(TreeConflictData.FileToFile.MINE_UNV_THEIRS_MOVE);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNull(leftVersion);
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.FILE, version.getKind());
}
@Test
public void testFile2File_MINE_MOVE_THEIRS_EDIT() throws Exception {
final String conflictFile = createConflict(TreeConflictData.FileToFile.MINE_MOVE_THEIRS_EDIT);
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.EDIT, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNotNull(leftVersion);
Assert.assertEquals(SVNNodeKind.FILE, leftVersion.getKind());
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.FILE, version.getKind());
}
@Test
public void testFile2File_MINE_MOVE_THEIRS_ADD() throws Exception {
final String conflictFile = createConflict(TreeConflictData.FileToFile.MINE_MOVE_THEIRS_ADD);
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNull(leftVersion);
//Assert.assertEquals(SVNNodeKind.FILE, leftVersion.getKind());
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.FILE, version.getKind());
}
//---------------------------------- dirs --------------------------------------------------------
@Test
public void testDir2Dir_MINE_UNV_THEIRS_ADD() throws Exception {
final String conflictFile = createConflict(TreeConflictData.DirToDir.MINE_UNV_THEIRS_ADD);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNull(leftVersion);
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.DIR, version.getKind());
}
@Test
public void testDir2Dir_MINE_EDIT_THEIRS_DELETE() throws Exception {
final String conflictFile = createConflict(TreeConflictData.DirToDir.MINE_EDIT_THEIRS_DELETE);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.DELETE, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNotNull(leftVersion);
Assert.assertEquals(SVNNodeKind.DIR, leftVersion.getKind());
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.NONE, version.getKind());
}
@Test
public void testDir2Dir_MINE_DELETE_THEIRS_EDIT() throws Exception {
final String conflictFile = createConflict(TreeConflictData.DirToDir.MINE_DELETE_THEIRS_EDIT);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
changeListManager.ensureUpToDate(false);
final Change change = changeListManager.getChange(new FilePathImpl(new File(myWorkingCopyDir.getPath(), conflictFile), true));
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.EDIT, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNotNull(leftVersion);
Assert.assertEquals(SVNNodeKind.DIR, leftVersion.getKind());
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.DIR, version.getKind());
}
@Test
public void testDir2Dir_MINE_EDIT_THEIRS_MOVE() throws Exception {
final String conflictFile = createConflict(TreeConflictData.DirToDir.MINE_EDIT_THEIRS_MOVE);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.DELETE, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNotNull(leftVersion);
Assert.assertEquals(SVNNodeKind.DIR, leftVersion.getKind());
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.NONE, version.getKind());
}
@Test
public void testDir2Dir_MINE_UNV_THEIRS_MOVE() throws Exception {
final String conflictFile = createConflict(TreeConflictData.DirToDir.MINE_UNV_THEIRS_MOVE);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNull(leftVersion);
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.DIR, version.getKind());
}
@Test
public void testDir2Dir_MINE_MOVE_THEIRS_EDIT() throws Exception {
final String conflictFile = createConflict(TreeConflictData.DirToDir.MINE_MOVE_THEIRS_EDIT);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
changeListManager.ensureUpToDate(false);
final Change change = changeListManager.getChange(new FilePathImpl(new File(myWorkingCopyDir.getPath(), conflictFile), true));
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.EDIT, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNotNull(leftVersion);
Assert.assertEquals(SVNNodeKind.DIR, leftVersion.getKind());
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.DIR, version.getKind());
}
@Test
public void testDir2Dir_MINE_MOVE_THEIRS_ADD() throws Exception {
final String conflictFile = createConflict(TreeConflictData.DirToDir.MINE_MOVE_THEIRS_ADD);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
changeListManager.ensureUpToDate(false);
final Change change = changeListManager.getChange(new FilePathImpl(new File(myWorkingCopyDir.getPath(), conflictFile), true));
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNotNull(leftVersion);
Assert.assertEquals(SVNNodeKind.DIR, leftVersion.getKind());
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.DIR, version.getKind());
}
//---------------------------------
@Test
public void testFile2Dir_MINE_UNV_THEIRS_ADD() throws Exception {
final String conflictFile = createConflict(TreeConflictData.FileToDir.MINE_UNV_THEIRS_ADD);
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNull(leftVersion);
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.DIR, version.getKind());
}
@Test
public void testFile2Dir_MINE_ADD_THEIRS_ADD() throws Exception {
final String conflictFile = createConflict(TreeConflictData.FileToDir.MINE_ADD_THEIRS_ADD);
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNull(leftVersion);
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.DIR, version.getKind());
}
@Test
public void testFile2Dir_MINE_UNV_THEIRS_MOVE() throws Exception {
final String conflictFile = createConflict(TreeConflictData.FileToDir.MINE_UNV_THEIRS_MOVE);
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNull(leftVersion);
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.DIR, version.getKind());
}
@Test
public void testFile2Dir_MINE_ADD_THEIRS_MOVE() throws Exception {
final String conflictFile = createConflict(TreeConflictData.FileToDir.MINE_ADD_THEIRS_MOVE);
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNull(leftVersion);
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.DIR, version.getKind());
}
@Test
public void testFile2Dir_MINE_MOVE_THEIRS_ADD() throws Exception {
final String conflictFile = createConflict(TreeConflictData.FileToDir.MINE_MOVE_THEIRS_ADD);
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNull(leftVersion);
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.DIR, version.getKind());
}
//******************************************
// dir -> file (mine, theirs)
@Test
public void testDir2File_MINE_UNV_THEIRS_ADD() throws Exception {
final String conflictFile = createConflict(TreeConflictData.DirToFile.MINE_UNV_THEIRS_ADD);
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNull(leftVersion);
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.FILE, version.getKind());
}
@Test
public void testDir2File_MINE_ADD_THEIRS_ADD() throws Exception {
final String conflictFile = createConflict(TreeConflictData.DirToFile.MINE_ADD_THEIRS_ADD);
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNull(leftVersion);
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.FILE, version.getKind());
}
@Test
public void testDir2File_MINE_UNV_THEIRS_MOVE() throws Exception {
final String conflictFile = createConflict(TreeConflictData.DirToFile.MINE_UNV_THEIRS_MOVE);
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNull(leftVersion);
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.FILE, version.getKind());
}
@Test
public void testDir2File_MINE_ADD_THEIRS_MOVE() throws Exception {
final String conflictFile = createConflict(TreeConflictData.DirToFile.MINE_ADD_THEIRS_MOVE);
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNull(leftVersion);
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.FILE, version.getKind());
}
@Test
public void testDir2File_MINE_MOVE_THEIRS_ADD() throws Exception {
final String conflictFile = createConflict(TreeConflictData.DirToFile.MINE_MOVE_THEIRS_ADD);
ChangeListManager changeListManager = ChangeListManager.getInstance(myProject);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VcsDirtyScopeManager.getInstance(myProject).markEverythingDirty();
changeListManager.ensureUpToDate(false);
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myWorkingCopyDir.getPath(), conflictFile));
Assert.assertNotNull(vf);
final Change change = changeListManager.getChange(vf);
Assert.assertTrue(change instanceof ConflictedSvnChange);
SVNTreeConflictDescription beforeDescription = ((ConflictedSvnChange)change).getBeforeDescription();
Assert.assertNotNull(beforeDescription);
final SVNTreeConflictDescription afterDescription = ((ConflictedSvnChange)change).getAfterDescription();
Assert.assertNull(afterDescription);
Assert.assertEquals(SVNOperation.UPDATE, beforeDescription.getOperation());
Assert.assertEquals(SVNConflictAction.ADD, beforeDescription.getConflictAction());
Assert.assertTrue(beforeDescription.isTreeConflict());
SVNConflictVersion leftVersion = beforeDescription.getSourceLeftVersion();
Assert.assertNull(leftVersion);
final SVNConflictVersion version = beforeDescription.getSourceRightVersion();
Assert.assertNotNull(version);
Assert.assertEquals(SVNNodeKind.FILE, version.getKind());
}
private void createSubTree() throws Exception {
enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
final SubTree subTree = new SubTree(myWorkingCopyDir);
mySvnClientRunner.checkin(myWorkingCopyDir);
sleep(10);
mySvnClientRunner.update(myTheirs);
mySvnClientRunner.update(myWorkingCopyDir);
sleep(10);
disableSilentOperation(VcsConfiguration.StandardConfirmation.ADD);
disableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE);
}
private static void sleep(final int millis) {
try {
Thread.sleep(millis);
}
catch (InterruptedException ignore) { }
}
}
@@ -0,0 +1,455 @@
/*
* Copyright 2000-2012 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 org.jetbrains.idea.svn;
import org.tmatesoft.svn.core.wc.SVNStatusType;
import java.util.*;
/**
* Created with IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 5/2/12
* Time: 1:11 PM
*/
public interface TreeConflictData {
Data[] ourAll = new Data[] {
FileToFile.MINE_DELETE_THEIRS_EDIT, FileToFile.MINE_EDIT_THEIRS_DELETE, FileToFile.MINE_EDIT_THEIRS_MOVE,
FileToFile.MINE_UNV_THEIRS_ADD, FileToFile.MINE_UNV_THEIRS_MOVE, FileToFile.MINE_MOVE_THEIRS_EDIT,
FileToFile.MINE_MOVE_THEIRS_ADD,
DirToDir.MINE_DELETE_THEIRS_EDIT, DirToDir.MINE_EDIT_THEIRS_DELETE, DirToDir.MINE_EDIT_THEIRS_MOVE,
DirToDir.MINE_UNV_THEIRS_ADD, DirToDir.MINE_UNV_THEIRS_MOVE, DirToDir.MINE_MOVE_THEIRS_EDIT,
DirToDir.MINE_MOVE_THEIRS_ADD,
DirToFile.MINE_ADD_THEIRS_ADD, DirToFile.MINE_ADD_THEIRS_MOVE, DirToFile.MINE_UNV_THEIRS_ADD,
DirToFile.MINE_UNV_THEIRS_MOVE, DirToFile.MINE_MOVE_THEIRS_ADD,
FileToDir.MINE_ADD_THEIRS_ADD, FileToDir.MINE_ADD_THEIRS_MOVE, FileToDir.MINE_UNV_THEIRS_ADD,
FileToDir.MINE_UNV_THEIRS_MOVE, FileToDir.MINE_MOVE_THEIRS_ADD};
interface FileToFile {
Data MINE_UNV_THEIRS_ADD = new Data("Index: added.txt\n" +
"===================================================================\n" +
"--- added.txt\t(revision )\n" +
"+++ added.txt\t(revision )\n" +
"@@ -0,0 +1,1 @@\n" +
"+added text\n" +
"\\ No newline at end of file\n",
"added.txt", new FileData[]{new FileData("added.txt", "unversioned text", SVNStatusType.STATUS_UNVERSIONED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
false)});
Data MINE_EDIT_THEIRS_DELETE = new Data("Index: root/source/s1.txt\n" +
"===================================================================\n" +
"--- root/source/s1.txt\t(revision 358)\n" +
"+++ root/source/s1.txt\t(revision 358)\n" +
"@@ -1,1 +0,0 @@\n" +
"-123\n" +
"\\ No newline at end of file\n", "root/source/s1.txt",
new FileData[] {new FileData("root/source/s1.txt", "1*2*3", SVNStatusType.STATUS_NORMAL,
SVNStatusType.STATUS_MODIFIED, SVNStatusType.STATUS_NORMAL, false)});
Data MINE_DELETE_THEIRS_EDIT = new Data("Index: root/source/s1.txt\n" +
"===================================================================\n" +
"--- root/source/s1.txt\t(revision 358)\n" +
"+++ root/source/s1.txt\t(revision )\n" +
"@@ -1,1 +1,1 @@\n" +
"-123\n" +
"\\ No newline at end of file\n" +
"+1*2*3\n" +
"\\ No newline at end of file\n", "root/source/s1.txt",
new FileData[] {new FileData("root/source/s1.txt", null, SVNStatusType.STATUS_DELETED,
SVNStatusType.STATUS_DELETED, SVNStatusType.STATUS_DELETED, false)});
Data MINE_EDIT_THEIRS_MOVE = new Data("Index: root/source/s1.txt\n" +
"===================================================================\n" +
"--- root/source/s1.txt\t(revision 358)\n" +
"+++ root/source/s1renamed.txt\t(revision )\n" +
"@@ -1,0 +1,0 @@\n", "root/source/s1.txt",
new FileData[] {new FileData("root/source/s1.txt", "1*2*3", SVNStatusType.STATUS_NORMAL,
SVNStatusType.STATUS_MODIFIED, SVNStatusType.STATUS_NORMAL, false)});
Data MINE_UNV_THEIRS_MOVE = new Data("Index: root/source/s1.txt\n" +
"===================================================================\n" +
"--- root/source/s1.txt\t(revision 358)\n" +
"+++ root/source/s1renamed.txt\t(revision )\n" +
"@@ -1,0 +1,0 @@\n", "root/source/s1renamed.txt",
new FileData[] {new FileData("root/source/s1renamed.txt", "1*2*3", SVNStatusType.STATUS_UNVERSIONED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
false)});
Data MINE_MOVE_THEIRS_EDIT = new Data("Index: root/source/s1.txt\n" +
"===================================================================\n" +
"--- root/source/s1.txt\t(revision 358)\n" +
"+++ root/source/s1.txt\t(revision )\n" +
"@@ -1,1 +1,1 @@\n" +
"-123\n" +
"\\ No newline at end of file\n" +
"+1*2*3\n" +
// conflict would be marked by svn on s1.txt, but here we put s1moved.txt, for change list manager to find the change
"\\ No newline at end of file\n", "root/source/s1moved.txt",
new FileData[] {new FileData("root/source/s1moved.txt", null, SVNStatusType.STATUS_ADDED,
SVNStatusType.STATUS_ADDED, SVNStatusType.STATUS_ADDED, false, "root/source/s1.txt"),
new FileData("root/source/s1.txt", null, SVNStatusType.STATUS_DELETED,
SVNStatusType.STATUS_DELETED, SVNStatusType.STATUS_DELETED, false)});
Data MINE_MOVE_THEIRS_ADD = new Data("Index: root/source/s1moved.txt\n" +
"===================================================================\n" +
"--- root/source/s1moved.txt\t(revision )\n" +
"+++ root/source/s1moved.txt\t(revision )\n" +
"@@ -0,0 +1,1 @@\n" +
"+added text\n" +
"\\ No newline at end of file\n",
"root/source/s1moved.txt",
new FileData[] {new FileData("root/source/s1moved.txt", null, SVNStatusType.STATUS_ADDED,
SVNStatusType.STATUS_ADDED, SVNStatusType.STATUS_ADDED, false, "root/source/s1.txt"),
new FileData("root/source/s1.txt", null, SVNStatusType.STATUS_DELETED,
SVNStatusType.STATUS_DELETED, SVNStatusType.STATUS_DELETED, false)}) {
@Override
protected void afterInit() {
setExcludeFromToTheirsCheck("root\\source\\s1.txt");
}
};
}
interface DirToDir {
Data MINE_UNV_THEIRS_ADD = new Data("Index: addedDir/added.txt\n" +
"===================================================================\n" +
"--- addedDir/added.txt\t(revision )\n" +
"+++ addedDir/added.txt\t(revision )\n" +
"@@ -0,0 +1,1 @@\n" +
"+added text\n" +
"\\ No newline at end of file\n",
"addedDir", new FileData[]{new FileData("addedDir", null, SVNStatusType.STATUS_UNVERSIONED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
true),
new FileData("addedDir/unv.txt", "unversioned", SVNStatusType.STATUS_UNVERSIONED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
false)});
Data MINE_EDIT_THEIRS_DELETE = new Data("Index: root/source/s1.txt\n" +
"===================================================================\n" +
"--- root/source/s1.txt\t(revision 358)\n" +
"+++ root/source/s1.txt\t(revision 358)\n" +
"@@ -1,1 +0,0 @@\n" +
"-123\n" +
"\\ No newline at end of file\n" +
"Index: root/source/s2.txt\n" +
"===================================================================\n" +
"--- root/source/s2.txt\t(revision 358)\n" +
"+++ root/source/s2.txt\t(revision 358)\n" +
"@@ -1,1 +0,0 @@\n" +
"-abc\n" +
"\\ No newline at end of file\n", "root/source",
new FileData[] {new FileData("root/source/s1.txt", "1*2*3", SVNStatusType.STATUS_NORMAL,
SVNStatusType.STATUS_MODIFIED, SVNStatusType.STATUS_NORMAL, false)});
Data MINE_DELETE_THEIRS_EDIT = new Data("Index: root/source/s1.txt\n" +
"===================================================================\n" +
"--- root/source/s1.txt\t(revision 358)\n" +
"+++ root/source/s1.txt\t(revision )\n" +
"@@ -1,1 +1,1 @@\n" +
"-123\n" +
"\\ No newline at end of file\n" +
"+1*2*3\n" +
"\\ No newline at end of file\n", "root/source",
new FileData[] {new FileData("root/source", null, SVNStatusType.STATUS_DELETED,
SVNStatusType.STATUS_DELETED, SVNStatusType.STATUS_DELETED, true)});
Data MINE_EDIT_THEIRS_MOVE = new Data(
"Index: root/source/s1.txt\n" +
"===================================================================\n" +
"--- root/source/s1.txt\t(revision 358)\n" +
"+++ root/source1/s1.txt\t(revision )\n" +
"@@ -1,0 +1,0 @@\n" +
"Index: root/source/s2.txt\n" +
"===================================================================\n" +
"--- root/source/s2.txt\t(revision 358)\n" +
"+++ root/source1/s2.txt\t(revision )\n" +
"@@ -1,0 +1,0 @@\n",
"root/source",
new FileData[] {new FileData("root/source/s1.txt", "1*2*3", SVNStatusType.STATUS_NORMAL,
SVNStatusType.STATUS_MODIFIED, SVNStatusType.STATUS_NORMAL, false)});
Data MINE_UNV_THEIRS_MOVE = new Data(
"Index: root/source/s1.txt\n" +
"===================================================================\n" +
"--- root/source/s1.txt\t(revision 358)\n" +
"+++ root/source1/s1.txt\t(revision )\n" +
"@@ -1,0 +1,0 @@\n" +
"Index: root/source/s2.txt\n" +
"===================================================================\n" +
"--- root/source/s2.txt\t(revision 358)\n" +
"+++ root/source1/s2.txt\t(revision )\n" +
"@@ -1,0 +1,0 @@\n", "root/source1",
new FileData[] {new FileData("root/source1", null, SVNStatusType.STATUS_UNVERSIONED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
true),
new FileData("root/source1/unv.txt", "unversioned", SVNStatusType.STATUS_UNVERSIONED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
false)});
Data MINE_MOVE_THEIRS_EDIT = new Data("Index: root/source/s1.txt\n" +
"===================================================================\n" +
"--- root/source/s1.txt\t(revision 358)\n" +
"+++ root/source/s1.txt\t(revision )\n" +
"@@ -1,1 +1,1 @@\n" +
"-123\n" +
"\\ No newline at end of file\n" +
"+1*2*3\n" +
"\\ No newline at end of file\n", "root/source",
new FileData[] {
new FileData("root/sourceNew", null, SVNStatusType.STATUS_ADDED,
SVNStatusType.STATUS_ADDED, SVNStatusType.STATUS_ADDED, true, "root/source"),
new FileData("root/source", null, SVNStatusType.STATUS_DELETED,
SVNStatusType.STATUS_DELETED, SVNStatusType.STATUS_DELETED, true)});
Data MINE_MOVE_THEIRS_ADD = new Data("Index: root/sourceNew/added.txt\n" +
"===================================================================\n" +
"--- root/sourceNew/added.txt\t(revision )\n" +
"+++ root/sourceNew/added.txt\t(revision )\n" +
"@@ -0,0 +1,1 @@\n" +
"+added text\n" +
"\\ No newline at end of file\n", "root/sourceNew",
new FileData[] {
new FileData("root/sourceNew", null, SVNStatusType.STATUS_ADDED,
SVNStatusType.STATUS_ADDED, SVNStatusType.STATUS_ADDED, true, "root/source"),
new FileData("root/source", null, SVNStatusType.STATUS_DELETED,
SVNStatusType.STATUS_DELETED, SVNStatusType.STATUS_DELETED, true)}) {
@Override
protected void afterInit() {
setExcludeFromToTheirsCheck("root\\source", "root\\source\\s1.txt", "root\\source\\s2.txt");
}
};
}
// mine -> theirs
interface FileToDir {
Data MINE_UNV_THEIRS_ADD = new Data("Index: addedDir/added.txt\n" +
"===================================================================\n" +
"--- addedDir/added.txt\t(revision )\n" +
"+++ addedDir/added.txt\t(revision )\n" +
"@@ -0,0 +1,1 @@\n" +
"+added text\n" +
"\\ No newline at end of file\n",
"addedDir", new FileData[]{new FileData("addedDir", "unversioned", SVNStatusType.STATUS_UNVERSIONED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
false)});
Data MINE_ADD_THEIRS_ADD = new Data("Index: addedDir/added.txt\n" +
"===================================================================\n" +
"--- addedDir/added.txt\t(revision )\n" +
"+++ addedDir/added.txt\t(revision )\n" +
"@@ -0,0 +1,1 @@\n" +
"+added text\n" +
"\\ No newline at end of file\n",
"addedDir", new FileData[]{new FileData("addedDir", "unversioned", SVNStatusType.STATUS_ADDED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
false)});
Data MINE_UNV_THEIRS_MOVE = new Data( "Index: root/source/s1.txt\n" +
"===================================================================\n" +
"--- root/source/s1.txt\t(revision 358)\n" +
"+++ root/source1/s1.txt\t(revision )\n" +
"@@ -1,0 +1,0 @@\n" +
"Index: root/source/s2.txt\n" +
"===================================================================\n" +
"--- root/source/s2.txt\t(revision 358)\n" +
"+++ root/source1/s2.txt\t(revision )\n" +
"@@ -1,0 +1,0 @@\n",
"root/source1", new FileData[]{new FileData("root/source1", "unversioned", SVNStatusType.STATUS_UNVERSIONED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
false)});
Data MINE_ADD_THEIRS_MOVE = new Data( "Index: root/source/s1.txt\n" +
"===================================================================\n" +
"--- root/source/s1.txt\t(revision 358)\n" +
"+++ root/source1/s1.txt\t(revision )\n" +
"@@ -1,0 +1,0 @@\n" +
"Index: root/source/s2.txt\n" +
"===================================================================\n" +
"--- root/source/s2.txt\t(revision 358)\n" +
"+++ root/source1/s2.txt\t(revision )\n" +
"@@ -1,0 +1,0 @@\n",
"root/source1", new FileData[]{new FileData("root/source1", "unversioned", SVNStatusType.STATUS_ADDED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
false)});
Data MINE_MOVE_THEIRS_ADD = new Data("Index: addedDir/added.txt\n" +
"===================================================================\n" +
"--- addedDir/added.txt\t(revision )\n" +
"+++ addedDir/added.txt\t(revision )\n" +
"@@ -0,0 +1,1 @@\n" +
"+added text\n" +
"\\ No newline at end of file\n",
"addedDir", new FileData[]{new FileData("addedDir", null, SVNStatusType.STATUS_ADDED,
SVNStatusType.STATUS_ADDED, SVNStatusType.STATUS_ADDED,
false, "root/source/s1.txt"),
new FileData("root/source/s1.txt", null, SVNStatusType.STATUS_DELETED,
SVNStatusType.STATUS_DELETED, SVNStatusType.STATUS_DELETED,
false, null)}) {
@Override
protected void afterInit() {
setExcludeFromToTheirsCheck("root\\source\\s1.txt");
}
};
}
// mine -> theirs
interface DirToFile {
Data MINE_UNV_THEIRS_ADD = new Data("Index: addedDir.txt\n" +
"===================================================================\n" +
"--- addedDir.txt\t(revision )\n" +
"+++ addedDir.txt\t(revision )\n" +
"@@ -0,0 +1,1 @@\n" +
"+added text\n" +
"\\ No newline at end of file\n",
"addedDir.txt", new FileData[]{new FileData("addedDir.txt", null, SVNStatusType.STATUS_UNVERSIONED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
true),
new FileData("addedDir.txt/unv.txt", "unversioned", SVNStatusType.STATUS_UNVERSIONED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
false)});
Data MINE_ADD_THEIRS_ADD = new Data("Index: addedDir.txt\n" +
"===================================================================\n" +
"--- addedDir.txt\t(revision )\n" +
"+++ addedDir.txt\t(revision )\n" +
"@@ -0,0 +1,1 @@\n" +
"+added text\n" +
"\\ No newline at end of file\n",
"addedDir.txt", new FileData[]{new FileData("addedDir.txt", null, SVNStatusType.STATUS_ADDED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
true),
new FileData("addedDir.txt/unv.txt", "unversioned", SVNStatusType.STATUS_ADDED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
false)});
Data MINE_UNV_THEIRS_MOVE = new Data( "Index: root/source/s1.txt\n" +
"===================================================================\n" +
"--- root/source/s1.txt\t(revision 358)\n" +
"+++ root/source/s1renamed.txt\t(revision )\n" +
"@@ -1,0 +1,0 @@\n" +
"\\ No newline at end of file\n",
"root/source/s1renamed.txt", new FileData[]{new FileData("root/source/s1renamed.txt", null,
SVNStatusType.STATUS_UNVERSIONED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
true),
new FileData("root/source/s1renamed.txt/file.txt", "unversioned",
SVNStatusType.STATUS_UNVERSIONED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
false)});
Data MINE_ADD_THEIRS_MOVE = new Data( "Index: root/source/s1.txt\n" +
"===================================================================\n" +
"--- root/source/s1.txt\t(revision 358)\n" +
"+++ root/source/s1renamed.txt\t(revision )\n" +
"@@ -1,0 +1,0 @@\n" +
"\\ No newline at end of file\n",
"root/source/s1renamed.txt", new FileData[]{new FileData("root/source/s1renamed.txt", null,
SVNStatusType.STATUS_ADDED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
true),
new FileData("root/source/s1renamed.txt/file.txt", "unversioned",
SVNStatusType.STATUS_ADDED,
SVNStatusType.STATUS_UNVERSIONED, SVNStatusType.STATUS_UNVERSIONED,
false)});
Data MINE_MOVE_THEIRS_ADD = new Data("Index: addedDir.txt\n" +
"===================================================================\n" +
"--- addedDir.txt\t(revision )\n" +
"+++ addedDir.txt\t(revision )\n" +
"@@ -0,0 +1,1 @@\n" +
"+added text\n" +
"\\ No newline at end of file\n",
"addedDir.txt", new FileData[]{new FileData("addedDir.txt", null, SVNStatusType.STATUS_ADDED,
SVNStatusType.STATUS_ADDED, SVNStatusType.STATUS_ADDED, true, "root/source"),
new FileData("root/source", null, SVNStatusType.STATUS_DELETED,
SVNStatusType.STATUS_DELETED, SVNStatusType.STATUS_DELETED, true)}) {
@Override
protected void afterInit() {
setExcludeFromToTheirsCheck("root\\source", "root\\source\\s1.txt", "root\\source\\s2.txt");
}
};
}
class Data {
private final Collection<FileData> myFileData;
private final String myPatch;
private final String myConflictFile;
private String[] myExcludeFromToTheirsCheck;
public Data(String patch, String file, FileData... fileData) {
myConflictFile = file;
myFileData = new ArrayList<FileData>(Arrays.asList(fileData));
myPatch = patch;
afterInit();
}
protected void afterInit() {
}
Collection<FileData> getLeftFiles() {
return myFileData;
}
String getTheirsPatch() {
return myPatch;
}
public String getConflictFile() {
return myConflictFile;
}
public String[] getExcludeFromToTheirsCheck() {
return myExcludeFromToTheirsCheck;
}
public void setExcludeFromToTheirsCheck(String... excludeFromToTheirsCheck) {
myExcludeFromToTheirsCheck = excludeFromToTheirsCheck;
}
}
class FileData {
public final String myRelativePath;
public final String myContents;
public final String myCopyFrom;
public final SVNStatusType myNodeStatus;
public final SVNStatusType myContentsStatus;
// not used for now
public final SVNStatusType myPropertiesStatus;
public boolean myIsDir;
public FileData(String relativePath,
String contents,
SVNStatusType nodeStatus,
SVNStatusType contentsStatus,
SVNStatusType propertiesStatus,
boolean isDir) {
this(relativePath, contents, nodeStatus, contentsStatus, propertiesStatus, isDir, null);
}
public FileData(String relativePath,
String contents,
SVNStatusType nodeStatus,
SVNStatusType contentsStatus,
SVNStatusType propertiesStatus,
boolean isDir, final String copyFrom) {
myRelativePath = relativePath;
myContents = contents;
myNodeStatus = nodeStatus;
myContentsStatus = contentsStatus;
myPropertiesStatus = propertiesStatus;
myIsDir = isDir;
myCopyFrom = copyFrom;
}
}
}
@@ -153,7 +153,7 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase {
}
protected ProcessOutput runSvn(String... commandLine) throws IOException {
return runClient("svn", null, myWcRoot, commandLine);
return createClientRunner().runClient("svn", null, myWcRoot, commandLine);
}
protected void enableSilentOperation(final VcsConfiguration.StandardConfirmation op) {