/**
  * Ensure that the sync info for all the provided resources has been loaded. If an out-of-sync
  * resource is found, prompt to refresh all the projects involved.
  */
 protected boolean ensureSyncInfoLoaded(IResource[] resources) throws CVSException {
   boolean keepTrying = true;
   while (keepTrying) {
     try {
       EclipseSynchronizer.getInstance().ensureSyncInfoLoaded(resources, getActionDepth());
       keepTrying = false;
     } catch (CVSException e) {
       if (e.getStatus().getCode() == IResourceStatus.OUT_OF_SYNC_LOCAL) {
         // determine the projects of the resources involved
         Set projects = new HashSet();
         for (int i = 0; i < resources.length; i++) {
           IResource resource = resources[i];
           projects.add(resource.getProject());
         }
         // prompt to refresh
         if (promptToRefresh(
             getShell(),
             (IResource[]) projects.toArray(new IResource[projects.size()]),
             e.getStatus())) {
           for (Iterator iter = projects.iterator(); iter.hasNext(); ) {
             IProject project = (IProject) iter.next();
             try {
               project.refreshLocal(IResource.DEPTH_INFINITE, null);
             } catch (CoreException coreException) {
               throw CVSException.wrapException(coreException);
             }
           }
         } else {
           return false;
         }
       } else {
         throw e;
       }
     }
   }
   return true;
 }
 /**
  * Return true if the sync info is loaded for all selected resources. The purpose of this method
  * is to allow enablement code to be as fast as possible. If the sync info is not loaded, the menu
  * should be enabled and, if choosen, the action will verify that it is indeed enabled before
  * performing the associated operation
  */
 protected boolean isSyncInfoLoaded(IResource[] resources) throws CVSException {
   return EclipseSynchronizer.getInstance().isSyncInfoLoaded(resources, getEnablementDepth());
 }