Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 36436 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/team/internal/ccvs/core/CVSContentComparator.java (+201 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 Axel Mueller and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Axel Mueller - initial implementation
10
 *******************************************************************************/
11
package org.eclipse.team.internal.ccvs.core;
12
13
import java.io.*;
14
15
import org.eclipse.core.resources.IFile;
16
import org.eclipse.core.runtime.CoreException;
17
import org.eclipse.core.runtime.IProgressMonitor;
18
import org.eclipse.team.core.TeamException;
19
import org.eclipse.team.core.history.IFileRevision;
20
import org.eclipse.team.core.variants.IResourceVariant;
21
import org.eclipse.team.internal.core.Policy;
22
import org.eclipse.team.internal.core.TeamPlugin;
23
24
/**
25
 * This is an internal class that is used by the <code>CVSContentComparisonSyncInfoFilter</code>
26
 * to compare the contents of the local and remote resources
27
 */
28
public class CVSContentComparator {
29
30
	private final static String[] CVSKeywords = new String[] {
31
			"Id:", 		 //$NON-NLS-1$
32
			"Revision:",  //$NON-NLS-1$
33
			"Date:", 	 //$NON-NLS-1$
34
			"Author:", 	 //$NON-NLS-1$
35
			"Log:",  	 //$NON-NLS-1$
36
			"Header:",  	 //$NON-NLS-1$
37
			"Name:" };  	 //$NON-NLS-1$
38
	
39
	private final static int MaxKeywordLen = 9;
40
	
41
	public CVSContentComparator() {
42
	}
43
		
44
	public boolean compare(Object e1, Object e2, IProgressMonitor monitor) {
45
		InputStream is1 = null;
46
		InputStream is2 = null;
47
		try {
48
			monitor.beginTask(null, 100);
49
			is1 = getContents(e1, Policy.subMonitorFor(monitor, 50));
50
			is2 = getContents(e2, Policy.subMonitorFor(monitor, 50));
51
			return contentsEqual(is1, is2);
52
		} catch(TeamException e) {
53
			TeamPlugin.log(e);
54
			return false;
55
		} finally {
56
			try {
57
				try {
58
					if (is1 != null) {
59
						is1.close();
60
					}
61
				} finally {
62
					if (is2 != null) {
63
						is2.close();
64
					}
65
				}
66
			} catch (IOException e) {
67
				// Ignore
68
			}
69
			monitor.done();
70
		}
71
	}
72
73
	/**
74
	 * Returns <code>true</code> if both input streams byte contents is
75
	 * identical.
76
	 * 
77
	 * @param input1
78
	 *                   first input to contents compare
79
	 * @param input2
80
	 *                   second input to contents compare
81
	 * @return <code>true</code> if content is equal
82
	 */
83
	private boolean contentsEqual(InputStream is1, InputStream is2) {
84
		try {
85
			if (is1 == is2)
86
				return true;
87
88
			if (is1 == null && is2 == null) // no byte contents
89
				return true;
90
91
			if (is1 == null || is2 == null) // only one has contents
92
				return false;
93
94
			boolean StartFound = false;
95
			boolean KeywordFound = false;
96
			char[] Buffer = new char[MaxKeywordLen];
97
			int Idx = 0;
98
			
99
			while (true) {
100
				int c1 = is1.read();
101
				// if keyword was found ignore everything until the next '$' that marks the end
102
				while (KeywordFound && !isDollar(c1))
103
					c1 = is1.read();
104
				int c2 = is2.read();
105
				// if keyword was found ignore everything until the next '$' that marks the end
106
				while (KeywordFound && !isDollar(c2))
107
					c2 = is2.read();
108
				// keywords starts and ends with a '$'
109
				if (isDollar(c1)){
110
					if (StartFound){ // restart search when we get the second '$'
111
						StartFound = false; 
112
						KeywordFound = false;
113
						Idx = 0;
114
					}
115
					else
116
						StartFound = true;
117
				}
118
				if (c1 == -1 && c2 == -1)
119
					return true;
120
				if (c1 != c2)
121
					break;
122
				// we have a possible start but no keyword identified yet
123
				if (StartFound && !KeywordFound){
124
					if (!isDollar(c1)){
125
						Buffer[Idx] = (char)c1; // save to temporary buffer (w/o starting '$')
126
						++Idx;
127
					}
128
					if (isColon(c1))  // colon marks the end of a possible keyword
129
					{ 
130
						// check for keyword
131
						String key = new String(Buffer,0,Idx);
132
						for (int i = 0; i < CVSKeywords.length; i++) {
133
							if (CVSKeywords[i].equals(key)){
134
								KeywordFound = true;
135
								break;
136
							}
137
						}
138
						if (!KeywordFound)
139
						{
140
							StartFound = false;
141
							Idx = 0;
142
						}
143
							
144
					} else if (Idx >= MaxKeywordLen) 
145
					{ // still no colon then stop search
146
						StartFound = false;
147
						KeywordFound = false;
148
						Idx = 0;
149
					}
150
				}
151
			}
152
		} catch (IOException ex) {
153
		} finally {
154
			try {
155
				try {
156
					if (is1 != null) {
157
						is1.close();
158
					}
159
				} finally {
160
					if (is2 != null) {
161
						is2.close();
162
					}
163
				}
164
			} catch (IOException e) {
165
				// Ignore
166
			}
167
		}
168
		return false;
169
	}
170
171
	private boolean isDollar(int c) {
172
		if (c == -1)
173
			return false;
174
		return (((char)c) == '$');
175
	}
176
177
	private boolean isColon(int c) {
178
		if (c == -1)
179
			return false;
180
		return (((char)c) == ':');
181
	}
182
	
183
	private InputStream getContents(Object resource, IProgressMonitor monitor) throws TeamException {
184
		try {
185
			if (resource instanceof IFile) {
186
				return new BufferedInputStream(((IFile) resource).getContents());
187
			} else if(resource instanceof IResourceVariant) {
188
				IResourceVariant remote = (IResourceVariant)resource;
189
				if (!remote.isContainer()) {
190
					return new BufferedInputStream(remote.getStorage(monitor).getContents());
191
				}
192
			} else if(resource instanceof IFileRevision) {
193
				IFileRevision remote = (IFileRevision)resource;
194
				return new BufferedInputStream(remote.getStorage(monitor).getContents());
195
			}
196
			return null;
197
		} catch (CoreException e) {
198
			throw TeamException.asTeamException(e);
199
		}
200
	}
201
}
(-)src/org/eclipse/team/internal/ccvs/core/CVSContentComparisonSyncInfoFilter.java (+69 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2010 Axel Mueller and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Axel Mueller - initial implementation
10
 *******************************************************************************/
11
package org.eclipse.team.internal.ccvs.core;
12
13
import org.eclipse.core.resources.IFile;
14
import org.eclipse.core.resources.IResource;
15
import org.eclipse.core.runtime.Assert;
16
import org.eclipse.core.runtime.IProgressMonitor;
17
import org.eclipse.team.core.synchronize.SyncInfo;
18
import org.eclipse.team.core.synchronize.SyncInfoFilter;
19
import org.eclipse.team.core.variants.IResourceVariant;
20
21
22
/**
23
 * Selects <code>SyncInfo</code> whose local and remote contents match.
24
 * This filter makes use of the <code>IStorage</code> provided by
25
 * an <code>IResourceVariant</code> to obtain the remote contents.
26
 * This means that the comparison may contact the server unless the contents
27
 * were cached locally by a previous operation. The caching of remote
28
 * contents is subscriber specific. 
29
 * Differences in CVS keywords are ignored, e.g. different revisions that cause
30
 * pseudo conflicts during merging.
31
 * <p>
32
 * For folders, the comparison always returns <code>true</code>.
33
 */
34
public class CVSContentComparisonSyncInfoFilter extends SyncInfoFilter {
35
	CVSContentComparator criteria = new CVSContentComparator();
36
	
37
	public CVSContentComparisonSyncInfoFilter() {
38
		criteria = new CVSContentComparator();
39
	}
40
41
	/* (non-Javadoc)
42
	 * @see org.eclipse.team.core.synchronize.SyncInfoFilter#select(org.eclipse.team.core.synchronize.SyncInfo, org.eclipse.core.runtime.IProgressMonitor)
43
	 */
44
	public boolean select(SyncInfo info, IProgressMonitor monitor) {
45
		IResourceVariant remote = info.getRemote();
46
		IResource local = info.getLocal();
47
		if (local.getType() != IResource.FILE) return true;
48
		if (remote == null) return !local.exists();
49
		if (!local.exists()) return false;
50
		return compareContents((IFile)local, remote, monitor);
51
	}
52
53
	/**
54
	 * Compare the contents of the local file and its variant.
55
	 * This is used by the <code>select</code> method to compare the
56
	 * contents of two non-null files.
57
	 * @param local a local file
58
	 * @param remote a resource variant of the file
59
	 * @param monitor a progress monitor
60
	 * @return whether the contents of the two files are equal
61
	 */
62
	public boolean compareContents(IFile local, IResourceVariant remote, IProgressMonitor monitor) {
63
		Assert.isNotNull(local);
64
		Assert.isNotNull(remote);
65
		return criteria.compare(local, remote, monitor);
66
	}
67
}
68
	
69
	
(-)src/org/eclipse/team/internal/ccvs/core/CVSMergeSubscriber.java (-4 / +16 lines)
Lines 23-28 Link Here
23
import org.eclipse.team.core.synchronize.SyncInfo;
23
import org.eclipse.team.core.synchronize.SyncInfo;
24
import org.eclipse.team.core.synchronize.SyncInfoFilter;
24
import org.eclipse.team.core.synchronize.SyncInfoFilter;
25
import org.eclipse.team.core.variants.*;
25
import org.eclipse.team.core.variants.*;
26
import org.eclipse.team.internal.ccvs.core.client.Command;
27
import org.eclipse.team.internal.ccvs.core.client.Command.KSubstOption;
26
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
28
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
27
import org.eclipse.team.internal.ccvs.core.resources.RemoteFile;
29
import org.eclipse.team.internal.ccvs.core.resources.RemoteFile;
28
import org.eclipse.team.internal.ccvs.core.syncinfo.CVSResourceVariantTree;
30
import org.eclipse.team.internal.ccvs.core.syncinfo.CVSResourceVariantTree;
Lines 317-322 Link Here
317
		if (refreshed.length == 0) return;
319
		if (refreshed.length == 0) return;
318
		SyncInfoFilter.ContentComparisonSyncInfoFilter contentFilter =
320
		SyncInfoFilter.ContentComparisonSyncInfoFilter contentFilter =
319
			new SyncInfoFilter.ContentComparisonSyncInfoFilter();
321
			new SyncInfoFilter.ContentComparisonSyncInfoFilter();
322
		CVSContentComparisonSyncInfoFilter CVSKeywordscontentFilter =
323
			new CVSContentComparisonSyncInfoFilter();
320
		monitor.beginTask(null, refreshed.length * 100);
324
		monitor.beginTask(null, refreshed.length * 100);
321
		for (int i = 0; i < refreshed.length; i++) {
325
		for (int i = 0; i < refreshed.length; i++) {
322
			IResource resource = refreshed[i];
326
			IResource resource = refreshed[i];
Lines 327-336 Link Here
327
				if (remoteBytes != null 
331
				if (remoteBytes != null 
328
						&& localBytes != null
332
						&& localBytes != null
329
						&& local.exists()
333
						&& local.exists()
330
						&& !ResourceSyncInfo.getRevision(remoteBytes).equals(ResourceSyncInfo.getRevision(localBytes))
334
						&& !ResourceSyncInfo.getRevision(remoteBytes).equals(ResourceSyncInfo.getRevision(localBytes)) ){
331
						&& contentFilter.select(getSyncInfo(resource), Policy.subMonitorFor(monitor, 100))) {
335
					boolean isContentDifferent; 
332
					// The contents are equals so mark the file as merged
336
					KSubstOption localKSubst = ResourceSyncInfo.getKeywordMode(localBytes);
333
					internalMerged(resource);
337
					if ( localKSubst.equals(Command.KSUBST_BINARY) || localKSubst.equals(Command.KSUBST_TEXT) ){//TODO: check keywordMode of remote file, too?
338
						isContentDifferent = contentFilter.select(getSyncInfo(resource), Policy.subMonitorFor(monitor, 100));
339
					} else {
340
						isContentDifferent = CVSKeywordscontentFilter.select(getSyncInfo(resource), Policy.subMonitorFor(monitor, 100));
341
					}
342
					if (isContentDifferent) {
343
						// The contents are equals so mark the file as merged
344
						internalMerged(resource);
345
					}
334
				}
346
				}
335
			}
347
			}
336
		}
348
		}

Return to bug 36436