View | Details | Raw Unified | Return to bug 183226 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/compare/tests/PatchTest.java (-135 / +20 lines)
Lines 10-22 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.compare.tests;
11
package org.eclipse.compare.tests;
12
12
13
import java.io.BufferedInputStream;
14
import java.io.BufferedReader;
13
import java.io.BufferedReader;
15
import java.io.ByteArrayInputStream;
14
import java.io.ByteArrayInputStream;
16
import java.io.File;
15
import java.io.File;
17
import java.io.FileFilter;
16
import java.io.FileFilter;
18
import java.io.FileInputStream;
17
import java.io.FileInputStream;
19
import java.io.FileNotFoundException;
20
import java.io.IOException;
18
import java.io.IOException;
21
import java.io.InputStream;
19
import java.io.InputStream;
22
import java.io.InputStreamReader;
20
import java.io.InputStreamReader;
Lines 38-44 Link Here
38
import junit.framework.AssertionFailedError;
36
import junit.framework.AssertionFailedError;
39
import junit.framework.TestCase;
37
import junit.framework.TestCase;
40
38
41
import org.eclipse.compare.internal.Utilities;
42
import org.eclipse.compare.internal.core.patch.FileDiff;
39
import org.eclipse.compare.internal.core.patch.FileDiff;
43
import org.eclipse.compare.internal.core.patch.FileDiffResult;
40
import org.eclipse.compare.internal.core.patch.FileDiffResult;
44
import org.eclipse.compare.internal.core.patch.LineReader;
41
import org.eclipse.compare.internal.core.patch.LineReader;
Lines 49-56 Link Here
49
import org.eclipse.compare.patch.IHunk;
46
import org.eclipse.compare.patch.IHunk;
50
import org.eclipse.compare.patch.IHunkFilter;
47
import org.eclipse.compare.patch.IHunkFilter;
51
import org.eclipse.compare.patch.PatchConfiguration;
48
import org.eclipse.compare.patch.PatchConfiguration;
49
import org.eclipse.compare.tests.PatchUtils.JarEntryStorage;
50
import org.eclipse.compare.tests.PatchUtils.PatchTestConfiguration;
51
import org.eclipse.compare.tests.PatchUtils.StringStorage;
52
import org.eclipse.core.resources.IStorage;
52
import org.eclipse.core.resources.IStorage;
53
import org.eclipse.core.resources.ResourcesPlugin;
54
import org.eclipse.core.runtime.CoreException;
53
import org.eclipse.core.runtime.CoreException;
55
import org.eclipse.core.runtime.FileLocator;
54
import org.eclipse.core.runtime.FileLocator;
56
import org.eclipse.core.runtime.IPath;
55
import org.eclipse.core.runtime.IPath;
Lines 59-161 Link Here
59
import org.eclipse.core.runtime.Path;
58
import org.eclipse.core.runtime.Path;
60
import org.eclipse.core.runtime.Platform;
59
import org.eclipse.core.runtime.Platform;
61
import org.eclipse.core.runtime.Status;
60
import org.eclipse.core.runtime.Status;
62
import org.osgi.framework.Bundle;
63
61
64
public class PatchTest extends TestCase {
62
public class PatchTest extends TestCase {
65
63
66
	private static final String PATCHDATA = "patchdata";
67
	private static final String PATCH_CONFIGURATION = "patchConfiguration.properties";
64
	private static final String PATCH_CONFIGURATION = "patchConfiguration.properties";
68
	
65
	
69
	Properties defaultPatchProperties;
66
	Properties defaultPatchProperties;
70
	
67
	
71
	class StringStorage implements IStorage {
72
		String fileName;
73
		public StringStorage(String old) {
74
			fileName = old;
75
		}
76
		public Object getAdapter(Class adapter) {
77
			return null;
78
		}
79
		public boolean isReadOnly() {
80
			return false;
81
		}
82
		public String getName() {
83
			return fileName;
84
		}
85
		public IPath getFullPath() {
86
			return null;
87
		}
88
		public InputStream getContents() throws CoreException {
89
			return new BufferedInputStream(asInputStream(fileName));
90
		}
91
	}
92
	
93
	class FileStorage implements IStorage {
94
		File file;
95
		public FileStorage(File file) {
96
			this.file = file;
97
		}
98
		public InputStream getContents() throws CoreException {
99
			try {
100
				return new FileInputStream(file);
101
			} catch (FileNotFoundException e) {
102
				// ignore, should never happen
103
			}
104
			return null;
105
		}
106
		public IPath getFullPath() {
107
			return new Path(file.getAbsolutePath());
108
		}
109
		public String getName() {
110
			return file.getName();
111
		}
112
		public boolean isReadOnly() {
113
			return true;
114
		}
115
		public Object getAdapter(Class adapter) {
116
			return null;
117
		}
118
	}
119
	
120
	class JarEntryStorage implements IStorage {
121
		JarEntry jarEntry;
122
		JarFile jarFile;
123
		public JarEntryStorage(JarEntry jarEntry, JarFile jarFile) {
124
			this.jarEntry = jarEntry;
125
			this.jarFile = jarFile;
126
		}
127
		public InputStream getContents() throws CoreException {
128
			try {
129
				return jarFile.getInputStream(jarEntry);
130
			} catch (IOException e) {
131
				// ignore, should never happen
132
			}
133
			return null;
134
		}
135
		public IPath getFullPath() {
136
			return new Path(jarFile.getName());
137
		}
138
		public String getName() {
139
			return jarEntry.getName();
140
		}
141
		public boolean isReadOnly() {
142
			return true;
143
		}
144
		public Object getAdapter(Class adapter) {
145
			return null;
146
		}
147
	}
148
	
149
	class PatchTestConfiguration {
150
		String subfolderName;
151
		PatchConfiguration pc;
152
		String patchFileName;
153
		String[] originalFileNames;
154
		String[] expectedFileNames;
155
		String[] actualFileNames;
156
		// TODO: getters, setters
157
	}
158
	
159
	public PatchTest(String name) {
68
	public PatchTest(String name) {
160
		super(name);
69
		super(name);
161
		defaultPatchProperties = new Properties();
70
		defaultPatchProperties = new Properties();
Lines 217-227 Link Here
217
126
218
		InputStream actual = result.getPatchedContents();
127
		InputStream actual = result.getPatchedContents();
219
128
220
		LineReader lr = new LineReader(getReader("exp_hunkFilter.txt"));
129
		LineReader lr = new LineReader(PatchUtils.getReader("exp_hunkFilter.txt"));
221
		List inLines = lr.readLines();
130
		List inLines = lr.readLines();
222
		String expected = LineReader.createString(false, inLines);
131
		String expected = LineReader.createString(false, inLines);
223
132
224
		assertEquals(expected, asString(actual));
133
		assertEquals(expected, PatchUtils.asString(actual));
225
	}
134
	}
226
135
227
	public void testContext3PatchWithHeader() throws CoreException, IOException {
136
	public void testContext3PatchWithHeader() throws CoreException, IOException {
Lines 298-304 Link Here
298
	private List failures = new ArrayList();
207
	private List failures = new ArrayList();
299
	
208
	
300
	public void testPatchdataSubfolders() throws IOException, CoreException {
209
	public void testPatchdataSubfolders() throws IOException, CoreException {
301
		URL patchdataUrl = new URL(getBundle().getEntry("/"), new Path(PATCHDATA).toString());
210
		URL patchdataUrl = new URL(PatchUtils.getBundle().getEntry("/"),
211
				new Path(PatchUtils.PATCHDATA).toString());
302
		patchdataUrl = FileLocator.resolve(patchdataUrl);
212
		patchdataUrl = FileLocator.resolve(patchdataUrl);
303
		
213
		
304
		Map map = null;
214
		Map map = null;
Lines 321-327 Link Here
321
			PatchConfiguration pc = ptc.pc;
231
			PatchConfiguration pc = ptc.pc;
322
			
232
			
323
			// create a message to distinguish tests from different subfolders
233
			// create a message to distinguish tests from different subfolders
324
			String msg = "Test for subfolder [" + PATCHDATA + "/" + sf + "] failed.";
234
			String msg = "Test for subfolder [" + PatchUtils.PATCHDATA + "/"
235
					+ sf + "] failed.";
325
			
236
			
326
			try {
237
			try {
327
				// test with expected result
238
				// test with expected result
Lines 339-346 Link Here
339
					continue; // continue with a next subfolder
250
					continue; // continue with a next subfolder
340
				}
251
				}
341
				failures.add(new AssertionFailedError(
252
				failures.add(new AssertionFailedError(
342
						"\npatchWorkspace should fail for folder [" + PATCHDATA
253
						"\npatchWorkspace should fail for folder ["
343
								+ "/" + sf + "]."));
254
								+ PatchUtils.PATCHDATA + "/" + sf + "]."));
344
			}
255
			}
345
		}
256
		}
346
		
257
		
Lines 391-397 Link Here
391
		while (entries.hasMoreElements()) {
302
		while (entries.hasMoreElements()) {
392
			JarEntry entry = (JarEntry) entries.nextElement();
303
			JarEntry entry = (JarEntry) entries.nextElement();
393
			String entryName = entry.getName();
304
			String entryName = entry.getName();
394
			if (entryName.endsWith("/" + PATCHDATA + "/")) {
305
			if (entryName.endsWith("/" + PatchUtils.PATCHDATA + "/")) {
395
				patchdataName = entryName;
306
				patchdataName = entryName;
396
				break;
307
				break;
397
			}
308
			}
Lines 512-543 Link Here
512
		result.put(subfolderName, tpc);
423
		result.put(subfolderName, tpc);
513
	}
424
	}
514
425
515
516
	// Test changing
517
	private BufferedReader getReader(String name) {
518
		InputStream resourceAsStream = asInputStream(name);
519
		InputStreamReader reader2= new InputStreamReader(resourceAsStream);
520
		return new BufferedReader(reader2);
521
	}
522
523
	private InputStream asInputStream(String name) {
524
		IPath path= new Path(PATCHDATA).append(name);
525
		try {
526
			URL url= new URL(getBundle().getEntry("/"), path.toString());
527
			return url.openStream();
528
		} catch (IOException e) {
529
			fail("Failed while reading " + name);
530
			return null; // never reached
531
		}
532
	}
533
534
	private void patch(final String old, String patch, String expt) throws CoreException, IOException {
426
	private void patch(final String old, String patch, String expt) throws CoreException, IOException {
535
		patcherPatch(old, patch, expt);
427
		patcherPatch(old, patch, expt);
536
		filePatch(old, patch, expt);
428
		filePatch(old, patch, expt);
537
	}
429
	}
538
430
539
	private void filePatch(final String old, String patch, String expt) throws CoreException, IOException {
431
	private void filePatch(final String old, String patch, String expt) throws CoreException, IOException {
540
		LineReader lr= new LineReader(getReader(expt));
432
		LineReader lr= new LineReader(PatchUtils.getReader(expt));
541
		List inLines= lr.readLines();
433
		List inLines= lr.readLines();
542
		String expected = LineReader.createString(false, inLines);
434
		String expected = LineReader.createString(false, inLines);
543
		
435
		
Lines 549-569 Link Here
549
		assertTrue(result.hasMatches());
441
		assertTrue(result.hasMatches());
550
		assertFalse(result.hasRejects());
442
		assertFalse(result.hasRejects());
551
		InputStream actualStream = result.getPatchedContents();
443
		InputStream actualStream = result.getPatchedContents();
552
		String actual = asString(actualStream);
444
		String actual = PatchUtils.asString(actualStream);
553
		assertEquals(expected, actual);
445
		assertEquals(expected, actual);
554
	}
446
	}
555
447
556
	private String asString(InputStream exptStream) throws IOException {
557
		return Utilities.readString(exptStream, ResourcesPlugin.getEncoding());
558
	}
559
560
	private void patcherPatch(String old, String patch, String expt) {
448
	private void patcherPatch(String old, String patch, String expt) {
561
		LineReader lr= new LineReader(getReader(old));
449
		LineReader lr= new LineReader(PatchUtils.getReader(old));
562
		List inLines= lr.readLines();
450
		List inLines= lr.readLines();
563
451
564
		WorkspacePatcher patcher= new WorkspacePatcher();
452
		WorkspacePatcher patcher= new WorkspacePatcher();
565
		try {
453
		try {
566
			patcher.parse(getReader(patch));
454
			patcher.parse(PatchUtils.getReader(patch));
567
		} catch (IOException e) {
455
		} catch (IOException e) {
568
			e.printStackTrace();
456
			e.printStackTrace();
569
		}
457
		}
Lines 574-580 Link Here
574
		FileDiffResult diffResult = patcher.getDiffResult(diffs[0]);
462
		FileDiffResult diffResult = patcher.getDiffResult(diffs[0]);
575
		diffResult.patch(inLines, null);
463
		diffResult.patch(inLines, null);
576
		
464
		
577
		LineReader expectedContents= new LineReader(getReader(expt));
465
		LineReader expectedContents= new LineReader(PatchUtils.getReader(expt));
578
		List expectedLines= expectedContents.readLines();
466
		List expectedLines= expectedContents.readLines();
579
		
467
		
580
		Object[] expected= expectedLines.toArray();
468
		Object[] expected= expectedLines.toArray();
Lines 618-624 Link Here
618
			patcher.getConfiguration().setFuzz(patchConfiguration.getFuzz());
506
			patcher.getConfiguration().setFuzz(patchConfiguration.getFuzz());
619
			patcher.getConfiguration().setIgnoreWhitespace(patchConfiguration.isIgnoreWhitespace());
507
			patcher.getConfiguration().setIgnoreWhitespace(patchConfiguration.isIgnoreWhitespace());
620
			patcher.getConfiguration().setPrefixSegmentStripCount(patchConfiguration.getPrefixSegmentStripCount());
508
			patcher.getConfiguration().setPrefixSegmentStripCount(patchConfiguration.getPrefixSegmentStripCount());
621
			patcher.parse(getReader(patch));
509
			patcher.parse(PatchUtils.getReader(patch));
622
			patcher.setReversed(patchConfiguration.isReversed());
510
			patcher.setReversed(patchConfiguration.isReversed());
623
		} catch (IOException e) {
511
		} catch (IOException e) {
624
			e.printStackTrace();
512
			e.printStackTrace();
Lines 630-642 Link Here
630
		//Iterate through all of the original files, apply the diffs that belong to the file and compare
518
		//Iterate through all of the original files, apply the diffs that belong to the file and compare
631
		//with the corresponding outcome file
519
		//with the corresponding outcome file
632
		for (int i = 0; i < originalFiles.length; i++) {	
520
		for (int i = 0; i < originalFiles.length; i++) {	
633
			LineReader lr= new LineReader(getReader(originalFiles[i]));
521
			LineReader lr= new LineReader(PatchUtils.getReader(originalFiles[i]));
634
			List inLines= lr.readLines();
522
			List inLines= lr.readLines();
635
		
523
		
636
			FileDiffResult diffResult = patcher.getDiffResult(diffs[i]);
524
			FileDiffResult diffResult = patcher.getDiffResult(diffs[i]);
637
			diffResult.patch(inLines, null);
525
			diffResult.patch(inLines, null);
638
			
526
			
639
			LineReader expectedContents= new LineReader(getReader(expectedOutcomeFiles[i]));
527
			LineReader expectedContents= new LineReader(PatchUtils.getReader(expectedOutcomeFiles[i]));
640
			List expectedLines= expectedContents.readLines();
528
			List expectedLines= expectedContents.readLines();
641
			
529
			
642
			Object[] expected= expectedLines.toArray();
530
			Object[] expected= expectedLines.toArray();
Lines 652-658 Link Here
652
		}
540
		}
653
	}
541
	}
654
	
542
	
655
	private Bundle getBundle() {
656
		return CompareTestPlugin.getDefault().getBundle();
657
	}	
658
}
543
}
(-)src/org/eclipse/compare/tests/AllTests.java (-1 / +2 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 IBM Corporation and others.
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 28-33 Link Here
28
		suite.addTestSuite(DocLineComparatorTest.class);
28
		suite.addTestSuite(DocLineComparatorTest.class);
29
		suite.addTestSuite(FilterTest.class);
29
		suite.addTestSuite(FilterTest.class);
30
		suite.addTestSuite(PatchTest.class);
30
		suite.addTestSuite(PatchTest.class);
31
		suite.addTestSuite(PatchBuilderTest.class);
31
		suite.addTestSuite(AsyncExecTests.class);
32
		suite.addTestSuite(AsyncExecTests.class);
32
		suite.addTestSuite(DiffTest.class);
33
		suite.addTestSuite(DiffTest.class);
33
		suite.addTestSuite(FileDiffResultTest.class);
34
		suite.addTestSuite(FileDiffResultTest.class);
(-)src/org/eclipse/compare/tests/PatchUtils.java (+170 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.compare.tests;
12
13
import java.io.BufferedInputStream;
14
import java.io.BufferedReader;
15
import java.io.File;
16
import java.io.FileInputStream;
17
import java.io.FileNotFoundException;
18
import java.io.IOException;
19
import java.io.InputStream;
20
import java.io.InputStreamReader;
21
import java.net.URL;
22
import java.util.jar.JarEntry;
23
import java.util.jar.JarFile;
24
25
import junit.framework.Assert;
26
27
import org.eclipse.compare.internal.Utilities;
28
import org.eclipse.compare.patch.PatchConfiguration;
29
import org.eclipse.core.resources.IStorage;
30
import org.eclipse.core.resources.ResourcesPlugin;
31
import org.eclipse.core.runtime.CoreException;
32
import org.eclipse.core.runtime.IPath;
33
import org.eclipse.core.runtime.Path;
34
import org.osgi.framework.Bundle;
35
36
public class PatchUtils {
37
38
	public static final String PATCHDATA = "patchdata";
39
40
	public static class PatchTestConfiguration {
41
		String subfolderName;
42
		PatchConfiguration pc;
43
		String patchFileName;
44
		String[] originalFileNames;
45
		String[] expectedFileNames;
46
		String[] actualFileNames;
47
	}
48
49
	public static class StringStorage implements IStorage {
50
		String fileName;
51
52
		public StringStorage(String old) {
53
			fileName = old;
54
		}
55
56
		public Object getAdapter(Class adapter) {
57
			return null;
58
		}
59
60
		public boolean isReadOnly() {
61
			return false;
62
		}
63
64
		public String getName() {
65
			return fileName;
66
		}
67
68
		public IPath getFullPath() {
69
			return null;
70
		}
71
72
		public InputStream getContents() throws CoreException {
73
			return new BufferedInputStream(asInputStream(fileName));
74
		}
75
	}
76
77
	public static class FileStorage implements IStorage {
78
		File file;
79
80
		public FileStorage(File file) {
81
			this.file = file;
82
		}
83
84
		public InputStream getContents() throws CoreException {
85
			try {
86
				return new FileInputStream(file);
87
			} catch (FileNotFoundException e) {
88
				// ignore, should never happen
89
			}
90
			return null;
91
		}
92
93
		public IPath getFullPath() {
94
			return new Path(file.getAbsolutePath());
95
		}
96
97
		public String getName() {
98
			return file.getName();
99
		}
100
101
		public boolean isReadOnly() {
102
			return true;
103
		}
104
105
		public Object getAdapter(Class adapter) {
106
			return null;
107
		}
108
	}
109
110
	public static class JarEntryStorage implements IStorage {
111
		JarEntry jarEntry;
112
		JarFile jarFile;
113
114
		public JarEntryStorage(JarEntry jarEntry, JarFile jarFile) {
115
			this.jarEntry = jarEntry;
116
			this.jarFile = jarFile;
117
		}
118
119
		public InputStream getContents() throws CoreException {
120
			try {
121
				return jarFile.getInputStream(jarEntry);
122
			} catch (IOException e) {
123
				// ignore, should never happen
124
			}
125
			return null;
126
		}
127
128
		public IPath getFullPath() {
129
			return new Path(jarFile.getName());
130
		}
131
132
		public String getName() {
133
			return jarEntry.getName();
134
		}
135
136
		public boolean isReadOnly() {
137
			return true;
138
		}
139
140
		public Object getAdapter(Class adapter) {
141
			return null;
142
		}
143
	}
144
145
	public static String asString(InputStream exptStream) throws IOException {
146
		return Utilities.readString(exptStream, ResourcesPlugin.getEncoding());
147
	}
148
149
	public static InputStream asInputStream(String name) {
150
		IPath path = new Path(PATCHDATA).append(name);
151
		try {
152
			URL url = new URL(getBundle().getEntry("/"), path.toString());
153
			return url.openStream();
154
		} catch (IOException e) {
155
			Assert.fail("Failed while reading " + name);
156
			return null; // never reached
157
		}
158
	}
159
160
	public static BufferedReader getReader(String name) {
161
		InputStream resourceAsStream = PatchUtils.asInputStream(name);
162
		InputStreamReader reader2 = new InputStreamReader(resourceAsStream);
163
		return new BufferedReader(reader2);
164
	}
165
166
	public static Bundle getBundle() {
167
		return CompareTestPlugin.getDefault().getBundle();
168
	}
169
170
}
(-)src/org/eclipse/compare/tests/PatchBuilderTest.java (+254 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.compare.tests;
12
13
import java.io.IOException;
14
import java.io.InputStream;
15
import java.util.List;
16
17
import junit.framework.TestCase;
18
19
import org.eclipse.compare.internal.core.patch.FileDiff;
20
import org.eclipse.compare.internal.core.patch.Hunk;
21
import org.eclipse.compare.internal.core.patch.LineReader;
22
import org.eclipse.compare.internal.patch.FileDiffWrapper;
23
import org.eclipse.compare.patch.ApplyPatchOperation;
24
import org.eclipse.compare.patch.IFilePatch;
25
import org.eclipse.compare.patch.IFilePatch2;
26
import org.eclipse.compare.patch.IFilePatchResult;
27
import org.eclipse.compare.patch.IHunk;
28
import org.eclipse.compare.patch.PatchBuilder;
29
import org.eclipse.compare.patch.PatchConfiguration;
30
import org.eclipse.compare.tests.PatchUtils.StringStorage;
31
import org.eclipse.core.resources.IStorage;
32
import org.eclipse.core.runtime.CoreException;
33
import org.eclipse.core.runtime.NullProgressMonitor;
34
import org.eclipse.core.runtime.Path;
35
36
public class PatchBuilderTest extends TestCase {
37
38
	public PatchBuilderTest() {
39
40
	}
41
42
	protected void setUp() throws Exception {
43
		// Nothing to do
44
	}
45
46
	protected void tearDown() throws Exception {
47
		super.tearDown();
48
	}
49
50
	public void testModifyHunks() throws CoreException, IOException {
51
		IStorage patchStorage = new StringStorage("patch_modifyHunks.txt");
52
		IStorage contextStorage = new StringStorage("context.txt");
53
		IFilePatch[] patches = ApplyPatchOperation.parsePatch(patchStorage);
54
		assertEquals(1, patches.length);
55
		IHunk[] hunksBefore = patches[0].getHunks();
56
		assertEquals(5, hunksBefore.length);
57
58
		String[] lines = new String[] { " [d]", "+[d1]", "+[d2]", "+[d3]",
59
				"+[d4]", " [e]" };
60
		addLineDelimiters(lines);
61
		IHunk[] toAdd = new IHunk[] { PatchBuilder.createHunk(3, 3, lines) };
62
		IFilePatch2 filePatch = PatchBuilder.addHunks(patches[0], toAdd, false);
63
64
		IHunk[] toRemove = new IHunk[] { hunksBefore[0], hunksBefore[2] };
65
		filePatch = PatchBuilder.removeHunks(filePatch, toRemove, false);
66
67
		IHunk[] hunksAfter = filePatch.getHunks();
68
		assertEquals(4, hunksAfter.length);
69
		assertEquals(3, ((Hunk) hunksAfter[0]).getStart(false));
70
		assertEquals(3, ((Hunk) hunksAfter[0]).getStart(true));
71
		assertEquals(7, ((Hunk) hunksAfter[1]).getStart(false));
72
		assertEquals(9, ((Hunk) hunksAfter[1]).getStart(true));
73
		assertEquals(18, ((Hunk) hunksAfter[2]).getStart(false));
74
		assertEquals(19, ((Hunk) hunksAfter[2]).getStart(true));
75
		assertEquals(28, ((Hunk) hunksAfter[3]).getStart(false));
76
		assertEquals(30, ((Hunk) hunksAfter[3]).getStart(true));
77
78
		FileDiffWrapper wrapper = new FileDiffWrapper((FileDiff) filePatch);
79
		IFilePatchResult result = wrapper.apply(contextStorage,
80
				new PatchConfiguration(), new NullProgressMonitor());
81
82
		IHunk[] rejects = result.getRejects();
83
		assertEquals(1, rejects.length);
84
85
		InputStream actual = result.getPatchedContents();
86
87
		LineReader lr = new LineReader(PatchUtils
88
				.getReader("exp_modifyHunks.txt"));
89
		List inLines = lr.readLines();
90
		String expected = LineReader.createString(false, inLines);
91
92
		assertEquals(expected, PatchUtils.asString(actual));
93
	}
94
95
	public void testModifyRecalculateHunks() throws CoreException, IOException {
96
		IStorage patchStorage = new StringStorage("patch_modifyHunks.txt");
97
		IStorage contextStorage = new StringStorage("context.txt");
98
		IFilePatch[] patches = ApplyPatchOperation.parsePatch(patchStorage);
99
		assertEquals(1, patches.length);
100
		IHunk[] hunksBefore = patches[0].getHunks();
101
		assertEquals(5, hunksBefore.length);
102
103
		String[] lines = new String[] { " [d]", "+[d1]", "+[d2]", "+[d3]",
104
				"+[d4]", " [e]" };
105
		addLineDelimiters(lines);
106
		IHunk[] toAdd = new IHunk[] { PatchBuilder.createHunk(3, 5, lines) };
107
		IFilePatch2 filePatch = PatchBuilder.addHunks(patches[0], toAdd, true);
108
109
		IHunk[] toRemove = new IHunk[] { hunksBefore[0], hunksBefore[2] };
110
		filePatch = PatchBuilder.removeHunks(filePatch, toRemove, true);
111
112
		IHunk[] hunksAfter = filePatch.getHunks();
113
		assertEquals(4, hunksAfter.length);
114
		assertEquals(3, ((Hunk) hunksAfter[0]).getStart(false));
115
		assertEquals(3, ((Hunk) hunksAfter[0]).getStart(true));
116
		assertEquals(7, ((Hunk) hunksAfter[1]).getStart(false));
117
		assertEquals(11, ((Hunk) hunksAfter[1]).getStart(true));
118
		assertEquals(18, ((Hunk) hunksAfter[2]).getStart(false));
119
		assertEquals(22, ((Hunk) hunksAfter[2]).getStart(true));
120
		assertEquals(28, ((Hunk) hunksAfter[3]).getStart(false));
121
		assertEquals(33, ((Hunk) hunksAfter[3]).getStart(true));
122
123
		FileDiffWrapper wrapper = new FileDiffWrapper((FileDiff) filePatch);
124
		IFilePatchResult result = wrapper.apply(contextStorage,
125
				new PatchConfiguration(), new NullProgressMonitor());
126
127
		IHunk[] rejects = result.getRejects();
128
		assertEquals(1, rejects.length);
129
130
		InputStream actual = result.getPatchedContents();
131
132
		LineReader lr = new LineReader(PatchUtils
133
				.getReader("exp_modifyHunks.txt"));
134
		List inLines = lr.readLines();
135
		String expected = LineReader.createString(false, inLines);
136
137
		assertEquals(expected, PatchUtils.asString(actual));
138
	}
139
140
	public void testCreateFilePatch() throws CoreException, IOException {
141
		IStorage contextStorage = new StringStorage("context.txt");
142
143
		String[] lines0 = new String[] { "+[a1]", "+[a2]", "+[a3]", " [a]" };
144
		addLineDelimiters(lines0);
145
		Hunk hunk0 = (Hunk) PatchBuilder.createHunk(0, 0, lines0);
146
147
		String[] lines1 = new String[] { " [a]", " [b]", "-[c]", " [d]",
148
				"-[e]", " [f]", " [g]", " [h]", "+[h1]", " [i]", " [j]",
149
				"+[j1]", "+[j2]", " [k]", " [l]" };
150
		addLineDelimiters(lines1);
151
		Hunk hunk1 = (Hunk) PatchBuilder.createHunk(0, 3, lines1);
152
153
		IHunk[] hunks = new IHunk[] { hunk1, hunk0 };
154
155
		IFilePatch2 filePatch = PatchBuilder.createFilePatch(new Path(""),
156
				IFilePatch2.DATE_UNKNOWN, new Path(""),
157
				IFilePatch2.DATE_UNKNOWN, hunks, true);
158
159
		assertEquals(2, filePatch.getHunks().length);
160
		assertEquals(hunk0, filePatch.getHunks()[0]);
161
		assertEquals(hunk1, filePatch.getHunks()[1]);
162
163
		FileDiffWrapper wrapper = new FileDiffWrapper((FileDiff) filePatch);
164
		IFilePatchResult result = wrapper.apply(contextStorage,
165
				new PatchConfiguration(), new NullProgressMonitor());
166
167
		InputStream actual = result.getPatchedContents();
168
169
		LineReader lr = new LineReader(PatchUtils
170
				.getReader("exp_createFilePatch.txt"));
171
		List inLines = lr.readLines();
172
		String expected = LineReader.createString(false, inLines);
173
174
		assertEquals(expected, PatchUtils.asString(actual));
175
	}
176
177
	public void testCreateHunk0() throws CoreException {
178
		IStorage patch = new StringStorage("patch_createHunk0.txt");
179
		IFilePatch[] filePatches = ApplyPatchOperation.parsePatch(patch);
180
		assertEquals(1, filePatches.length);
181
		assertEquals(1, filePatches[0].getHunks().length);
182
183
		String[] lines = new String[] { "+[a1]", "+[a2]", "+[a3]", " [a]",
184
				" [b]", "-[c]", " [d]", " [e]", " [f]" };
185
		addLineDelimiters(lines);
186
		Hunk hunk = (Hunk) PatchBuilder.createHunk(0, 0, lines);
187
188
		assertHunkEquals(hunk, (Hunk) filePatches[0].getHunks()[0]);
189
	}
190
191
	public void testCreateHunk1() throws CoreException {
192
		IStorage patch = new StringStorage("patch_createHunk1.txt");
193
		IFilePatch[] filePatches = ApplyPatchOperation.parsePatch(patch);
194
		assertEquals(1, filePatches.length);
195
		assertEquals(1, filePatches[0].getHunks().length);
196
197
		String[] lines = new String[] { " [a]", " [b]", "-[c]", " [d]", "-[e]",
198
				" [f]", " [g]", " [h]", "+[h1]", " [i]", " [j]", "+[j1]",
199
				"+[j2]", " [k]", " [l]", " [m]" };
200
		addLineDelimiters(lines);
201
		Hunk hunk = (Hunk) PatchBuilder.createHunk(0, 0, lines);
202
203
		assertHunkEquals(hunk, (Hunk) filePatches[0].getHunks()[0]);
204
	}
205
206
	public void testCreateHunk2() throws CoreException {
207
		IStorage patch = new StringStorage("patch_createHunk2.txt");
208
		IFilePatch[] filePatches = ApplyPatchOperation.parsePatch(patch);
209
		assertEquals(1, filePatches.length);
210
		assertEquals(1, filePatches[0].getHunks().length);
211
212
		String[] lines = new String[] { "+[aa]", "+[bb]", "+[cc]" };
213
		addLineDelimiters(lines);
214
		Hunk hunk = (Hunk) PatchBuilder.createHunk(0, 0, lines);
215
216
		assertHunkEquals(hunk, (Hunk) filePatches[0].getHunks()[0]);
217
	}
218
219
	public void testCreateHunk3() throws CoreException {
220
		IStorage patch = new StringStorage("patch_createHunk3.txt");
221
		IFilePatch[] filePatches = ApplyPatchOperation.parsePatch(patch);
222
		assertEquals(1, filePatches.length);
223
		assertEquals(1, filePatches[0].getHunks().length);
224
225
		String[] lines = new String[] { "-[aa]", "-[bb]", "-[cc]", "-[dd]" };
226
		addLineDelimiters(lines);
227
		Hunk hunk = (Hunk) PatchBuilder.createHunk(0, 0, lines);
228
229
		assertHunkEquals(hunk, (Hunk) filePatches[0].getHunks()[0]);
230
	}
231
232
	private void assertHunkEquals(Hunk h1, Hunk h2) {
233
		String[] l1 = h1.getLines();
234
		String[] l2 = h2.getLines();
235
		assertEquals(l1.length, l2.length);
236
		for (int i = 0; i < l1.length; i++) {
237
			assertFalse(l1[i] == null && l2[i] != null);
238
			assertEquals(l1[i], (l2[i]));
239
		}
240
		assertEquals(h1.getStart(false), h2.getStart(false));
241
		assertEquals(h1.getStart(true), h2.getStart(true));
242
		assertEquals(h1.getLength(false), h2.getLength(false));
243
		assertEquals(h1.getLength(true), h2.getLength(true));
244
		assertEquals(h1.getHunkType(false), h2.getHunkType(false));
245
		assertEquals(h1.getHunkType(true), h2.getHunkType(true));
246
	}
247
248
	private void addLineDelimiters(String[] lines) {
249
		for (int i = 0; i < lines.length; i++) {
250
			lines[i] = lines[i] + "\r\n";
251
		}
252
	}
253
254
}
(-)patchdata/exp_createFilePatch.txt (+42 lines)
Added Link Here
1
### Eclipse Workspace Patch 1.0
2
#P Bug202944
3
Index: tmp/a.txt
4
===================================================================
5
RCS file: tmp/a.txt
6
diff -N tmp/a.txt
7
--- /dev/null	1 Jan 1970 00:00:00 -0000
Added Link Here
1
### Eclipse Workspace Patch 1.0
2
#P Bug202944
3
Index: tmp/list.txt
4
===================================================================
5
RCS file: /TEST/Bug202944/tmp/list.txt,v
6
retrieving revision 1.2
7
diff -u -r1.2 list.txt
8
--- tmp/list.txt	20 Feb 2009 11:02:27 -0000	1.2
Added Link Here
1
[a1]
2
[a2]
3
[a3]
4
[a]
5
[b]
6
[d]
7
[f]
8
[g]
9
[h]
10
[h1]
11
[i]
12
[j]
13
[j1]
14
[j2]
15
[k]
16
[l]
17
[m]
18
[n]
19
[o]
20
[p]
21
[q]
22
[r]
23
[s]
24
[t]
25
[u]
26
[v]
27
[w]
(-)patchdata/exp_modifyHunks.txt (+28 lines)
Added Link Here
1
[a]
2
[b]
3
[c]
4
[d]
5
[d1]
6
[d2]
7
[d3]
8
[d4]
9
[e]
10
[f]
11
[g]
12
[h]
13
[i1]
14
[j]
15
[k]
16
[l]
17
[m]
18
[n]
19
[o]
20
[p]
21
[q]
22
[r]
23
[s]
24
[s1]
25
[t]
26
[u]
27
[v]
28
[w]
(-)compare/org/eclipse/compare/internal/patch/FileDiffWrapper.java (+25 lines)
Added Link Here
1
### Eclipse Workspace Patch 1.0
2
#P Bug202944
3
Index: tmp/list.txt
4
===================================================================
5
RCS file: /TEST/Bug202944/tmp/list.txt,v
6
retrieving revision 1.2
7
diff -u -r1.2 list.txt
8
--- tmp/list.txt	20 Feb 2009 11:02:27 -0000	1.2
Added Link Here
1
--- old.txt	2005-05-07 00:16:20.000000000 +0200
Added Link Here
1
### Eclipse Workspace Patch 1.0
2
#P Bug202944
3
Index: tmp/a.txt
4
===================================================================
5
RCS file: /TEST/Bug202944/tmp/a.txt,v
6
retrieving revision 1.1
7
diff -u -r1.1 a.txt
8
--- tmp/a.txt	20 Feb 2009 11:37:35 -0000	1.1
Added Link Here
75
		return fileDiff.getHunks();
75
		return fileDiff.getHunks();
76
	}
76
	}
77
77
78
	public IPath getAfterPath() {
79
		return fileDiff.getAfterPath();
80
	}
81
82
	public IPath getBeforePath() {
83
		return fileDiff.getBeforePath();
84
	}
85
78
}
86
}
(-)src/org/eclipse/compare/internal/core/patch/FileDiffResult.java (-4 / +13 lines)
Lines 259-267 Link Here
259
259
260
	public List getFailedHunks() {
260
	public List getFailedHunks() {
261
		List failedHunks = new ArrayList();
261
		List failedHunks = new ArrayList();
262
		for (Iterator iterator = fHunkResults.values().iterator(); iterator.hasNext();) {
262
		IHunk[] hunks = fDiff.getHunks();
263
			HunkResult result = (HunkResult) iterator.next();
263
		for (int i = 0; i < hunks.length; i++) {
264
			if (!result.isOK())
264
			HunkResult result = (HunkResult) fHunkResults.get(hunks[i]);
265
			if (result != null && !result.isOK())
265
				failedHunks.add(result.getHunk());
266
				failedHunks.add(result.getHunk());
266
		}
267
		}
267
		return failedHunks;
268
		return failedHunks;
Lines 280-286 Link Here
280
	}
281
	}
281
282
282
	public HunkResult[] getHunkResults() {
283
	public HunkResult[] getHunkResults() {
283
		return (HunkResult[]) fHunkResults.values().toArray(new HunkResult[fHunkResults.size()]);
284
		List results = new ArrayList();
285
		IHunk[] hunks = fDiff.getHunks();
286
		for (int i = 0; i < hunks.length; i++) {
287
			HunkResult result = (HunkResult) fHunkResults.get(hunks[i]);
288
			if (result != null) {
289
				results.add(result.getHunk());
290
			}
291
		}
292
		return (HunkResult[]) results.toArray(new HunkResult[results.size()]);
284
	}
293
	}
285
294
286
	public InputStream getOriginalContents() {
295
	public InputStream getOriginalContents() {
(-)src/org/eclipse/compare/internal/core/patch/FileDiff.java (+8 lines)
Lines 258-261 Link Here
258
		return removedLines;
258
		return removedLines;
259
	}
259
	}
260
260
261
	public IPath getBeforePath() {
262
		return fOldPath;
263
	}
264
265
	public IPath getAfterPath() {
266
		return fNewPath;
267
	}
268
261
}
269
}
(-)src/org/eclipse/compare/internal/core/patch/Hunk.java (-6 / +18 lines)
Lines 127-133 Link Here
127
		return sb.toString();
127
		return sb.toString();
128
	}
128
	}
129
	
129
	
130
	int getHunkType(boolean reverse) {
130
	public int getHunkType(boolean reverse) {
131
		if (reverse) {
131
		if (reverse) {
132
			if (hunkType == FileDiff.ADDITION)
132
			if (hunkType == FileDiff.ADDITION)
133
				return FileDiff.DELETION;
133
				return FileDiff.DELETION;
Lines 145-150 Link Here
145
		return fLines;
145
		return fLines;
146
	}
146
	}
147
147
148
	public String[] getUnifiedLines() {
149
		return fLines;
150
	}
151
148
	/**
152
	/**
149
	 * Set the parent of this hunk. This method
153
	 * Set the parent of this hunk. This method
150
	 * should only be invoked from {@link FileDiff#add(Hunk)}
154
	 * should only be invoked from {@link FileDiff#add(Hunk)}
Lines 291-305 Link Here
291
		return true;
295
		return true;
292
	}
296
	}
293
	
297
	
294
	int getStart(boolean reverse) {
298
	public int getStart(boolean after) {
295
		if (reverse) {
299
		if (after) {
296
			return fNewStart;
300
			return fNewStart;
297
		}
301
		}
298
		return fOldStart;
302
		return fOldStart;
299
	}
303
	}
300
	
304
301
	private int getLength(boolean reverse) {
305
	public void setStart(int start, boolean after) {
302
		if (reverse) {
306
		if (after) {
307
			fNewStart = start;
308
		} else {
309
			fOldStart = start;
310
		}
311
	}
312
313
	public int getLength(boolean after) {
314
		if (after) {
303
			return fNewLength;
315
			return fNewLength;
304
		}
316
		}
305
		return fOldLength;
317
		return fOldLength;
(-)src/org/eclipse/compare/patch/IHunk.java (-1 / +16 lines)
Lines 56-62 Link Here
56
	 * @return the contents that contain the modifications for this hunk
56
	 * @return the contents that contain the modifications for this hunk
57
	 */
57
	 */
58
	public InputStream getPatchedContents();
58
	public InputStream getPatchedContents();
59
	
59
60
	/**
61
	 * Returns hunk's content in a unified format. This is an internal format in
62
	 * which hunk stores it's content and is always the same even if the hunk
63
	 * was extracted from a patch stored in a different format. In a unified
64
	 * format each line is prefixed with one of the following:
65
	 * <ul>
66
	 * <li> <code>' '</code> for context
67
	 * <li> <code>'+'</code> for addition
68
	 * <li> <code>'+'</code> for removal
69
	 * </ul>
70
	 * 
71
	 * @return hunk's content in a unified format
72
	 */
73
	public String[] getUnifiedLines();
74
60
	/**
75
	/**
61
	 * Returns the name of a charset encoding to be used when decoding the contents 
76
	 * Returns the name of a charset encoding to be used when decoding the contents 
62
	 * of this hunk into characters. Returns <code>null</code> if a proper 
77
	 * of this hunk into characters. Returns <code>null</code> if a proper 
(-)src/org/eclipse/compare/patch/IFilePatch2.java (+14 lines)
Lines 80-85 Link Here
80
	public long getAfterDate();
80
	public long getAfterDate();
81
81
82
	/**
82
	/**
83
	 * Returns the path of the before state of the file.
84
	 * 
85
	 * @return the path of the before state of the file
86
	 */
87
	IPath getBeforePath();
88
89
	/**
90
	 * Returns the path of the after state of the file.
91
	 * 
92
	 * @return the path of the after state of the file
93
	 */
94
	IPath getAfterPath();
95
96
	/**
83
	 * Returns all the hunks this file patch contains.
97
	 * Returns all the hunks this file patch contains.
84
	 * 
98
	 * 
85
	 * @return array of hunks
99
	 * @return array of hunks
(-)src/org/eclipse/compare/patch/PatchBuilder.java (+323 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 IBM Corporation 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
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.compare.patch;
12
13
import java.util.Arrays;
14
import java.util.Comparator;
15
16
import org.eclipse.compare.internal.core.patch.FileDiff;
17
import org.eclipse.compare.internal.core.patch.Hunk;
18
import org.eclipse.core.runtime.IPath;
19
20
/**
21
 * Builder for creating IFilePatch2 and IHunk objects as well as building
22
 * relationship between them.
23
 * 
24
 * @since org.eclipse.compare.core 1.0.0
25
 */
26
public class PatchBuilder {
27
28
	public static final char CONTEXT_PREFIX = ' ';
29
	public static final char ADDITION_PREFIX = '+';
30
	public static final char REMOVAL_PREFIX = '-';
31
32
	/**
33
	 * Creates an IFilePatch2 instance.
34
	 * 
35
	 * @param oldPath
36
	 *            the path of the before state of the file
37
	 * @param oldDate
38
	 *            the timestamp of the before state, see also
39
	 *            {@link IFilePatch2#DATE_UNKNOWN}
40
	 * @param newPath
41
	 *            the path of the after state
42
	 * @param newDate
43
	 *            the timestamp of the after state, see also
44
	 *            {@link IFilePatch2#DATE_UNKNOWN}
45
	 * @param hunks
46
	 *            hunks to insert into IFilePatch2
47
	 * @param sort
48
	 *            whether to sort hunks
49
	 * @return IFilePatch2 instance
50
	 */
51
	public static IFilePatch2 createFilePatch(IPath oldPath, long oldDate,
52
			IPath newPath, long newDate, IHunk[] hunks, boolean sort) {
53
		if (sort) {
54
			Arrays.sort(hunks, new HunkComparator());
55
		}
56
		FileDiff fileDiff = new FileDiff(oldPath, oldDate, newPath, newDate);
57
		for (int i = 0; i < hunks.length; i++) {
58
			fileDiff.add((Hunk) hunks[i]);
59
		}
60
		return fileDiff;
61
	}
62
63
	/**
64
	 * Creates an IHunk instance.
65
	 * 
66
	 * @param oldStart
67
	 *            the start position in the before file
68
	 * @param newStart
69
	 *            the start position in the after file
70
	 * @param lines
71
	 *            content of the hunk. Each line starts with a control
72
	 *            character. Their meaning is as follows:
73
	 *            <ul>
74
	 *            <li>
75
	 *            '+': add the line
76
	 *            <li>
77
	 *            '-': delete the line
78
	 *            <li>
79
	 *            ' ': no change, context line
80
	 *            </ul>
81
	 * @return IHunk instance
82
	 */
83
	public static IHunk createHunk(int oldStart, int newStart, String[] lines) {
84
		int hunkType = getHunkType(lines);
85
		int oldLength = getLength(lines, true);
86
		int newLength = getLength(lines, false);
87
		return new Hunk(null, hunkType, oldStart, oldLength, newStart,
88
				newLength, lines);
89
	}
90
91
	/**
92
	 * Adds IHunks to a given IFilePatch2 and performs recalculation of already
93
	 * present IHunks. Such recalculation is needed to move start position of
94
	 * IHunks that existed in a IFilePatch2 on positions after more hunks have
95
	 * been put.
96
	 * 
97
	 * @param filePatch
98
	 *            a file patch to add hunks to
99
	 * @param toAdd
100
	 *            an array of IHunks to add
101
	 * @param recalculate
102
	 *            whether to recalculate start position of hunks that existed in
103
	 *            the patch
104
	 * @return newly created file patch with added hunks
105
	 */
106
	public static IFilePatch2 addHunks(IFilePatch2 filePatch, IHunk[] toAdd,
107
			boolean recalculate) {
108
		IHunk[] result = addHunks(filePatch.getHunks(), toAdd, recalculate);
109
		return createFilePatch(filePatch.getBeforePath(), filePatch
110
				.getBeforeDate(), filePatch.getAfterPath(), filePatch
111
				.getAfterDate(), result, false);
112
	}
113
114
	/**
115
	 * Removes IHunks from a given IFilePatch2 and performs recalculation of
116
	 * already present IHunks. Such recalculation is needed to move start
117
	 * position of IHunk that existed in a IFilePatch2 on position after other
118
	 * hunk is removed.
119
	 * 
120
	 * @param filePatch
121
	 *            a file patch to add hunks to
122
	 * @param toRemove
123
	 *            an array of IHunks to add
124
	 * @param recalculate
125
	 *            whether to recalculate start position of hunks that existed in
126
	 *            the patch
127
	 * @return newly created file patch with removed hunks
128
	 */
129
	public static IFilePatch2 removeHunks(IFilePatch2 filePatch,
130
			IHunk[] toRemove, boolean recalculate) {
131
		IHunk[] result = removeHunks(filePatch.getHunks(), toRemove,
132
				recalculate);
133
		return createFilePatch(filePatch.getBeforePath(), filePatch
134
				.getBeforeDate(), filePatch.getAfterPath(), filePatch
135
				.getAfterDate(), result, false);
136
	}
137
138
	/**
139
	 * Returns hunk type given the hunk content.
140
	 * 
141
	 * @param lines
142
	 *            content of the hunk
143
	 * @return hunk type
144
	 */
145
	private static int getHunkType(String[] lines) {
146
		boolean hasContextLines = checkForPrefix(CONTEXT_PREFIX, lines);
147
		if (!hasContextLines) {
148
			boolean hasLineAdditions = checkForPrefix(ADDITION_PREFIX, lines);
149
			boolean hasLineDeletions = checkForPrefix(REMOVAL_PREFIX, lines);
150
			if (hasLineAdditions && !hasLineDeletions) {
151
				return FileDiff.ADDITION;
152
			} else if (!hasLineAdditions && hasLineDeletions) {
153
				return FileDiff.DELETION;
154
			}
155
		}
156
		return FileDiff.CHANGE;
157
	}
158
159
	/**
160
	 * Check if any of the passed lines starts with a given prefix.
161
	 * 
162
	 * @param prefix
163
	 *            the prefix to search for
164
	 * @param lines
165
	 *            the array of lines to be searched for prefix
166
	 * @return if any of the passed lines starts with a given prefix
167
	 */
168
	private static boolean checkForPrefix(char prefix, String[] lines) {
169
		for (int i = 0; i < lines.length; i++) {
170
			if (lines[i].length() > 0) {
171
				if (lines[i].charAt(0) == prefix) {
172
					return true;
173
				}
174
			}
175
		}
176
		return false;
177
	}
178
179
	/**
180
	 * Return the length of hunk in terms of lines of the before the apply state
181
	 * or after.
182
	 * 
183
	 * @param lines
184
	 *            the lines to count
185
	 * @param old
186
	 *            whether to count lines in the before state of after state
187
	 * @return
188
	 */
189
	private static int getLength(String[] lines, boolean old) {
190
		int length = 0;
191
		for (int i = 0; i < lines.length; i++) {
192
			if (lines[i].length() > 0) {
193
				switch (lines[i].charAt(0)) {
194
				case ' ':
195
					length++;
196
					break;
197
				case '+':
198
					if (!old) {
199
						length++;
200
					}
201
					break;
202
				case '-':
203
					if (old) {
204
						length++;
205
					}
206
					break;
207
				default:
208
					throw new IllegalArgumentException("");
209
				}
210
			}
211
		}
212
		return length;
213
	}
214
215
	/**
216
	 * Merge
217
	 * 
218
	 * @param hunks
219
	 * @param toAdd
220
	 * @param recalculate
221
	 * @return
222
	 */
223
	private static IHunk[] addHunks(IHunk[] hunks, IHunk[] toAdd,
224
			boolean recalculate) {
225
		IHunk[] merged = addHunks(hunks, toAdd);
226
		Arrays.sort(merged, new HunkComparator());
227
		if (recalculate) {
228
			Arrays.sort(toAdd, new HunkComparator());
229
			int shift = 0;
230
			for (int i = 0, j = 0; i < merged.length; i++) {
231
				Hunk hunk = (Hunk) merged[i];
232
				if (j < toAdd.length && hunk == toAdd[j]) {
233
					shift += hunk.getLength(true) - hunk.getLength(false);
234
					j++;
235
				} else {
236
					int start = hunk.getStart(true) + shift;
237
					hunk.setStart(start, true);
238
				}
239
			}
240
		}
241
		return merged;
242
	}
243
244
	/**
245
	 * @param hunks
246
	 * @param toAdd
247
	 * @return
248
	 */
249
	private static IHunk[] addHunks(IHunk[] hunks, IHunk[] toAdd) {
250
		IHunk[] ret = new IHunk[hunks.length + toAdd.length];
251
		System.arraycopy(hunks, 0, ret, 0, hunks.length);
252
		System.arraycopy(toAdd, 0, ret, hunks.length, toAdd.length);
253
		Arrays.sort(ret, new HunkComparator());
254
		return ret;
255
	}
256
257
	/**
258
	 * @param hunks
259
	 * @param toRemove
260
	 * @param recalculate
261
	 * @return
262
	 */
263
	private static IHunk[] removeHunks(IHunk[] hunks, IHunk[] toRemove,
264
			boolean recalculate) {
265
		if (recalculate) {
266
			Arrays.sort(hunks, new HunkComparator());
267
			Arrays.sort(toRemove, new HunkComparator());
268
			int shift = 0;
269
			for (int i = 0, j = 0; i < hunks.length; i++) {
270
				Hunk hunk = (Hunk) hunks[i];
271
				if (j < toRemove.length && hunk == toRemove[j]) {
272
					shift += hunk.getLength(true) - hunk.getLength(false);
273
					j++;
274
				} else {
275
					int start = hunk.getStart(true) - shift;
276
					hunk.setStart(start, true);
277
				}
278
			}
279
		}
280
		return removeHunks(hunks, toRemove);
281
	}
282
283
	/**
284
	 * @param hunks
285
	 * @param toRemove
286
	 * @return
287
	 */
288
	private static IHunk[] removeHunks(IHunk[] hunks, IHunk[] toRemove) {
289
		int removed = 0;
290
		for (int i = 0; i < hunks.length; i++) {
291
			for (int j = 0; j < toRemove.length; j++) {
292
				if (toRemove[j] == hunks[i]) {
293
					hunks[i] = null;
294
					removed++;
295
				}
296
			}
297
		}
298
		IHunk[] ret = new IHunk[hunks.length - removed];
299
		for (int i = 0, j = 0; i < hunks.length; i++) {
300
			if (hunks[i] != null) {
301
				ret[j++] = hunks[i];
302
			}
303
		}
304
		return ret;
305
	}
306
307
	/**
308
	 * Helper class to compare IHunks.
309
	 */
310
	private static class HunkComparator implements Comparator {
311
		public int compare(Object arg0, Object arg1) {
312
			if ((arg0 != null && arg0 instanceof Hunk)
313
					&& (arg1 != null && arg1 instanceof Hunk)) {
314
				Hunk hunk0 = (Hunk) arg0;
315
				Hunk hunk1 = (Hunk) arg1;
316
				int shift = hunk0.getStart(true) - hunk1.getStart(true);
317
				return shift;
318
			}
319
			return 0;
320
		}
321
	}
322
323
}

Return to bug 183226