Skip to main content
summaryrefslogtreecommitdiffstats
blob: 8ef8b53ad7a4961fbf31415e08c38ac868d99f45 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.team.tests.ccvs.core.provider;
import java.io.*;
import java.util.*;

import junit.framework.Test;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.team.core.*;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.*;
import org.eclipse.team.internal.ccvs.core.client.Command.KSubstOption;
import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
import org.eclipse.team.tests.ccvs.core.EclipseTest;

/*
 * This class tests both the CVSProvider and the CVSTeamProvider
 */
public class CVSProviderTest extends EclipseTest {

	/**
	 * Constructor for CVSProviderTest
	 */
	public CVSProviderTest() {
		super();
	}

	/**
	 * Constructor for CVSProviderTest
	 */
	public CVSProviderTest(String name) {
		super(name);
	}

	public static Test suite() {
		return suite(CVSProviderTest.class);
	}
	
	public void testAdd() throws TeamException, CoreException {
		
		// Test add with cvsignores
		/*
		IProject project = createProject("testAdd", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt" });
		IFile file = project.getFile(".cvsignore");
		file.create(new ByteArrayInputStream("ignored.txt".getBytes()), false, null);
		file = project.getFile("ignored.txt");
		file.create(new ByteArrayInputStream("some text".getBytes()), false, null);
		file = project.getFile("notignored.txt");
		file.create(new ByteArrayInputStream("some more text".getBytes()), false, null);
		file = project.getFile("folder1/.cvsignore");
		file.create(new ByteArrayInputStream("ignored.txt".getBytes()), false, null);
		file = project.getFile("folder1/ignored.txt");
		file.create(new ByteArrayInputStream("some text".getBytes()), false, null);
		file = project.getFile("folder1/notignored.txt");
		file.create(new ByteArrayInputStream("some more text".getBytes()), false, null);
		
		getProvider(project).add(new IResource[] {project}, IResource.DEPTH_INFINITE, DEFAULT_MONITOR);
		
		assertTrue( ! CVSWorkspaceRoot.getCVSResourceFor(project.getFile("ignored.txt")).isManaged());
		assertTrue( ! CVSWorkspaceRoot.getCVSResourceFor(project.getFile("folder1/ignored.txt")).isManaged());
		
		assertTrue(CVSWorkspaceRoot.getCVSResourceFor(project.getFile("notignored.txt")).isManaged());
		assertTrue(CVSWorkspaceRoot.getCVSResourceFor(project.getFile("folder1/notignored.txt")).isManaged());
		assertTrue(CVSWorkspaceRoot.getCVSResourceFor(project.getFile(".cvsignore")).isManaged());
		assertTrue(CVSWorkspaceRoot.getCVSResourceFor(project.getFile("folder1/.cvsignore")).isManaged());
		*/
	}
	
	public void testDeleteHandling() throws TeamException, CoreException {
		
		IProject project = createProject("testDeleteHandling", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt" });
		
		// Delete a file and ensure that it is an outgoing deletion
		project.getFile("deleted.txt").delete(false, false, null);
		ICVSFile file = CVSWorkspaceRoot.getCVSFileFor(project.getFile("deleted.txt"));
		assertTrue("File is not outgoing deletion", file.getSyncInfo().isDeleted());
		
		// Delete a folder and ensure that the file is managed but doesn't exist
		// (Special behavior is provider by the CVS move/delete hook but this is not part of CVS core)
		project.getFolder("folder1").delete(false, false, null);
		ICVSFolder folder = CVSWorkspaceRoot.getCVSFolderFor(project.getFolder("folder1"));
		assertTrue("Deleted folder not in proper state", ! folder.exists() && folder.isManaged());
	}
	
	public void testCheckin() throws TeamException, CoreException, IOException {
		IProject project = createProject("testCheckin", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt" });
		
		// Perform some operations on the project
		IResource[] newResources = buildResources(project, new String[] { "added.txt", "folder2/", "folder2/added.txt" }, false);
		setContentsAndEnsureModified(project.getFile("changed.txt"));
		addResources(newResources);
		deleteResources(new IResource[] {project.getFile("deleted.txt")});
		assertIsModified("testDeepCheckin: ", newResources);
		assertIsModified("testDeepCheckin: ", new IResource[] {project.getFile("deleted.txt"), project.getFile("changed.txt")});
		commitResources(new IResource[] {project}, IResource.DEPTH_INFINITE);
		assertLocalStateEqualsRemote(project);
	}
	
	public void testMoveHandling() throws TeamException, CoreException {
		IProject project = createProject("testMoveHandling", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt" });
		
		// Move a file and ensure that it is an outgoing deletion at the source and unmanaged at the destination
		project.getFile("deleted.txt").move(new Path("moved.txt"), false, false, null);
		ICVSFile file = CVSWorkspaceRoot.getCVSFileFor(project.getFile("deleted.txt"));
		assertTrue("Source is not outgoing deletion", file.getSyncInfo().isDeleted());
		file = CVSWorkspaceRoot.getCVSFileFor(project.getFile("moved.txt"));
		assertTrue("Destination not in proper state", ! file.isManaged());
		
		// Move a folder and ensure the source is deleted
		project.getFolder("folder1").move(new Path("moved"), false, false, null);
		ICVSFolder folder = CVSWorkspaceRoot.getCVSFolderFor(project.getFolder("folder1"));
		assertTrue("Deleted folder not in proper state", ! folder.exists() && folder.isManaged());
		folder = CVSWorkspaceRoot.getCVSFolderFor(project.getFolder("moved"));
		assertTrue("Moved folder should not be managed", ! folder.isManaged());
		assertTrue("Moved folder should not be a CVS folder", ! folder.isCVSFolder());
	}
	
	public void testUpdate() throws TeamException, CoreException, IOException {
		// Create a test project, import it into cvs and check it out
		IProject project = createProject("testUpdate", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt" });

		// Check the project out under a different name
		IProject copy = checkoutCopy(project, "-copy");
		
		// Perform some operations on the copy
		addResources(copy, new String[] { "added.txt", "folder2/", "folder2/added.txt" }, false);
		setContentsAndEnsureModified(copy.getFile("changed.txt"));
		deleteResources(new IResource[] {copy.getFile("deleted.txt")});
		
		// Commit the copy and update the project
		commitResources(new IResource[] {copy}, IResource.DEPTH_INFINITE);
		updateProject(project, null, false);
		assertEquals(project, copy);
	}
	
	public void testUpdate123280() throws CoreException {
		IProject project = createProject(new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt" });
		
		// Make a remote change
		IProject copy = checkoutCopy(project, "-copy");
		setContentsAndEnsureModified(copy.getFile("folder1/a.txt"));
		commitProject(copy);
		
		// Delete locally and then update
		project.getFile("deleted.txt").delete(false, null);
		updateProject(project, null, false);
		// Ensure that the file is still an outgoing deletion
		ICVSFile file = CVSWorkspaceRoot.getCVSFileFor(project.getFile("deleted.txt"));
		assertTrue(!file.exists() && file.isManaged());
	}
	
	public void testVersionTag() throws TeamException, CoreException, IOException {
		
		// Create a test project, import it into cvs and check it out
		IProject project = createProject("testVersionTag", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt" });
		
		// Perform some operations on the copy and commit
		IProject copy = checkoutCopy(project, "-copy");
		addResources(copy, new String[] { "added.txt", "folder2/", "folder2/added.txt" }, false);
		changeResources(copy, new String[] {"changed.txt"}, false);
		deleteResources(copy, new String[] {"deleted.txt"}, false);
		commitResources(copy, true);
		
		// Tag the original, checkout the tag and compare with original
		CVSTag v1Tag = new CVSTag("v1", CVSTag.VERSION);
		tagProject(project, v1Tag, false);
		IProject v1 = checkoutCopy(project, v1Tag);
		assertEquals(project, v1);
		
		// Update original to HEAD and compare with copy including tags
		updateProject(project, null, false);
		assertEquals(project, copy, false, true);
		
		// Update copy to v1 and compare with the copy (including tag)
		updateProject(copy, v1Tag, false);
		assertEquals(copy, v1, false, true);
		
		// Update copy back to HEAD and compare with project (including tag)
		updateProject(copy, CVSTag.DEFAULT, false);
		assertEquals(project, copy, false, true);
	}
	
	public void testMakeBranch() throws TeamException, CoreException, IOException {
		// Create a test project
		IProject project = createProject("testMakeBranch", new String[] { "file1.txt", "file2.txt", "file3.txt", "folder1/", "folder1/a.txt", "folder1/b.txt"});

		// Make some local modifications including "cvs adds" and "cvs removes"
		addResources(project, new String[] {"folder1/c.txt"}, false);
		deleteResources(project, new String[] {"folder1/b.txt"}, false);
		changeResources(project, new String[] {"file2.txt"}, false);
		
		// Make the branch including a pre-version
		CVSTag version = new CVSTag("v1", CVSTag.BRANCH);
		CVSTag branch = new CVSTag("branch1", CVSTag.BRANCH);
		makeBranch(new IResource[] {project}, version, branch, true);

		// Checkout a copy from the branch and version and compare
		IProject branchCopy = checkoutCopy(project, branch);
		IProject versionCopy = checkoutCopy(project, version);
		assertEquals(branchCopy, versionCopy, true, false);
		
		// Commit the project, update the branch and compare
		commitProject(project);
		updateProject(branchCopy, null, false);
		assertEquals(branchCopy, project, false, true);
	}

	public void testPruning() throws TeamException, CoreException, IOException {
		// Create a project with empty folders
		CVSProviderPlugin.getPlugin().setPruneEmptyDirectories(false);
		IProject project = createProject("testPruning", new String[] { "file.txt", "folder1/", "folder2/folder3/" });

		// Disable pruning, checkout a copy and ensure original and copy are the same
		IProject copy = checkoutCopy(project, "-copy");
		assertEquals(project, copy); 

		// Enable pruning, update copy and ensure emtpy folders are gone
		CVSProviderPlugin.getPlugin().setPruneEmptyDirectories(true);
		updateProject(copy, null, false);
		assertDoesNotExistInFileSystem(new IResource[] {copy.getFolder("folder1"), copy.getFolder("folder2"), copy.getFolder("folder2/folder3")});
		
		// Checkout another copy and ensure that the two copies are the same (with pruning enabled)
		IProject copy2 = checkoutCopy(project, "-copy2");
		assertEquals(copy, copy2); 
		
		// Disable pruning, update copy and ensure directories come back
		// TODO: disabled until bug 125037 can be resolved
//		CVSProviderPlugin.getPlugin().setPruneEmptyDirectories(false);
//		updateProject(copy, null, false);
//		assertEquals(project, copy);
		
		// Enable pruning again since it's the default
		CVSProviderPlugin.getPlugin().setPruneEmptyDirectories(true);
	}

	public void testGet() throws TeamException, CoreException, IOException {
		
		// Create a project
		IProject project = createProject("testGet", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt" });
		
		// Checkout a copy and modify locally
		IProject copy = checkoutCopy(project, "-copy");
		//addResources(copy, new String[] { "added.txt", "folder2/", "folder2/added.txt" }, false);
		deleteResources(copy, new String[] {"deleted.txt"}, false);
		setContentsAndEnsureModified(copy.getFile("changed.txt"));

		// get the remote conetns
		replace(new IResource[] {copy}, null, true);
		assertEquals(project, copy);
	}
	
	public void testReadOnly() throws TeamException, CoreException, IOException {
		IProject project = createProject("testReadOnly", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt" });
		// Need to check the project out as read-only
	}
	
	public void testCleanLineDelimiters() throws TeamException, CoreException, IOException {
		// Create a project
		IProject project = getUniqueTestProject("testCleanLineDelimiters");
		IFile file = project.getFile("testfile");
		IProgressMonitor monitor = new NullProgressMonitor();

		// empty file
		setFileContents(file, "");
		CVSTeamProvider.cleanLineDelimiters(file, false, monitor);
		assertEqualsFileContents(file, "");
		CVSTeamProvider.cleanLineDelimiters(file, true, monitor);
		assertEqualsFileContents(file, "");
		
		// one byte
		setFileContents(file, "a");
		CVSTeamProvider.cleanLineDelimiters(file, false, monitor);
		assertEqualsFileContents(file, "a");
		CVSTeamProvider.cleanLineDelimiters(file, true, monitor);
		assertEqualsFileContents(file, "a");
		
		// single orphan carriage return (should be preserved)
		setFileContents(file, "\r");
		CVSTeamProvider.cleanLineDelimiters(file, false, monitor);
		assertEqualsFileContents(file, "\r");
		CVSTeamProvider.cleanLineDelimiters(file, true, monitor);
		assertEqualsFileContents(file, "\r");

		// single line feed
		setFileContents(file, "\n");
		CVSTeamProvider.cleanLineDelimiters(file, false, monitor);
		assertEqualsFileContents(file, "\n");
		CVSTeamProvider.cleanLineDelimiters(file, true, monitor);
		assertEqualsFileContents(file, "\r\n");
		
		// single carriage return line feed
		setFileContents(file, "\r\n");
		CVSTeamProvider.cleanLineDelimiters(file, true, monitor);
		assertEqualsFileContents(file, "\r\n");
		CVSTeamProvider.cleanLineDelimiters(file, false, monitor);
		assertEqualsFileContents(file, "\n");
		
		// mixed text with orphaned CR's
		setFileContents(file, "The \r\n quick brown \n fox \r\r\r\n jumped \n\n over \r\n the \n lazy dog.\r\n");
		CVSTeamProvider.cleanLineDelimiters(file, false, monitor);
		assertEqualsFileContents(file, "The \n quick brown \n fox \r\r\n jumped \n\n over \n the \n lazy dog.\n");
		setFileContents(file, "The \r\n quick brown \n fox \r\r\r\n jumped \n\n over \r\n the \n lazy dog.\r\n");
		CVSTeamProvider.cleanLineDelimiters(file, true, monitor);
		assertEqualsFileContents(file, "The \r\n quick brown \r\n fox \r\r\r\n jumped \r\n\r\n over \r\n the \r\n lazy dog.\r\n");
	}
	
	public void testKeywordSubstitution() throws TeamException, CoreException, IOException {
		testKeywordSubstitution(Command.KSUBST_BINARY); // -kb
		testKeywordSubstitution(Command.KSUBST_TEXT); // -ko
		testKeywordSubstitution(Command.KSUBST_TEXT_EXPAND); // -kkv
	}

	private void testKeywordSubstitution(KSubstOption ksubst) throws TeamException, CoreException, IOException {
		// setup some known file types
		Team.setAllTypes( new String[] {"xbin", "xtxt"}, new int[] {Team.BINARY, Team.TEXT});
		
		// create a test project
		IProject project = createProject("testKeywordSubstitution", new String[] { "dummy" });
		addResources(project, new String[] { "binary.xbin", "text.xtxt", "folder1/", "folder1/a.xtxt" }, true);
		addResources(project, new String[] { "added.xbin", "added.xtxt" }, false);
		assertHasKSubstOption(project, "binary.xbin", Command.KSUBST_BINARY);
		assertHasKSubstOption(project, "added.xbin", Command.KSUBST_BINARY);
		assertHasKSubstOption(project, "text.xtxt", CVSProviderPlugin.DEFAULT_TEXT_KSUBST_OPTION);
		assertHasKSubstOption(project, "folder1/a.xtxt", CVSProviderPlugin.DEFAULT_TEXT_KSUBST_OPTION);
		assertHasKSubstOption(project, "added.xtxt", CVSProviderPlugin.DEFAULT_TEXT_KSUBST_OPTION);
		
		// change keyword substitution
		Map map = new HashMap();
		map.put(project.getFile("binary.xbin"), ksubst);
		map.put(project.getFile("added.xbin"), ksubst);
		map.put(project.getFile("text.xtxt"), ksubst);
		map.put(project.getFile("folder1/a.xtxt"), ksubst);
		map.put(project.getFile("added.xtxt"), ksubst);
		
		waitMsec(1500);
		IStatus status = getProvider(project).setKeywordSubstitution(map, null, null);
		assertTrue("Status should be ok, was: " + status.toString(), status.isOK());
		assertHasKSubstOption(project, "binary.xbin", ksubst);
		assertHasKSubstOption(project, "text.xtxt", ksubst);
		assertHasKSubstOption(project, "folder1/a.xtxt", ksubst);
		assertHasKSubstOption(project, "added.xtxt", ksubst);
		assertHasKSubstOption(project, "added.xbin", ksubst);

		// verify that substitution mode changed remotely and "added.xtxt", "added.xbin" don't exist
		IProject copy = checkoutCopy(project, "-copy");
		assertHasKSubstOption(copy, "binary.xbin", ksubst);
		assertHasKSubstOption(copy, "text.xtxt", ksubst);
		assertHasKSubstOption(copy, "folder1/a.xtxt", ksubst);
		assertDoesNotExistInWorkspace(copy.getFile("added.xtxt"));
		assertDoesNotExistInWorkspace(copy.getFile("added.xbin"));
		
		// commit added files then checkout the copy again
		commitResources(project, new String[] { "added.xbin", "added.xtxt" });
		IProject copy2 = checkoutCopy(project, "-copy2");
		assertHasKSubstOption(copy2, "added.xtxt", ksubst);
		assertHasKSubstOption(copy2, "added.xbin", ksubst);
		
		IFileTypeInfo[] infos = Team.getDefaultTypes();
		String[] extensions = new String[infos.length];
		int[] types = new int[infos.length];
		for (int i = 0; i < infos.length; i++) {
			IFileTypeInfo info = infos[i];
			extensions[i] = info.getExtension();
			types[i] = info.getType();
		}
		Team.setAllTypes(extensions, types);
	}
	
	public void testKeywordSubsBinToText() throws TeamException, CoreException, IOException {
		//create a test project
		KSubstOption ksubst = Command.KSUBST_TEXT;
		IProject project = createProject("testKeywordSubsBinToText", new String[] { "dummy" });
		assertHasKSubstOption(project, "dummy", Command.KSUBST_BINARY);
	
		// change keyword substitution
		Map map = new HashMap();
		map.put(project.getFile("dummy"), ksubst);
		
		// change from binary to text should commit a new file with 
		waitMsec(1500);
		IStatus status = getProvider(project).setKeywordSubstitution(map, null, null);
		assertTrue("Status should be ok, was: " + status.toString(), status.isOK());
		assertHasKSubstOption(project, "dummy", ksubst);

		IProject copy = checkoutCopy(project, "-copy");
		assertHasKSubstOption(copy, "dummy", ksubst);
		assertEquals(project, copy);		 		
	}
	
	public static void setFileContents(IFile file, String string) throws CoreException {
		InputStream is = new ByteArrayInputStream(string.getBytes());
		if (file.exists()) {
			file.setContents(is, false /*force*/, true /*keepHistory*/, null);
		} else {
			file.create(is, false /*force*/, null);
		}
	}
	
	public static void assertEqualsFileContents(IFile file, String string) throws CoreException, IOException {
		String other = getFileContents(file);
		assertEquals(string, other);
	}
	
	public static void assertHasKSubstOption(IContainer container, String filename, KSubstOption ksubst)
		throws TeamException {
		IFile file = container.getFile(new Path(filename));
		ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor(file);
		ResourceSyncInfo info = cvsFile.getSyncInfo();
		assertEquals(ksubst, info.getKeywordMode());
	}
	
	public void testUnmap() throws CoreException, TeamException {
		// Create a project
		IProject project = createProject("testUnmap", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt", "folder1/", "folder1/folder2/deep.txt", "folder2/b.txt" });
		// delete a file and folder to create phantoms
		project.getFile("deleted.txt").delete(false, false, null);
		assertTrue(project.getFile("deleted.txt").isPhantom());
		project.getFolder("folder2").delete(false, false, null);
		assertTrue(project.getFolder("folder2").isPhantom());
		// unmap
		RepositoryProvider.unmap(project);
		// ensure that phantoms for the resoucrs no longer exist
		assertFalse(project.getFile("deleted.txt").isPhantom());
		assertFalse(project.getFolder("folder2").isPhantom());
		
		// Create a project
		project = createProject("testUnmap2", new String[] { "changed.txt", "deleted.txt", "folder1/", "folder1/a.txt", "folder1/", "folder1/folder2/deep.txt", "folder2/b.txt" });
		// delete a deep folder to create phantoms
		project.getFolder("folder1/folder2").delete(false, false, null);
		assertTrue(project.getFolder("folder1/folder2").isPhantom());
		// unmap
		RepositoryProvider.unmap(project);
		// ensure that phantoms for the resources no longer exist
		assertFalse(project.getFolder("folder1/folder2").isPhantom());
	}
	
	public void testForBinaryLinefeedCorruption() throws CoreException, TeamException, IOException {
		String EOL = "\n";
		IProject project = createProject("testForBinaryLinefeedCorruption", new String[] { "binaryFile" });
		ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor(project.getFile("binaryFile"));
		assertTrue(ResourceSyncInfo.isBinary(cvsFile.getSyncBytes()));
		setContentsAndEnsureModified(project.getFile("binaryFile"), "line 1" + EOL + "line 2");
		commitProject(project);
		
		// Checkout a copy and ensure the file was not corrupted
		IProject copy = checkoutCopy(project, "-copy");
		assertEquals(project, copy);
	}
	
	public void test33984CannotCommitAfterConflictsMergedLocally() throws CoreException, TeamException, IOException {
			String EOL = System.getProperty("line.separator");
			
			IProject project = createProject("test33984", new String[] { "a.txt", "b.txt" });
			setContentsAndEnsureModified(project.getFile("a.txt"), "line 1");
		    setContentsAndEnsureModified(project.getFile("b.txt"), ("line 1" + EOL + "line 2" + EOL + "line3"));

			Map kMode = new HashMap();
			kMode.put(project.getFile("a.txt"), Command.KSUBST_TEXT);
			kMode.put(project.getFile("b.txt"), Command.KSUBST_TEXT);
			getProvider(project).setKeywordSubstitution(kMode, "", null);
		    
			commitProject(project);
			

		
			// Checkout a copy and ensure the file was not corrupted
			IProject copy = checkoutCopy(project, "-copy");
			assertEquals(project, copy);
			
			// TEST 1: simulate modifying same file by different users
			// b.txt has non-conflicting changes 
			setContentsAndEnsureModified(copy.getFile("b.txt"), ("line 1a" + EOL + "line 2" + EOL + "line3"));
		    
			commitProject(copy);
			
			// user updates which would cause a merge with conflict, a commit should not be allowed
			
			setContentsAndEnsureModified(project.getFile("b.txt"), ("line 1" + EOL + "line 2" + EOL + "line3a"));
			updateProject(project, CVSTag.DEFAULT, false /* don't ignore local changes */);
			commitProject(project);

			// TEST 2: a.txt has conflicting changes
			setContentsAndEnsureModified(copy.getFile("a.txt"), "line 1dfgdfne3");
  
			commitProject(copy);
			
			// user updates which would cause a merge with conflict, a commit should not be allowed
			setContentsAndEnsureModified(project.getFile("a.txt"), "some other text");
			updateProject(project, CVSTag.DEFAULT, false /* don't ignore local changes */);
			try {
				commitProject(project);
				fail("should not be allowed to commit a resource with merged conflicts");
			} catch(TeamException e) {
			}
	}
	
	public void testTagExistsFailure() throws TeamException, CoreException, IOException {
		IProject project = createProject(new String[] { "a.txt", "b.txt" });
		CVSTag tag = new CVSTag("v1", CVSTag.VERSION);
		tagProject(project, tag, false);
		
		setContentsAndEnsureModified(project.getFile("a.txt"));
		commitProject(project);
		
		try {
			tagProject(project, tag, false/* don't force */);
			fail("The tag should have failed since the tag already exists.");
		} catch (TeamException e) {
			// This is what we expected
			assertTrue("This exception should be an error", e.getStatus().getSeverity() == IStatus.ERROR);
		}
		
		tagProject(project, tag, true /* force */);
		IProject copy = checkoutCopy(project, tag);
		assertEquals(project, copy);
	}
	
	public void testUpdateWithOverwrite() throws TeamException, CoreException {
		// Create a project and ad an unmanaged resource
		IProject project = createProject(new String[] { "a.txt", "b.txt" });
		buildResources(project, new String[] { "new.txt" }, false);
		// Checkout a copy and commit the same resource
		IProject copy = checkoutCopy(project, "-copy");
		addResources(copy, new String[] { "new.txt" }, true);
		// Use the regular update and ensure that it fails
		IStatus status = executeCommand(project, Command.UPDATE, Command.NO_LOCAL_OPTIONS);
		assertStatusContainsCode(status, CVSStatus.INVALID_LOCAL_RESOURCE_PATH);
		// Use the update and overwrite and ensure that it works
		status = executeCommand(project, Command.REPLACE, Command.NO_LOCAL_OPTIONS);
		assertTrue(status.isOK());
	}

    private IStatus executeCommand(IProject project, Update update, LocalOption[] options) throws CVSException {
		Session session = new Session(getRepository(), CVSWorkspaceRoot.getCVSFolderFor(project));
		session.open(DEFAULT_MONITOR);
		try {
			return update.execute(
					session,
					Command.NO_GLOBAL_OPTIONS, 
					options, 
					new String[] { "." },
					null,
					DEFAULT_MONITOR);
		} finally {
			session.close();
		}
		
	}
    
    public void testUpdateWithNoChange() throws TeamException, CoreException {
        IProject project = createProject(new String[] { "a.txt"});
        setContentsAndEnsureModified(project.getFile("a.txt"), "contents");
        commitProject(project);
        Date modDate = CVSWorkspaceRoot.getCVSFileFor(project.getFile("a.txt")).getTimeStamp();
        // set the contents to the same value but ensure the local timestamp is different
        setContentsAndEnsureModified(project.getFile("a.txt"), "contents");
        // Update and ensure file tiemstamp is what is was before out edit
        updateProject(project, null, false);
        assertEquals("Timestamp was not properly reset", modDate, CVSWorkspaceRoot.getCVSFileFor(project.getFile("a.txt")).getTimeStamp());
        
    }
}

Back to the top