diff options
author | Jean Michel-Lemieux | 2002-03-01 23:27:06 +0000 |
---|---|---|
committer | Jean Michel-Lemieux | 2002-03-01 23:27:06 +0000 |
commit | 840f9c23941d1817e969e9012be889a31e4b1cf7 (patch) | |
tree | 65cd115fffe4173b73ab57523ad0018993a1eeeb | |
parent | 402b4f5ee148505e76f959cdbed7d4d7ef989a98 (diff) | |
download | eclipse.platform.team-840f9c23941d1817e969e9012be889a31e4b1cf7.tar.gz eclipse.platform.team-840f9c23941d1817e969e9012be889a31e4b1cf7.tar.xz eclipse.platform.team-840f9c23941d1817e969e9012be889a31e4b1cf7.zip |
refactoring in progress...
9 files changed, 462 insertions, 594 deletions
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java index 6ad6f9875..799fe565e 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/CVSProviderPlugin.java @@ -18,14 +18,10 @@ import org.eclipse.core.runtime.Plugin; import org.eclipse.team.core.ITeamProvider; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.TeamPlugin; -import org.eclipse.team.core.sync.ISyncProvider; import org.eclipse.team.internal.ccvs.core.CVSException; import org.eclipse.team.internal.ccvs.core.CVSProvider; import org.eclipse.team.internal.ccvs.core.Policy; import org.eclipse.team.internal.ccvs.core.client.Command.QuietOption; -import org.eclipse.team.internal.ccvs.core.resources.*; -import org.eclipse.team.internal.ccvs.core.syncinfo.*; -import org.eclipse.team.internal.ccvs.core.syncinfo.FileSystemSynchronizer; import org.eclipse.team.internal.ccvs.core.util.OrphanedFolderListener; import org.eclipse.team.internal.ccvs.core.util.ProjectDescriptionManager; import org.eclipse.team.internal.ccvs.core.util.Util; diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSFile.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSFile.java index 20ad63336..ba90eda1b 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSFile.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/ICVSFile.java @@ -37,6 +37,12 @@ public interface ICVSFile extends ICVSResource { * It is the responsibility of the caller to close the stream when finished. */ OutputStream getOutputStream() throws CVSException; + + /** + * Gets an appending output stream for writing to the file. + * It is the responsibility of the caller to close the stream when finished. + */ + OutputStream getAppendingOutputStream() throws CVSException; /** * Sets the file's read-only permission. diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java index 3dfcdf2e3..515abf2ec 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java @@ -72,6 +72,27 @@ class EclipseFile extends EclipseResource implements ICVSFile { } /* + * @see ICVSFile#getAppendingOutputStream() + */ + public OutputStream getAppendingOutputStream() throws CVSException { + return new ByteArrayOutputStream() { + public void close() throws IOException { + try { + IFile file = getIFile(); + if(resource.exists()) { + file.appendContents(new ByteArrayInputStream(toByteArray()), true /*force*/, true /*keep history*/, null); + } else { + file.create(new ByteArrayInputStream(toByteArray()), true /*force*/, null); + } + super.close(); + } catch(CoreException e) { + throw new IOException("Error setting file contents: " + e.getMessage()); + } + } + }; + } + + /* * @see ICVSFile#getTimeStamp() */ public String getTimeStamp() { @@ -180,5 +201,5 @@ class EclipseFile extends EclipseResource implements ICVSFile { */ private IFile getIFile() { return (IFile)resource; - } + } }
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseSynchronizer.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseSynchronizer.java index af1451a5f..56af1502c 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseSynchronizer.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseSynchronizer.java @@ -17,7 +17,6 @@ import java.util.List; import java.util.Set; import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ISynchronizer; import org.eclipse.core.resources.ResourcesPlugin; @@ -28,15 +27,26 @@ import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.team.ccvs.core.CVSProviderPlugin; import org.eclipse.team.ccvs.core.CVSTag; +import org.eclipse.team.ccvs.core.ICVSFolder; +import org.eclipse.team.ccvs.core.ICVSResource; import org.eclipse.team.core.TeamPlugin; import org.eclipse.team.internal.ccvs.core.CVSException; import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo; import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo; +import org.eclipse.team.internal.ccvs.core.util.SyncFileWriter; /** * A synchronizer is responsible for managing synchronization information for local * CVS resources. * + * [Notes: + * 1. how can we expire cache elements and purge to safe memory? + * 2. how can we safeguard against overwritting meta files changes made outside of Eclipse? I'm + * not sure we should force setting file contents in EclipseFile handles? + * 3. how can we group operations? + * 4. how do we reload + * ] + * * @see ResourceSyncInfo * @see FolderSyncInfo */ @@ -53,6 +63,13 @@ public class EclipseSynchronizer { getSynchronizer().add(FOLDER_SYNC_KEY); } + public static EclipseSynchronizer getInstance() { + if (instance == null) { + instance = new EclipseSynchronizer(); + } + return instance; + } + /** * Associates the provided folder sync information with the given folder. The folder * must exist on the file system. @@ -84,8 +101,12 @@ public class EclipseSynchronizer { beginOperation(); FolderSyncInfo info = getCachedFolderSync(folder); if (info == null) { - info = readFolderConfig(folder); - setCachedFolderSync(folder, info); + info = SyncFileWriter.readFolderConfig(CVSWorkspaceRoot.getCVSFolderFor(folder)); + if(info!=null) { + setCachedFolderSync(folder, info); + // read the child meta-files also + getMetaResourceSyncForFolder(folder, null); + } } endOperation(); return info; @@ -124,35 +145,13 @@ public class EclipseSynchronizer { if(resource.getType()==IResource.ROOT) return null; beginOperation(); ResourceSyncInfo info = getCachedResourceSync(resource); - if (info == null) { - IContainer parent = resource.getParent(); - if (parent != null) { - ResourceSyncInfo[] infos = readEntriesFile(resource.getParent()); - if (infos != null) { - for (int i = 0; i < infos.length; i++) { - ResourceSyncInfo syncInfo = infos[i]; - IResource peer; - if (resource.getName().equals(syncInfo.getName())) { - info = syncInfo; - peer = resource; - } else { - IPath path = new Path(syncInfo.getName()); - if (syncInfo.isDirectory()) { - peer = parent.getFolder(path); - } else { - peer = parent.getFile(path); - } - } - // may create a phantom if the sibling resource does not exist. - setCachedResourceSync(peer, syncInfo); - } - } - } + if(info==null) { + info = getMetaResourceSyncForFolder(resource.getParent(), resource); } endOperation(); return info; } - + /** * Removes the folder's and all children's folder sync information. This will essentially remove * all CVS knowledge from these resources. @@ -178,7 +177,6 @@ public class EclipseSynchronizer { * Answers if the following resource is ignored */ public boolean isIgnored(IResource resource) { - // FIX ME! return false; } @@ -186,7 +184,6 @@ public class EclipseSynchronizer { * Adds a pattern or file name to be ignored in the current files directory. */ public void setIgnored(IResource resource, String pattern) throws CVSException { - // FIX ME! } /** @@ -201,11 +198,16 @@ public class EclipseSynchronizer { */ public IResource[] members(IContainer folder) throws CVSException { try { + // initialize cache if needed, this will create phantoms + FolderSyncInfo info = getCachedFolderSync(folder); + if(info==null) { + getMetaResourceSyncForFolder(folder, null); + } IResource[] children = folder.members(true); List list = new ArrayList(children.length); for (int i = 0; i < children.length; ++i) { IResource child = children[i]; - if (! child.isPhantom() || getCachedResourceSync(child) != null) { + if (!child.isPhantom() || getCachedResourceSync(child) != null) { list.add(child); } } @@ -229,20 +231,22 @@ public class EclipseSynchronizer { while (it.hasNext()) { IContainer folder = (IContainer) it.next(); FolderSyncInfo info = getCachedFolderSync(folder); + ICVSFolder cvsFolder = CVSWorkspaceRoot.getCVSFolderFor(folder); if (info != null) { - writeFolderConfig(folder, info); + SyncFileWriter.writeFolderConfig(cvsFolder, info); } else { - deleteFolderConfig(folder); + SyncFileWriter.deleteFolderSync(cvsFolder); } } it = changedResources.iterator(); while (it.hasNext()) { IResource resource = (IResource) it.next(); ResourceSyncInfo info = getCachedResourceSync(resource); + ICVSResource cvsResource = CVSWorkspaceRoot.getCVSResourceFor(resource); if (info != null) { - writeResourceSync(resource, info); + SyncFileWriter.writeResourceSync(cvsResource, info); } else { - deleteResourceSync(resource); + SyncFileWriter.deleteSync(cvsResource); } } @@ -257,7 +261,7 @@ public class EclipseSynchronizer { } } - private ISynchronizer getSynchronizer() { + private static ISynchronizer getSynchronizer() { return ResourcesPlugin.getWorkspace().getSynchronizer(); } @@ -332,58 +336,36 @@ public class EclipseSynchronizer { } catch(IOException e) { throw CVSException.wrapException(e); } - } - - private FolderSyncInfo readFolderConfig(IContainer folder) throws CVSException { - //return SyncFileUtil.readFolderConfig(folder.getLocation().toFile()); - return null; - } - - private void writeFolderConfig(IContainer folder, FolderSyncInfo info) throws CVSException { - /* - SyncFileUtil.writeFolderConfig(folder.getLocation().toFile(), info); - try { - folder.refreshLocal(IResource.DEPTH_INFINITE, null); - } catch (CoreException e) { - throw CVSException.wrapException(e); - } - */ - } - - private void deleteFolderConfig(IContainer folder) throws CVSException { - //SyncFileUtil.deleteSync(folder.getLocation().toFile()); - } - - private ResourceSyncInfo[] readEntriesFile(IContainer folder) throws CVSException { - //return SyncFileUtil.readEntriesFile(folder.getLocation().toFile()); - return null; - } - - private void writeResourceSync(IResource resource, ResourceSyncInfo info) throws CVSException { - /* - SyncFileUtil.writeResourceSync(resource.getLocation().toFile(), info); - try { - resource.getParent().refreshLocal(IResource.DEPTH_INFINITE, null); - } catch (CoreException e) { - throw CVSException.wrapException(e); - }*/ - } - - private void deleteResourceSync(IResource resource) throws CVSException { - /* - SyncFileUtil.deleteSync(resource.getLocation().toFile()); - try { - resource.getParent().refreshLocal(IResource.DEPTH_INFINITE, null); - } catch (CoreException e) { - throw CVSException.wrapException(e); - } - */ - } + } - public static EclipseSynchronizer getInstance() { - if (instance == null) { - instance = new EclipseSynchronizer(); + /* + * Reads and caches the ResourceSyncInfos for this folder. If target is non-null, then + * returns the ResourceSync for this resource is it is found. + */ + private ResourceSyncInfo getMetaResourceSyncForFolder(IContainer folder, IResource target) throws CVSException { + ResourceSyncInfo info = null; + if (folder!=null) { + ResourceSyncInfo[] infos = SyncFileWriter.readEntriesFile(CVSWorkspaceRoot.getCVSFolderFor(folder)); + if (infos != null) { + for (int i = 0; i < infos.length; i++) { + ResourceSyncInfo syncInfo = infos[i]; + IResource peer; + if (target!=null && target.getName().equals(syncInfo.getName())) { + info = syncInfo; + peer = target; + } else { + IPath path = new Path(syncInfo.getName()); + if (syncInfo.isDirectory()) { + peer = folder.getFolder(path); + } else { + peer = folder.getFile(path); + } + } + // may create a phantom if the sibling resource does not exist. + setCachedResourceSync(peer, syncInfo); + } + } } - return instance; + return info; } }
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java index 869f6fc75..6ac193ef2 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/RemoteFile.java @@ -395,4 +395,11 @@ public class RemoteFile extends RemoteResource implements ICVSRemoteFile, ICVSFi RemoteFile remote = (RemoteFile) target; return super.equals(target) && remote.getRevision().equals(getRevision()); } + + /* + * @see ICVSFile#getAppendingOutputStream() + */ + public OutputStream getAppendingOutputStream() throws CVSException { + return null; + } }
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/FileSystemSynchronizer.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/FileSystemSynchronizer.java deleted file mode 100644 index a23245581..000000000 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/FileSystemSynchronizer.java +++ /dev/null @@ -1,429 +0,0 @@ -package org.eclipse.team.internal.ccvs.core.syncinfo; - -/* - * (c) Copyright IBM Corp. 2000, 2001. - * All Rights Reserved. - */ - -import java.io.File; -import java.util.HashSet; -import java.util.Set; - -import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceVisitor; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.core.runtime.Path; -import org.eclipse.team.core.TeamPlugin; -import org.eclipse.team.internal.ccvs.core.CVSException; -import org.eclipse.team.internal.ccvs.core.Policy; -import org.eclipse.team.internal.ccvs.core.resources.ICVSSynchronizer; -import org.eclipse.team.internal.ccvs.core.util.Assert; -import org.eclipse.team.internal.ccvs.core.util.FileNameMatcher; -import org.eclipse.team.internal.ccvs.core.util.FileUtil; -import org.eclipse.team.internal.ccvs.core.util.ResourceDeltaVisitor; -import org.eclipse.team.internal.ccvs.core.util.SyncFileUtil; - -/** - * The FileSystemSynchronizer stores sync information to be compatible with CVS command line - * clients. It is also responsible for synchronizing the workbench when changes are made to CVS - * metafiles (CVS/Entries, CVS/Root..) from outside of the workbench by 3rd party tools. - * - * @see ICVSSynchronizer - */ -public class FileSystemSynchronizer implements ICVSSynchronizer { - - // caches for resource and folder sync. These are required to provide timely access to - // sync information that may be shown in the UI. - private ICache resourceSyncCache; - private ICache folderSyncCache; - private ICache cvsIgnoreCache; - - // a specialized resource listener required to interpret metafile changes made to CVS managed - // resources. - private SyncResourceChangeListener resourceListener; - - // time in minutes that a cached sync object should remain in the cache. A time of 0 indicates - // that the cache object will never expire. - private final static int CACHE_EXPIRATION_MINUTES = 0; - - /** - * Initialize the caches and register as a resource listener. - */ - public FileSystemSynchronizer() { - resourceSyncCache = new SimpleCache(); - resourceSyncCache.registerLoader(new ResourceSyncCacheLoader()); - - folderSyncCache = new SimpleCache(); - folderSyncCache.registerLoader(new FolderSyncCacheLoader()); - - cvsIgnoreCache = new SimpleCache(); - cvsIgnoreCache.registerLoader(new CVSIgnoreFileLoader()); - - resourceListener = new SyncResourceChangeListener(); - resourceListener.register(); - } - - /** - * For every get request from the cache, load the entire entries and permissions file. - */ - private class ResourceSyncCacheLoader implements ICacheLoader { - /* - * @see ICacheLoader#load(Object, ICache) - */ - public CacheData load(Object id, ICache cache) { - CacheData idInfo = null; - try { - File file = (File)id; - File parent = file.getParentFile(); - - ResourceSyncInfo infos[] = SyncFileUtil.readEntriesFile(parent); - // if null then, entries file does not exist - if(infos!=null) { - for (int i = 0; i < infos.length; i++) { - ResourceSyncInfo info = infos[i]; - CacheData cacheInfo = new CacheData(new File(parent, info.getName()), info, CACHE_EXPIRATION_MINUTES); - if(file.getName().equals(info.getName())) { - idInfo = cacheInfo; - } else { - cache.put(cacheInfo); - } - } - } - } catch(CVSException e) { - TeamPlugin.log(IStatus.ERROR, Policy.bind("FileSystemSynchronizer_Error_loading_from_CVS/Entries_file_1"), e); //$NON-NLS-1$ - return null; - } - return idInfo; - } - } - - /** - * For every get request from the cache, load the .cvsignore file - */ - private class CVSIgnoreFileLoader implements ICacheLoader { - /* - * @see ICacheLoader#load(Object, ICache) - */ - public CacheData load(Object id, ICache cache) { - CacheData idInfo = null; - try { - File file = (File)id; - File cvsignore = new File(file, SyncFileUtil.IGNORE_FILE); - String[] patterns = SyncFileUtil.readLines(cvsignore); - if(patterns.length>0) { - idInfo = new CacheData(file, patterns, CACHE_EXPIRATION_MINUTES); - cache.put(idInfo); - } - } catch(CVSException e) { - TeamPlugin.log(IStatus.ERROR, Policy.bind("FileSystemSynchronizer_Error_loading_from_.cvsignore_file_2"), e); //$NON-NLS-1$ - return null; - } - return idInfo; - } - } - - /** - * For every get request from the cache that fails, load the files that contain the folder sync info. - */ - private class FolderSyncCacheLoader implements ICacheLoader { - /* - * @see ICacheLoader#load(Object, ICache) - */ - public CacheData load(Object id, ICache cache) { - try { - File folder = (File)id; - FolderSyncInfo info = SyncFileUtil.readFolderConfig(folder); - - // no CVS sub-directory - if(info==null) { - return null; - } else { - return new CacheData(folder, info, CACHE_EXPIRATION_MINUTES); - } - } catch(CVSException e) { - TeamPlugin.log(IStatus.ERROR, Policy.bind("FileSystemSynchronizer_Error_loading_from_CVS/Root,Repository_files_3"), e); //$NON-NLS-1$ - return null; - } - } - } - - /** - * Handle changes made to meta files. - * 1. - */ - private class SyncResourceChangeListener extends ResourceDeltaVisitor { - final private Set delta = new HashSet(); - - protected void handleAdded(IResource[] resources) { - handleDefault(resources); - } - - protected void handleRemoved(IResource[] resources) { - handleDefault(resources); - } - - protected void handleChanged(IResource[] resources) { - handleDefault(resources); - } - - protected void finished() { - TeamPlugin.getManager().broadcastResourceStateChanges((IResource[]) delta.toArray(new IResource[delta.size()])); - delta.clear(); - } - - /** - * If a meta file has changed the cache will be out-of-date. It will be cleared and subsequent access - * will force a reload of the sync information when needed by a client. - */ - private void handleMetaChange(File cvsdir, IResource resource, boolean deep) { - File parent = cvsdir.getParentFile(); - clearCache(parent, IResource.DEPTH_ONE); - - // generate deltas for children of the parent because their state may of changed. - // it is safe to get the parent two up from the metafile because we have already - // confirmed that this is a meta directory. - if(resource.getParent().exists()) { - IContainer resourceParent = resource.getParent(); - delta.add(resourceParent); - try { - IResource[] children = resourceParent.members(); - for (int i = 0; i < children.length; i++) { - if(deep) { - children[i].accept(new IResourceVisitor() { - public boolean visit(IResource resource) throws CoreException { - delta.add(resource); - return true; - } - }); - } else { - delta.add(children[i]); - } - } - } catch(CoreException e) { - // XXX what can you do in a resource listener when an exception occurs??? - } - } - } - - /** - * Canonical handling of a resource change - */ - private void handleDefault(IResource[] resources) { - for (int i = 0; i < resources.length; i++) { - // it's seems that sometimes the resources in the array are null. - IResource resource = resources[i]; - if(resource!=null) { - IPath location = resource.getLocation(); - // if the resource does not exist on disk, ignore it. - if(location!=null) { - File file = location.toFile(); - String name = file.getName(); - if(SyncFileUtil.isMetaFile(file)) { - handleMetaChange(file.getParentFile(), resources[i].getParent(), false); - } else if(name.equals(SyncFileUtil.IGNORE_FILE)) { - handleMetaChange(file, resource, true); - } else if(!name.equals("CVS")) { //$NON-NLS-1$ - delta.add(resources[i]); - } - } - } - } - } - } - - /* - * @see ICVSSynchronizer#getFolderSync(File) - */ - public FolderSyncInfo getFolderSync(File file) throws CVSException { - if(file.exists() && file.isDirectory()) { - if(SyncFileUtil.getCVSSubdirectory(file).exists()) { - CacheData data = (CacheData)folderSyncCache.get(file, null); - if(data!=null) { - return (FolderSyncInfo)data.getData(); - } - } - } - return null; - } - - /* - * @see ICVSSynchronizer#getResourceSync(File) - */ - public ResourceSyncInfo getResourceSync(File file) throws CVSException { - File parentFile = file.getParentFile(); - if (parentFile != null) { - CacheData data = (CacheData)resourceSyncCache.get(file, null); - if(data!=null) { - return (ResourceSyncInfo)data.getData(); - } - } - return null; - } - - /* - * @see ICVSSynchronizer#setFolderSync(File, FolderSyncInfo) - */ - public void setFolderSync(File file, FolderSyncInfo info) throws CVSException { - SyncFileUtil.writeFolderConfig(file, info); - folderSyncCache.put(new CacheData(file, info, CACHE_EXPIRATION_MINUTES)); - } - - /* - * @see ICVSSynchronizer#setResourceSync(File, ResourceSyncInfo) - */ - public void setResourceSync(File file, ResourceSyncInfo info) throws CVSException { - Assert.isNotNull(info); - Assert.isTrue(file.getName().equals(info.getName())); - - SyncFileUtil.writeResourceSync(file, info); - resourceSyncCache.put(new CacheData(file, info, CACHE_EXPIRATION_MINUTES)); - } - - /* - * @see ICVSSynchronizer#deleteFolderSync(File, IProgressMonitor) - */ - public void deleteFolderSync(File file, IProgressMonitor monitor) throws CVSException { - destroySyncDeep(file, monitor); - } - - /* - * @see ICVSSynchronizer#deleteResourceSync(File) - */ - public void deleteResourceSync(File file) { - try { - SyncFileUtil.deleteSync(file); - } catch(CVSException e) { - // XXX Bad eating of exception - } - resourceSyncCache.remove(file); - } - - /* - * If the file no longer exists, then clear the cache, or else, refresh from local and allow the - * resource change listener to adapt to changes. - * - * @see ICVSSynchronizer#reload(File, IProgressMonitor) - */ - public void reload(File file, IProgressMonitor monitor) throws CVSException { - reloadDeep(file, false, monitor); - } - - /* - * Simply reload to absorb changes made to the underlying file system. - * - * @see ICVSSynchronizer#save(File, IProgressMonitor) - */ - public void save(File file, IProgressMonitor monitor) throws CVSException { - reload(file, monitor); - } - - /* - * Answers if the caches are empty. - * - * @see ICVSSynchronizer#isEmpty() - */ - public boolean isEmpty() { - return resourceSyncCache.isEmpty() && folderSyncCache.isEmpty(); - } - - /* - * @see ICVSSynchronizer#members(File) - */ - public ResourceSyncInfo[] members(File folder) throws CVSException { - // read the entries file and cache if needed - Assert.isTrue(folder.exists()); - ResourceSyncInfo[] infos = SyncFileUtil.readEntriesFile(folder); - if(infos==null) { - return new ResourceSyncInfo[0]; - } else { - return infos; - } - } - - protected void destroySyncDeep(File file, IProgressMonitor monitor) { - if (file.isDirectory()) { - File[] fileList = file.listFiles(); - for (int i = 0; i < fileList.length; i++) { - destroySyncDeep(fileList[i], monitor); - } - folderSyncCache.remove(file); - File metaDir = SyncFileUtil.getCVSSubdirectory(file); - if(metaDir.exists()) { - FileUtil.deepDelete(metaDir); - } - } - deleteResourceSync(file); - } - - protected void clearCache(File file, int depth) { - clearCacheForChildren(file); - } - - protected void clearCacheForChildren(File file) { - // XXX not optimal, could instead have implement the cache as a tree - // and be able to traverse children. This is the safest for now. - resourceSyncCache.clear(); - folderSyncCache.clear(); - cvsIgnoreCache.clear(); - } - - protected void reloadDeep(File file, boolean refreshFromParent, IProgressMonitor monitor) throws CVSException { - - clearCache(file, IResource.DEPTH_INFINITE); - - if(!file.exists()) { - // a non-existant file implies that there is no longer any meta information - // on disk, we can safely clear the cache. - // we can safely reload the parent if it exists. - file = file.getParentFile(); - if(!file.exists()) { - return; - } - } - - // the following is to refresh the workbench with the local file changes. - if(file.equals(ResourcesPlugin.getWorkspace().getRoot().getLocation().toFile())) { - return; - } - - IResource resource; - if(file.isDirectory() && !refreshFromParent) { - resource = ResourcesPlugin.getWorkspace().getRoot().getContainerForLocation(new Path(file.getAbsolutePath())); - } else { - // reload a container always, or else sync info changes won't be loaded! - resource = ResourcesPlugin.getWorkspace().getRoot().getContainerForLocation(new Path(file.getParentFile().getAbsolutePath())); - } - try { - if(resource!=null) { - resource.refreshLocal(IResource.DEPTH_INFINITE, monitor); - } - } catch(CoreException e) { - throw new CVSException(IStatus.ERROR, 0, Policy.bind("FileSystemSynchronizer_Error_reloading_sync_information_5"), e); //$NON-NLS-1$ - } - } - - /* - * @see ICVSSynchronizer#isIgnored(File) - */ - public boolean isIgnored(File file) { - CacheData data = cvsIgnoreCache.get(file.getParentFile(), null); - if(data==null) return false; - String[] patterns = (String[])data.getData(); - FileNameMatcher matcher = new FileNameMatcher(patterns); - return matcher.match(file.getName()); - } - - /* - * @see ICVSSynchronizer#setIgnored(File, String) - */ - public void setIgnored(File file, String pattern) throws CVSException { - SyncFileUtil.addCvsIgnoreEntry(file, pattern); - reloadDeep(file, true, new NullProgressMonitor()); - } -}
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/FileUtil.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/FileUtil.java index 41c72d2fd..67e6771a4 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/FileUtil.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/FileUtil.java @@ -10,6 +10,9 @@ import java.io.IOException; import java.io.InputStream;
import java.io.OutputStream;
+import org.eclipse.team.ccvs.core.ICVSFolder;
+import org.eclipse.team.ccvs.core.ICVSResource;
+
public class FileUtil {
public static void deepDelete(File resource) {
@@ -21,7 +24,7 @@ public class FileUtil { }
resource.delete();
}
-
+
public static void transfer(InputStream in, OutputStream out) throws IOException {
final byte[] BUFFER = new byte[4096];
int read = 0;
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/SyncFileWriter.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/SyncFileWriter.java new file mode 100644 index 000000000..3fe345b84 --- /dev/null +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/SyncFileWriter.java @@ -0,0 +1,354 @@ +package org.eclipse.team.internal.ccvs.core.util; + +/* + * (c) Copyright IBM Corp. 2000, 2001. + * All Rights Reserved. + */ + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.team.ccvs.core.CVSTag; +import org.eclipse.team.ccvs.core.ICVSFile; +import org.eclipse.team.ccvs.core.ICVSFolder; +import org.eclipse.team.ccvs.core.ICVSResource; +import org.eclipse.team.internal.ccvs.core.CVSException; +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.FolderSyncInfo; +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 { + + // 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$ + public static final String PERMISSIONS = "Permissions"; //$NON-NLS-1$ + public static final String ENTRIES_LOG="Entries.Log"; //$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$ + + // file and folder patterns that are ignored by default by the CVS server on import. + public static final String[] PREDEFINED_IGNORE_PATTERNS = { + "CVS", ".#*", "#*", ",*", "_$*", "*~", "*$", "*.a", "*.bak", "*.BAK", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ + "*.elc", "*.exe", "*.ln", "*.o", "*.obj", "*.olb", "*.old", "*.orig", "*.rej", "*.so", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$ + "*.Z", ".del-*", ".make.state", ".nse_depinfo", "CVS.adm", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ + "cvslog.*", "RCS", "RCSLOG", "SCCS", "tags", "TAGS"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ + + // file and folder patterns that are ignored by default by the CVS server on import. + public static final String[] BASIC_IGNORE_PATTERNS = {"CVS", ".#*"}; //$NON-NLS-1$ //$NON-NLS-2$ + + /* + * Reads the CVS/Entry and CVS/Permissions files for the given folder. If the folder does not have a + * CVS subdirectory then <code>null</code> is returned. + */ + public static ResourceSyncInfo[] readEntriesFile(ICVSFolder parent) throws CVSException { + + ICVSFolder cvsSubDir = getCVSSubdirectory(parent); + + if(!cvsSubDir.exists()) { + return null; + } + + // The Eclipse CVS client does not write to the Entries.log file. Thus + // merging is required for external command line client compatibility. + mergeEntriesLogFiles(parent); + + Map infos = new TreeMap(); + String[] entries = getContents(cvsSubDir.getFile(ENTRIES)); + String[] permissions = getContents(cvsSubDir.getFile(PERMISSIONS)); + + if (entries == null) { + return null; + } + + 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); + } + } + + if (permissions != null) { + for (int i = 0; i < permissions.length; i++) { + if ("".equals(permissions[i])) { //$NON-NLS-1$ + continue; + } + String line = permissions[i]; + EmptyTokenizer tokenizer = new EmptyTokenizer(line,"/"); //$NON-NLS-1$ + String name = tokenizer.nextToken(); + String perms = tokenizer.nextToken(); + ResourceSyncInfo info = (ResourceSyncInfo) infos.get(name); + // Running the command line tool will update the Entries file and thus cause + // the Permissions to be out-of-sync. + if (info != null) { + infos.put(name, new ResourceSyncInfo(info.getEntryLine(true), perms, null)); + } + } + } + return (ResourceSyncInfo[])infos.values().toArray(new ResourceSyncInfo[infos.size()]); + } + + public static void writeResourceSync(ICVSResource file, ResourceSyncInfo info) throws CVSException { + writeEntriesLog(file, info, ADD_TAG); + } + + /* + * Delete this file from Entries/Permissions file + */ + public static void deleteSync(ICVSResource file) throws CVSException { + if(file.isFolder()) { + writeEntriesLog(file, new ResourceSyncInfo(file.getName()), REMOVE_TAG); + } else { + writeEntriesLog(file, new ResourceSyncInfo(file.getName(), "0", "", "", null, ""), REMOVE_TAG); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + } + } + + public static void deleteFolderSync(ICVSFolder folder) throws CVSException { + ICVSFolder[] children = folder.getFolders(); + for (int i = 0; i < children.length; i++) { + deleteFolderSync(children[i]); + } + ICVSFolder cvsSubDir = getCVSSubdirectory(folder); + cvsSubDir.delete(); + } + + /** + * Read folder sync info, returns <code>null</code> if the folder does not have + * a CVS subdirectory. + */ + public static FolderSyncInfo readFolderConfig(ICVSFolder folder) throws CVSException { + + ICVSFolder cvsSubDir = getCVSSubdirectory(folder); + + if(!cvsSubDir.exists()) { + return null; + } + + String staticDir = readLine(cvsSubDir.getFile(STATIC)); + String repo = readLine(cvsSubDir.getFile(REPOSITORY)); + String root = readLine(cvsSubDir.getFile(ROOT)); + String tag = readLine(cvsSubDir.getFile(TAG)); + + boolean isStatic = false; + if (staticDir != null) + isStatic = true; + + if(root == null || repo == null) { + return null; + } + + CVSTag cvsTag = null; + if(tag != null) { + cvsTag = new CVSEntryLineTag(tag); + } + + return new FolderSyncInfo(repo, root, cvsTag, isStatic); + } + + public static void writeFolderConfig(ICVSFolder folder, FolderSyncInfo info) throws CVSException { + + ICVSFolder cvsSubDir = getCVSSubdirectory(folder); + + if(!cvsSubDir.exists()) { + cvsSubDir.mkdir(); + } + + writeLines(cvsSubDir.getFile(ROOT), new String[] {info.getRoot()}); + ICVSFile tagFile = cvsSubDir.getFile(TAG); + if (info.getTag() != null) { + writeLines(tagFile, new String[] {info.getTag().toEntryLineFormat(false)}); + } else { + if(tagFile.exists()) { + tagFile.delete(); + } + } + ICVSFile staticFile = cvsSubDir.getFile(STATIC); + if(info.getIsStatic()) { + // the existance of the file is all that matters + writeLines(staticFile, new String[] {""}); //$NON-NLS-1$ + } else { + if(staticFile.exists()) { + staticFile.delete(); + } + } + writeLines(cvsSubDir.getFile(REPOSITORY), new String[] {info.getRepository()}); + } + + protected static String readLine(ICVSFile file) throws CVSException { + String[] contents = getContents(file); + if (contents == null) { + return null; + } else if (contents.length == 0) { + return ""; //$NON-NLS-1$ + } else { + return contents[0]; + } + } + + protected static String[] getContents(ICVSFile file) throws CVSException { + // If the property does not exsist we return null + // this is specified + if (file.exists()) { + return readLines(file); + } else { + return null; + } + } + + public static ICVSFolder getCVSSubdirectory(ICVSFolder folder) throws CVSException { + return folder.getFolder("CVS"); //$NON-NLS-1$ + } + + public static void mergeEntriesLogFiles(ICVSFolder root) throws CVSException { + + ICVSFile logEntriesFile = getCVSSubdirectory(root).getFile(ENTRIES_LOG); + ICVSFile entriesFile = getCVSSubdirectory(root).getFile(ENTRIES); + + if (!logEntriesFile.exists()) { + // If we do not have an Entries.Log file we are done because there is nothing + // to merge (this includes the case where we do not have CVSDirectory) + return; + } + + // The map contains the name of the resource as the key and the entryLine as the + // value + // "new ResourceSyncInfo(entryLine,null)).getName()" ist used to parse the name + // out of the entryLine and shoud maybe be replaced sometime + + Map mergedEntries = new HashMap(); + + if(entriesFile.exists()) { + String[] entries = readLines(entriesFile); + for (int i = 0; i < entries.length; i++) { + if (!FOLDER_TAG.equals(entries[i])) { + mergedEntries.put((new ResourceSyncInfo(entries[i],null, null)).getName(),entries[i]); + } + } + } + + String[] logEntries = readLines(logEntriesFile); + for (int i = 0; i < logEntries.length; i++) { + + if (logEntries[i].startsWith(ADD_TAG)) { + String newEntry = logEntries[i].substring(ADD_TAG.length()); + mergedEntries.put((new ResourceSyncInfo(newEntry,null, null)).getName(),newEntry); + } else if (logEntries[i].startsWith(REMOVE_TAG)) { + String newEntry = logEntries[i].substring(REMOVE_TAG.length()); + mergedEntries.remove((new ResourceSyncInfo(newEntry,null, null)).getName()); + } + } + + writeLines(entriesFile,(String[]) mergedEntries.values().toArray(new String[mergedEntries.size()])); + logEntriesFile.delete(); + } + + public static String[] readLines(ICVSFile file) throws CVSException { + BufferedReader fileReader; + List fileContentStore = new ArrayList(); + String line; + + try { + fileReader = new BufferedReader(new InputStreamReader(file.getInputStream())); + while ((line = fileReader.readLine()) != null) { + fileContentStore.add(line); + } + fileReader.close(); + } catch (IOException e) { + throw CVSException.wrapException(e); + } + + return (String[]) fileContentStore.toArray(new String[fileContentStore.size()]); + } + + /* + * To be compatible with other CVS clients meta files must be written with lines + * terminating with a carriage return only. + */ + private static void writeLines(ICVSFile file, String[] content) throws CVSException { + + BufferedWriter fileWriter; + + try { + fileWriter = new BufferedWriter(new OutputStreamWriter(file.getOutputStream())); + for (int i = 0; i<content.length; i++) { + fileWriter.write(content[i] + "\n"); //$NON-NLS-1$ + } + fileWriter.close(); + } catch (IOException e) { + throw CVSException.wrapException(e); + } + } + + public static void addCvsIgnoreEntry(ICVSFile file, String pattern) throws CVSException { + OutputStream out = null; + try { + ICVSFile cvsignore = file.getParent().getFile(IGNORE_FILE); + String line = pattern == null ? file.getName() : pattern; + line += "\n"; //$NON-NLS-1$ + out = cvsignore.getAppendingOutputStream(); + out.write(line.getBytes()); + } catch(IOException e) { + throw new CVSException(IStatus.ERROR, 0, Policy.bind("SyncFileUtil_Error_writing_to_.cvsignore_61"), e); //$NON-NLS-1$ + } finally { + try { + if(out!=null) { + out.close(); + } + } catch(IOException e) { + throw new CVSException(IStatus.ERROR, 0, Policy.bind("SyncFileUtil_Cannot_close_.cvsignore_62"), e); //$NON-NLS-1$ + } + } + } + + /* + * Append to Entries.log file + */ + private static void writeEntriesLog(ICVSResource file, ResourceSyncInfo info, String prefix) throws CVSException { + OutputStream out = null; + try { + ICVSFile entriesLogFile = getCVSSubdirectory(file.getParent()).getFile(ENTRIES_LOG); + String line = prefix + info.getEntryLine(true) +"\n"; //$NON-NLS-1$ + out = entriesLogFile.getAppendingOutputStream(); + out.write(line.getBytes()); + } catch(IOException e) { + throw new CVSException(IStatus.ERROR, 0, Policy.bind("SyncFileUtil_Error_writing_to_Entries.log_48"), e); //$NON-NLS-1$ + } finally { + try { + if(out!=null) { + out.close(); + } + } catch(IOException e) { + throw new CVSException(IStatus.ERROR, 0, Policy.bind("SyncFileUtil_Cannot_close_Entries.log_49"), e); //$NON-NLS-1$ + } + } + } +}
\ No newline at end of file diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/Util.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/Util.java index bf9ce02ab..7c94be7f5 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/Util.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/util/Util.java @@ -28,58 +28,7 @@ public class Util { // private static final String newLine = System.getProperty("line.separator"); - /** - * Looks for search in original. If it findes search it puts excange - * in the result. Otherwise it copies original in the result. - */ - public static byte[] replace(final byte[] original,final byte[] search,final byte[] excange) { - - final int tmpMulti; - final byte[] tmpResult; - final byte[] result; - - int size=0; - boolean replaced; - // create an array, that can hold the result for sure - tmpMulti = (int) Math.ceil((double)excange.length/(double)search.length); - - Assert.isTrue((long)tmpMulti * (long)original.length < Integer.MAX_VALUE); - tmpResult = new byte[tmpMulti * original.length]; - - int i=0; - while (i < original.length) { - replaced = false; - for (int j = 0; j < search.length; j++) { - - if ((i+j >= original.length) || (original[i+j] != search[j])) { - // Send another letter to the result - // array - break; - } - - if (j == search.length-1) { - // We have found the search and going to - // put excange intead of it - System.arraycopy(excange,0,tmpResult,size,excange.length); - size += excange.length; - i += search.length; - replaced = true; - } - } - - if (!replaced) { - tmpResult[size] = original[i]; - i++; - size++; - } - } - - result = new byte[size]; - System.arraycopy(tmpResult,0,result,0,size); - return result; - } - /** * @see Util#getOptions(String[],String,boolean) */ @@ -222,29 +171,8 @@ public class Util { * when you insert ":pserver:nkrambro:password@fiji:/home/nkrambro/repo" */ // FIXME: This is only used for tests ... move it - public static String getPassword(String root) { - return passwordHandle(root,false); - } // FIXME: This is only used for tests ... move it - public static String mergeRoot(String rootWithoutPwd, String password) { - - StringBuffer result = new StringBuffer(); - - Assert.isTrue(rootWithoutPwd.indexOf(AT) != -1); - Assert.isTrue(rootWithoutPwd.indexOf(COLON) != -1); - - if (password == null) { - return rootWithoutPwd; - } - - result.append(rootWithoutPwd.substring(0,rootWithoutPwd.indexOf(AT))); - result.append(COLON); - result.append(password); - result.append(rootWithoutPwd.substring(rootWithoutPwd.indexOf(AT))); - - return result.toString(); - } /** * Get the extention of the path of resource |