Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[subversive-dev] Some more bugs with "compare with branch"

Hi,

starting with subversive 3.0.4, we encountered a few bugs and glitches
that seem to come from the fix for bug [484929] (Weird behavior of the
"Compare with branch" feature).
Even though each of these problems should be declared as separate bug
reports I guess it would be interesting to have them all described here
since they will probably be fixed all at once.

The attached file svnrepo.tar.gz is a sample svn repository that I use
to describe some of the use cases below.
All the tests were made with Eclipse Mars, SVNKit connector 1.8, under
linux (and sometimes under Windows when specified).


1. compare with branch lists files with no actual differences

This is already described in bug [326694].
To reproduce this, checkout the trunk from the attached svnrepo and use
compare with branch -> 'mybranch'.
You'll see the file Main.java listed and when you double-click on it, no
differences are shown.
I wrote a dirty patch for subversive-2.0.4 (see attached file
remove-false-diffs-from-compare-view.patch).


2. new local files are not listed

Before 3.0.4, comparing with a branch would list new local files in
compare editor.
This is not true anymore.
To reproduce this, create a new file, for instance src/Foo.java.
Then compare with branch "mybranch" once again and you won't see the new
file listed in compare editor.

Adding the new file to version control solves the problem and is
actually the behavior of the svn command line client (which I consider
as a reference).
But I'm afraid users will consider this is a regression however.


3. changes with wrong direction

As said in a previous discussion ([msg00269] and [msg00273]) the patch
is not perfect because we loose the information concerning the
"direction" of changes.
Is there a way to improve this?
I think it really needs to be fixed because it can be really confusing.


4. a file existing in branch but not in trunk

A file existing in branch but not in trunk is listed as outgoing deletion.
Then double-clicking it throws popup with this message:
    Get content for 'Baz.java' failed.
    svn: E200005: '/tmp/eclipse/ws/fakeproject/src/Baz.java' is not
under version control


5. NPE on windows

This is the bug already reported as [SVNKIT-646].
I recently attached a patch to the bug report (I forgot to create an
account before posting therefore my comment was posted as user Guest).


I'm happy to help on these topics.
Actually I already created some patches for our customers using
subversive 2.0.4 as you can see.
But I'm not 100% confident on these patches because Eclipse is a big
piece of software and I'm still new to plugin development.


[326694]: https://bugs.eclipse.org/bugs/show_bug.cgi?id=326694
[484929]: https://bugs.eclipse.org/bugs/show_bug.cgi?id=484929
[msg00269]:
http://dev.eclipse.org/mhonarc/lists/subversive-dev/msg00269.html
[msg00273]:
http://dev.eclipse.org/mhonarc/lists/subversive-dev/msg00273.html
[SVNKIT-646]: https://issues.tmatesoft.com/issue/SVNKIT-646


-- 
Florent Angebault
Linagora - Support OSSA
https://www.08000linux.com/

Attachment: svnrepo.tar.gz
Description: application/gzip

diff -u b/org.eclipse.team.svn.ui/src/org/eclipse/team/svn/ui/operation/CompareResourcesInternalOperation.java b/org.eclipse.team.svn.ui/src/org/eclipse/team/svn/ui/operation/CompareResourcesInternalOperation.java
--- b/org.eclipse.team.svn.ui/src/org/eclipse/team/svn/ui/operation/CompareResourcesInternalOperation.java
+++ b/org.eclipse.team.svn.ui/src/org/eclipse/team/svn/ui/operation/CompareResourcesInternalOperation.java
@@ -22,9 +22,6 @@
 import java.io.OutputStream;
 import java.io.StringWriter;
 import java.lang.reflect.InvocationTargetException;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.rmi.RemoteException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -225,6 +224,8 @@
 	protected void fetchStatuses18(final ISVNConnector proxy, final ArrayList<SVNDiffStatus> localChanges, final ArrayList<SVNDiffStatus> remoteChanges, final IProgressMonitor monitor) {
 		this.protectStep(new IUnprotectedOperation() {
 			public void run(IProgressMonitor monitor) throws Exception {
+				final Map<SVNDiffStatus, IResource> localChangesMap = new LinkedHashMap<SVNDiffStatus, IResource>();
+				final Map<SVNDiffStatus, IResource> remoteChangesMap = new LinkedHashMap<SVNDiffStatus, IResource>();
 				final IContainer compareRoot = 
 					CompareResourcesInternalOperation.this.local instanceof ILocalFolder ? 
 					(IContainer)CompareResourcesInternalOperation.this.local.getResource() : 
@@ -242,20 +243,82 @@
 							resource = status.nodeKind == SVNEntry.Kind.FILE ? compareRoot.getFile(tPath) : compareRoot.getFolder(tPath);
 						}
 						if (IStateFilter.SF_ANY_CHANGE.accept(SVNRemoteStorage.instance().asLocalResource(resource))) {
-							localChanges.add(status);
+							localChangesMap.put(status, resource);
 						}
 						else {
 							String pathPrev = CompareResourcesInternalOperation.this.ancestor.getUrl() + status.pathNext.substring(refNext.path.length());
 							SVNDiffStatus newStatus = new SVNDiffStatus(pathPrev, status.pathNext, status.nodeKind, status.textStatus, status.propStatus);
-							remoteChanges.add(newStatus);
+							remoteChangesMap.put(newStatus, resource);
 						}
 					}
 				}, new SVNProgressMonitor(CompareResourcesInternalOperation.this, monitor, null, false));
 
+				{
+					removeFalseDiffs(localChangesMap, proxy);
+					removeFalseDiffs(remoteChangesMap, proxy);
+					localChanges.addAll(localChangesMap.keySet());
+					remoteChanges.addAll(remoteChangesMap.keySet());
+				}
+
 			}
 		}, monitor, 100, 50);
 	}
-	
+
+    /**
+     * In some cases, SVNDiffStatus reports files as being different although there are no real difference.
+     * This method removes such false positive result.
+     */
+    private void removeFalseDiffs(Map<SVNDiffStatus, IResource> changes, ISVNConnector proxy) {
+        Iterator<SVNDiffStatus> itChanges = changes.keySet().iterator();
+        while (itChanges.hasNext()) {
+            SVNDiffStatus status = itChanges.next();
+            IResource resource = changes.get(status);
+            if (status.nodeKind == SVNEntry.Kind.FILE
+                    && !_reallyDifferent(proxy, resource, new SVNEntryRevisionReference(status.pathNext))) {
+                itChanges.remove();
+                System.out.format("Diff entry removed because no real differences were found: '%s' vs. '%s'%n", status.pathPrev, status.pathNext);
+            }
+        }
+    }
+
+    private boolean _reallyDifferent(ISVNConnector proxy, IResource localResource, SVNEntryRevisionReference remoteFile) {
+        try {
+            // 1. Get remote file content
+            OutputStream stream = new ByteArrayOutputStream();
+            proxy.streamFileContent(remoteFile, 1000, stream, null);
+            String right = stream.toString();
+            right = right.replace("\n", "").replace("\r", "").trim();
+
+            // 2. Get local file content
+            String left = "";
+            File loc = localResource.getRawLocation().toFile();
+			if (loc.exists()) {
+				InputStream in = new FileInputStream(loc);
+				BufferedReader r = new BufferedReader(new InputStreamReader(in));
+				char[] buf = new char[1024];
+				StringWriter w = new StringWriter();
+				int readCount = -1;
+				while (-1 != (readCount = r.read(buf))) {
+					w.write(buf, 0, readCount);
+				}
+				left = w.toString();
+			}
+            left = left.replace("\n", "").replace("\r", "").trim();
+
+            // 3. Compare contents
+            if (left.equals(right)) {
+                return false;
+            }
+        } catch (SVNConnectorException e) {
+            e.printStackTrace();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return true;
+    }
+
 	protected boolean compareResultOK(CompareEditorInput input) {
 		final Shell shell = UIMonitorUtility.getShell();
 		

Back to the top