Skip to main content
summaryrefslogtreecommitdiffstats
blob: f8211234376362c81ed3cc5d255321990c4eab7e (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
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.core.util;


import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.team.internal.ccvs.core.CVSException;
import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
import org.eclipse.team.internal.ccvs.core.CVSTag;
import org.eclipse.team.internal.ccvs.core.Policy;
import org.eclipse.team.internal.ccvs.core.resources.CVSEntryLineTag;
import org.eclipse.team.internal.ccvs.core.syncinfo.BaserevInfo;
import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
import org.eclipse.team.internal.ccvs.core.syncinfo.NotifyInfo;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;

/*
 * This is a helper class that knows the format of the CVS metafiles. It
 * provides a bridge between the CVS metafile formats and location to the
 * Eclipse CVS client ResourceSyncInfo and FolderSyncInfo types.
 */
public class SyncFileWriter {

	// the famous CVS meta directory name
	public static final String CVS_DIRNAME = "CVS"; //$NON-NLS-1$

	// CVS meta files located in the CVS subdirectory
	public static final String REPOSITORY = "Repository"; //$NON-NLS-1$
	public static final String ROOT = "Root"; //$NON-NLS-1$
	public static final String STATIC = "Entries.Static";	 //$NON-NLS-1$
	public static final String TAG = "Tag";	 //$NON-NLS-1$
	public static final String ENTRIES = "Entries"; //$NON-NLS-1$
	//private static final String PERMISSIONS = "Permissions"; //$NON-NLS-1$
	public static final String ENTRIES_LOG="Entries.Log"; //$NON-NLS-1$
	public static final String NOTIFY = "Notify"; //$NON-NLS-1$
	public static final String BASE_DIRNAME = "Base"; //$NON-NLS-1$
	public static final String BASEREV = "Baserev"; //$NON-NLS-1$
	
	// the local workspace file that contains pattern for ignored resources
	public static final String IGNORE_FILE = ".cvsignore"; //$NON-NLS-1$

	// Some older CVS clients may of added a line to the entries file consisting
	// of only a 'D'. It is safe to ingnore these entries.	
	private static final String FOLDER_TAG="D"; //$NON-NLS-1$
	
	// Command characters found in the Entries.log file
	private static final String ADD_TAG="A "; //$NON-NLS-1$
	private static final String REMOVE_TAG="R "; //$NON-NLS-1$	
	
	// key for saving the mod stamp for each writen meta file
	public static final QualifiedName MODSTAMP_KEY = new QualifiedName("org.eclipse.team.cvs.core", "meta-file-modtime"); //$NON-NLS-1$ //$NON-NLS-2$
	
	/**
	 * Reads the CVS/Entries, CVS/Entries.log and CVS/Permissions files from the
	 * specified folder and returns ResourceSyncInfo instances for the data stored therein.
	 * If the folder does not have a CVS subdirectory then <code>null</code> is returned.
	 */
	public static byte[][] readAllResourceSync(IContainer parent) throws CVSException {
		IFolder cvsSubDir = getCVSSubdirectory(parent);
		if (! cvsSubDir.exists()) return null;
		
		if (Policy.DEBUG_METAFILE_CHANGES) {
			System.out.println("Reading Entries file for " + parent.getFullPath()); //$NON-NLS-1$
		}

		// process Entries file contents
		String[] entries = readLines(cvsSubDir.getFile(ENTRIES));
		if (entries == null) return null;
		Map infos = new TreeMap();
		for (int i = 0; i < entries.length; i++) {
			String line = entries[i];
			if(!FOLDER_TAG.equals(line) && !"".equals(line)) { //$NON-NLS-1$
				ResourceSyncInfo info = new ResourceSyncInfo(line, null, null);
				infos.put(info.getName(), info);			
			}
		}
		
		// process Entries.log file contents
		String[] entriesLog = readLines(cvsSubDir.getFile(ENTRIES_LOG));
		if (entriesLog != null) {
			for (int i = 0; i < entriesLog.length; i++) {
				String line = entriesLog[i];
				if (line.startsWith(ADD_TAG)) {
					line = line.substring(ADD_TAG.length());
					ResourceSyncInfo info = new ResourceSyncInfo(line, null, null);
					infos.put(info.getName(), info);
				} else if (line.startsWith(REMOVE_TAG)) {
					line = line.substring(REMOVE_TAG.length());
					ResourceSyncInfo info = new ResourceSyncInfo(line, null, null);
					infos.remove(info.getName());
				}
			}
		}
		
		//return (ResourceSyncInfo[])infos.values().toArray(new ResourceSyncInfo[infos.size()]);
		byte[][] result = new byte[infos.size()][];
		int i = 0;
		for (Iterator iter = infos.values().iterator(); iter.hasNext();) {
			ResourceSyncInfo info = (ResourceSyncInfo) iter.next();
			result[i++] = info.getBytes();
		}
		return result;
	}
	
	public static void writeAllResourceSync(IContainer parent, byte[][] infos) throws CVSException {
		try {
			if (Policy.DEBUG_METAFILE_CHANGES) {
				System.out.println("Writing Entries file for folder " + parent.getFullPath()); //$NON-NLS-1$
			}
			IFolder cvsSubDir = createCVSSubdirectory(parent);

			// format file contents
			String[] entries = new String[infos.length];
			for (int i = 0; i < infos.length; i++) {
				byte[] info = infos[i];
				entries[i] = new String(info);
			}

			// write Entries
			writeLines(cvsSubDir.getFile(ENTRIES), entries);

			// delete Entries.log
			cvsSubDir.getFile(ENTRIES_LOG).delete(IResource.NONE, null);
		} catch(CoreException e) {
			throw CVSException.wrapException(e);
		}
	}
	/**
	 * Reads the CVS/Root, CVS/Repository, CVS/Tag, and CVS/Entries.static files from
	 * the specified folder and returns a FolderSyncInfo instance for the data stored therein.
	 * If the folder does not have a CVS subdirectory then <code>null</code> is returned.
	 */
	public static FolderSyncInfo readFolderSync(IContainer folder) throws CVSException {
		IFolder cvsSubDir = getCVSSubdirectory(folder);
		if (! cvsSubDir.exists()) return null;

		if (Policy.DEBUG_METAFILE_CHANGES) {
			System.out.println("Reading Root/Repository files for " + folder.getFullPath()); //$NON-NLS-1$
		}
		
		// check to make sure the the cvs folder is hidden
		if (!cvsSubDir.isTeamPrivateMember()) {
			try {
				cvsSubDir.setTeamPrivateMember(true);
			} catch (CoreException e) {
				CVSProviderPlugin.log(e);
			}
		}
				
		// read CVS/Root
		String root = readFirstLine(cvsSubDir.getFile(ROOT));
		if (root == null) return null;
		
		// read CVS/Repository
		String repository = readFirstLine(cvsSubDir.getFile(REPOSITORY));
		if (repository == null) return null;
		
		// read CVS/Tag
		String tag = readFirstLine(cvsSubDir.getFile(TAG));
		if (Policy.DEBUG_METAFILE_CHANGES && tag != null) {
			System.out.println("Reading Tag file for " + folder.getFullPath()); //$NON-NLS-1$
		}
		CVSTag cvsTag = (tag != null) ? new CVSEntryLineTag(tag) : null;

		// read Entries.Static
		String staticDir = readFirstLine(cvsSubDir.getFile(STATIC));
		if (Policy.DEBUG_METAFILE_CHANGES && staticDir != null) {
			System.out.println("Reading Static file for " + folder.getFullPath()); //$NON-NLS-1$
		}
		boolean isStatic = (staticDir != null);
		
		// return folder sync
		return new FolderSyncInfo(repository, root, cvsTag, isStatic);		
	}
	
	/**
	 * Writes the CVS/Root, CVS/Repository, CVS/Tag, and CVS/Entries.static files to the
	 * specified folder using the data contained in the specified FolderSyncInfo instance.
	 */
	public static void writeFolderSync(IContainer folder, FolderSyncInfo info) throws CVSException {
		try {
			if (Policy.DEBUG_METAFILE_CHANGES) {
				System.out.println("Writing Root/Respository files for " + folder.getFullPath()); //$NON-NLS-1$
			}
			IFolder cvsSubDir = createCVSSubdirectory(folder);
	
			// write CVS/Root
			writeLines(cvsSubDir.getFile(ROOT), new String[] {info.getRoot()});
			
			// write CVS/Repository
			writeLines(cvsSubDir.getFile(REPOSITORY), new String[] {info.getRepository()});
			
			// write CVS/Tag
			IFile tagFile = cvsSubDir.getFile(TAG);
			if (info.getTag() != null) {
				if (Policy.DEBUG_METAFILE_CHANGES) {
					System.out.println("Writing Tag file for " + folder.getFullPath()); //$NON-NLS-1$
				}
				writeLines(tagFile, new String[] {info.getTag().toEntryLineFormat(false)});
			} else {
				if(tagFile.exists()) {
					if (Policy.DEBUG_METAFILE_CHANGES) {
						System.out.println("Deleting Tag file for " + folder.getFullPath()); //$NON-NLS-1$
					}
					tagFile.delete(IResource.NONE, null);
				}
			}
			
			// write CVS/Entries.Static
			IFile staticFile = cvsSubDir.getFile(STATIC);
			if(info.getIsStatic()) {
				// the existance of the file is all that matters
				if (Policy.DEBUG_METAFILE_CHANGES) {
					System.out.println("Writing Static file for " + folder.getFullPath()); //$NON-NLS-1$
				}
				writeLines(staticFile, new String[] {""}); //$NON-NLS-1$
			} else {
				if(staticFile.exists()) {
					if (Policy.DEBUG_METAFILE_CHANGES) {
						System.out.println("Deleting Static file for " + folder.getFullPath()); //$NON-NLS-1$
					}
					staticFile.delete(IResource.NONE, null);
				}
			}
		} catch(CoreException e) {
			throw CVSException.wrapException(e);
		}
	}

	/**
	 * Returns all .cvsignore entries for the specified folder.
	 */
	public static String[] readCVSIgnoreEntries(IContainer folder) throws CVSException {
		IFile ignoreFile = folder.getFile(new Path(IGNORE_FILE));
		if (ignoreFile != null) {
			return readLines(ignoreFile);
		}
		return null;
	}
	
	/**
	 * Writes all entries to the specified folder's .cvsignore file, overwriting any
	 * previous edition of the file.
	 */
	public static void writeCVSIgnoreEntries(IContainer folder, String[] patterns) throws CVSException {
		IFile ignoreFile = folder.getFile(new Path(IGNORE_FILE));
		writeLines(ignoreFile, patterns);
	}	

	/**
	 * Delete folder sync is equilavent to removing the CVS subdir.
	 */
	public static void deleteFolderSync(IContainer folder) throws CVSException {		
		try {
			if (Policy.DEBUG_METAFILE_CHANGES) {
				System.out.println("Deleting CVS directory from " + folder.getFullPath()); //$NON-NLS-1$
			}
			getCVSSubdirectory(folder).delete(IResource.NONE, null);
		} catch(CoreException e) {
			throw CVSException.wrapException(e);
		}
	}

	/**
	 * Reads the CVS/Notify file from the specified folder and returns NotifyInfo instances 
	 * for the data stored therein. If the folder does not have a CVS subdirectory then <code>null</code> is returned.
	 */
	public static NotifyInfo[] readAllNotifyInfo(IContainer parent) throws CVSException {
		IFolder cvsSubDir = getCVSSubdirectory(parent);
		if (! cvsSubDir.exists()) return null;

		// process Notify file contents
		String[] entries = readLines(cvsSubDir.getFile(NOTIFY));
		if (entries == null) return null;
		Map infos = new TreeMap();
		for (int i = 0; i < entries.length; i++) {
			String line = entries[i];
			if(!"".equals(line)) { //$NON-NLS-1$
				NotifyInfo info = new NotifyInfo(parent, line);
				infos.put(info.getName(), info);			
			}
		}
		
		return (NotifyInfo[])infos.values().toArray(new NotifyInfo[infos.size()]);
	}
	
	/**
	 * Writes the CVS/Notify file to the specified folder using the data contained in the 
	 * specified NotifyInfo instances. A CVS subdirectory must already exist (an exception 
	 * is thrown if it doesn't).
	 */
	public static void writeAllNotifyInfo(IContainer parent, NotifyInfo[] infos) throws CVSException {
		// get the CVS directory
		IFolder cvsSubDir = getCVSSubdirectory(parent);
		// write lines will throw an exception if the CVS directoru does not exist
		
		if (infos.length == 0) {
			// if there are no notify entries, delete the notify file
			try {
				IFile notifyFile = cvsSubDir.getFile(NOTIFY);
				if(notifyFile.exists()) {
					notifyFile.delete(IResource.NONE, null);
				}
			} catch (CoreException e) {
				throw CVSException.wrapException(e);
			}
		} else {
			// format file contents
			String[] entries = new String[infos.length];
			for (int i = 0; i < infos.length; i++) {
				NotifyInfo info = infos[i];
				entries[i] = info.getNotifyLine();
			}
	
			// write Notify entries
			writeLines(cvsSubDir.getFile(NOTIFY), entries);
		}
	}

	/**
	 * Reads the CVS/Baserev file from the specified folder and returns
	 * BaserevInfo instances for the data stored therein. If the folder does not
	 * have a CVS subdirectory then <code>null</code> is returned.
	 */
	public static BaserevInfo[] readAllBaserevInfo(IContainer parent) throws CVSException {
		IFolder cvsSubDir = getCVSSubdirectory(parent);
		if (! cvsSubDir.exists()) return null;

		// process Notify file contents
		String[] entries = readLines(cvsSubDir.getFile(BASEREV));
		if (entries == null) return null;
		Map infos = new TreeMap();
		for (int i = 0; i < entries.length; i++) {
			String line = entries[i];
			if(!"".equals(line)) { //$NON-NLS-1$
				BaserevInfo info = new BaserevInfo(line);
				infos.put(info.getName(), info);
			}
		}

		return (BaserevInfo[])infos.values().toArray(new BaserevInfo[infos.size()]);
	}

	/**
	 * Writes the CVS/Baserev file to the specified folder using the data
	 * contained in the specified BaserevInfo instances. A CVS subdirectory must
	 * already exist (an exception is thrown if it doesn't).
	 */
	public static void writeAllBaserevInfo(IContainer parent, BaserevInfo[] infos) throws CVSException {
		// get the CVS directory
		IFolder cvsSubDir = getCVSSubdirectory(parent);
		// write lines will throw an exception if the CVS directory does not exist

		// format file contents
		String[] entries = new String[infos.length];
		for (int i = 0; i < infos.length; i++) {
			BaserevInfo info = infos[i];
			entries[i] = info.getEntryLine();
		}

		// write Notify entries
		writeLines(cvsSubDir.getFile(BASEREV), entries);
	}
				
	/**
	 * Returns the CVS subdirectory for this folder.
	 */
	private static IFolder getCVSSubdirectory(IContainer folder) throws CVSException {
		return folder.getFolder(new Path(CVS_DIRNAME));
	}
	
	/**
	 * Creates and makes team-private and returns a CVS subdirectory in this folder.
	 */
	private static IFolder createCVSSubdirectory(IContainer folder) throws CVSException {
		try {
			final IFolder cvsSubDir = getCVSSubdirectory(folder);
			if (! cvsSubDir.exists()) {
				// important to have both the folder creation and setting of team-private in the
				// same runnable so that the team-private flag is set before other delta listeners 
				// sees the CVS folder creation.
				ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
					public void run(IProgressMonitor monitor) throws CoreException {
						cvsSubDir.create(false /*don't force*/, true /*make local*/, null);
						cvsSubDir.setTeamPrivateMember(true);
					} 
				}, folder, 0, null);
			}
			return cvsSubDir;
		} catch (CoreException e) {
			throw CVSException.wrapException(e);
		}
	}

	/*
	 * Reads the first line of the specified file.
	 * Returns null if the file does not exist, or the empty string if it is blank.
	 */
	private static String readFirstLine(IFile file) throws CVSException {
		if (! file.exists()) return null;
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(file.getContents()));
			try {
				String line = reader.readLine();
				if (line == null) return ""; //$NON-NLS-1$
				return line;
			} finally {
				reader.close();
			}
		} catch (IOException e) {
			throw CVSException.wrapException(e);
		} catch (CoreException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	/*
	 * Reads all lines of the specified file.
	 * Returns null if the file does not exist.
	 */
	private static String[] readLines(IFile file) throws CVSException {
		try {
			if(! file.exists()) return null;
			// Peform a forced read (ignoring out-of-sync)
			BufferedReader reader = new BufferedReader(new InputStreamReader(file.getContents(true)));
			List fileContentStore = new ArrayList();
			try {
				String line;
				while ((line = reader.readLine()) != null) {
					fileContentStore.add(line);
				}
				return (String[]) fileContentStore.toArray(new String[fileContentStore.size()]);
			} finally {
				reader.close();
			}
		} catch (IOException e) {
			throw CVSException.wrapException(e);
		} catch (CoreException e) {
			// If the IFile doesn't exist or the underlying File doesn't exist,
			// just return null to indicate the absence of the file
			if (e.getStatus().getCode() == IResourceStatus.RESOURCE_NOT_FOUND
					|| e.getStatus().getCode() == IResourceStatus.FAILED_READ_LOCAL)
				return null;
			throw CVSException.wrapException(e);
		}
	}
	
	/*
	 * Reads all lines of the specified file.
	 * Returns null if the file does not exist.
	 */
	public static byte[][] readLines(InputStream stream) throws CVSException {
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
			List fileContentStore = new ArrayList();
			try {
				String line;
				while ((line = reader.readLine()) != null) {
					fileContentStore.add(line.getBytes());
				}
				return (byte[][]) fileContentStore.toArray(new byte[fileContentStore.size()][]);
			} finally {
				reader.close();
			}
		} catch (IOException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	/*
	 * Writes all lines to the specified file, using linefeed terminators for
	 * compatibility with other CVS clients.
	 */
	private static void writeLines(final IFile file, final String[] contents) throws CVSException {
		try {
			// The creation of sync files has to be in a runnable in order for the resulting delta
			// to include the MODSTAMP value. If not in a runnable then create/setContents
			// will trigger a delta and the SyncFileWriter change listener won't know that the delta
			// was a result of our own creation.
			ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
				public void run(IProgressMonitor monitor) throws CoreException {
					try {
						ByteArrayOutputStream os = new ByteArrayOutputStream();
						writeLinesToStreamAndClose(os, contents);
						if(!file.exists()) {
							file.create(new ByteArrayInputStream(os.toByteArray()), IResource.NONE /*don't keep history and don't force*/, null);
						} else {
							file.setContents(new ByteArrayInputStream(os.toByteArray()), IResource.NONE /*don't keep history and don't force*/, null);
						}			
						file.setSessionProperty(MODSTAMP_KEY, new Long(file.getModificationStamp()));
					} catch(CVSException e) {
						throw new CoreException(e.getStatus());
					}
				}
			}, file, 0, null);
		} catch (CoreException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	private static void writeLinesToStreamAndClose(OutputStream os, String[] contents) throws CVSException {
		try {
			try {
				for (int i = 0; i < contents.length; i++) {
					os.write(contents[i].getBytes());
					os.write(0x0A); // newline byte
				}
			} finally {
				os.close();
			}
		} catch (IOException e) {
			throw CVSException.wrapException(e);
		}
	}
	
	/**
	 * Method writeFileToBaseDirectory.
	 * 
	 * @param file
	 * @param info
	 */
	public static void writeFileToBaseDirectory(IFile file, IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, 100);
		try {
			IFolder baseFolder = getBaseDirectory(file);
			if (!baseFolder.exists()) {
				baseFolder.create(false /* force */, true /* local */, Policy.subMonitorFor(monitor, 10));
			}
			IFile target = baseFolder.getFile(new Path(file.getName()));
			if (target.exists()) {
				// XXX Should ensure that we haven't already copied it
				// XXX write the revision to the CVS/Baserev file
				target.delete(true, Policy.subMonitorFor(monitor, 10));
			}
			// Copy the file so the timestamp is maintained
			file.copy(target.getFullPath(), true /* force */, Policy.subMonitorFor(monitor, 80));
		} catch (CoreException e) {
			throw CVSException.wrapException(e);
		} finally {
			monitor.done();
		}
	}
	/**
	 * Method restoreFileFromBaseDirectory.
	 * @param file
	 * @param info
	 * @param monitor
	 */
	public static void restoreFileFromBaseDirectory(IFile file, IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, 100);
		try {
			IFolder baseFolder = getBaseDirectory(file);
			IFile source = baseFolder.getFile(new Path(file.getName()));
			if (!source.exists()) {
				throw new CVSException(Policy.bind("SyncFileWriter.baseNotAvailable", file.getFullPath().toString())); //$NON-NLS-1$
			}
			if (file.exists()) {
				file.delete(false /* force */, true /* keep history */, Policy.subMonitorFor(monitor, 10));
			}
			// Copy the file so the timestamp is maintained
			source.move(file.getFullPath(), false /* force */, true /* keep history */,Policy.subMonitorFor(monitor, 100));
		} catch (CoreException e) {
			throw CVSException.wrapException(e);
		} finally {
			monitor.done();
		}
	}
	
	/**
	 * Method deleteFileFromBaseDirectory.
	 * @param file
	 * @param monitor
	 */
	public static void deleteFileFromBaseDirectory(IFile file, IProgressMonitor monitor) throws CVSException {
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(null, 100);
		try {
			IFolder baseFolder = getBaseDirectory(file);
			IFile source = baseFolder.getFile(new Path(file.getName()));
			if (source.exists()) {
				source.delete(false, false, Policy.subMonitorFor(monitor, 100));
			}
		} catch (CoreException e) {
			throw CVSException.wrapException(e);
		} finally {
			monitor.done();
		}
	}

	private static IFolder getBaseDirectory(IFile file) throws CVSException {
		IContainer cvsFolder = getCVSSubdirectory(file.getParent());
		IFolder baseFolder = cvsFolder.getFolder(new Path(BASE_DIRNAME));
		return baseFolder;
	}
	
	/**
	 * Return a handle to the CVS/Template file for the given folder
	 * @param folder
	 * @return IFile
	 * @throws CVSException
	 */
	public static IFile getTemplateFile(IContainer folder) throws CVSException {
		IFolder cvsFolder = createCVSSubdirectory(folder);
		return cvsFolder.getFile("Template"); //$NON-NLS-1$
	}
	
	/**
	 * Method isEdited.
	 * @param resource
	 * @return boolean
	 */
	public static boolean isEdited(IFile file) throws CVSException {
		IFolder baseFolder = getBaseDirectory(file);
		IFile baseFile = baseFolder.getFile(file.getName());
		return baseFile.exists();
	}

}

Back to the top