Copyright (c) 2000, 2015 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation Matt McCutchen - fix for bug 174492 James Blackburn (Broadcom Corp.) - ongoing development
/******************************************************************************* * Copyright (c) 2000, 2015 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation * Matt McCutchen - fix for bug 174492 * James Blackburn (Broadcom Corp.) - ongoing development *******************************************************************************/
package org.eclipse.core.internal.localstore; import java.util.Iterator; import java.util.List; import org.eclipse.core.filesystem.*; import org.eclipse.core.filesystem.provider.FileInfo; import org.eclipse.core.internal.resources.ICoreConstants; import org.eclipse.core.internal.resources.Resource; import org.eclipse.core.internal.utils.Messages; import org.eclipse.core.internal.utils.Policy; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; import org.eclipse.osgi.util.NLS; public class DeleteVisitor implements IUnifiedTreeVisitor, ICoreConstants { protected boolean force; protected boolean keepHistory; protected IProgressMonitor monitor; protected List<Resource> skipList; protected MultiStatus status;
The number of tickets available on the progress monitor
/** * The number of tickets available on the progress monitor */
private int ticks; public DeleteVisitor(List<Resource> skipList, int flags, IProgressMonitor monitor, int ticks) { this.skipList = skipList; this.ticks = ticks; this.force = (flags & IResource.FORCE) != 0; this.keepHistory = (flags & IResource.KEEP_HISTORY) != 0; this.monitor = monitor; status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.FAILED_DELETE_LOCAL, Messages.localstore_deleteProblem, null); }
Deletes a file from both the workspace resource tree and the file system.
/** * Deletes a file from both the workspace resource tree and the file system. */
protected void delete(UnifiedTreeNode node, boolean shouldKeepHistory) { Resource target = (Resource) node.getResource(); try { final boolean deleteLocalFile = !target.isLinked() && node.existsInFileSystem(); IFileStore localFile = deleteLocalFile ? node.getStore() : null; if (deleteLocalFile && shouldKeepHistory) recursiveKeepHistory(target.getLocalManager().getHistoryStore(), node); node.removeChildrenFromTree(); //delete from disk int work = ticks < 0 ? 0 : ticks; ticks -= work; if (deleteLocalFile) localFile.delete(EFS.NONE, Policy.subMonitorFor(monitor, work)); else monitor.worked(work); //delete from tree if (node.existsInWorkspace()) target.deleteResource(true, status); } catch (CoreException e) { status.add(e.getStatus()); // delete might have been partly successful, so refresh to ensure in sync try { target.refreshLocal(IResource.DEPTH_INFINITE, null); } catch (CoreException e1) { //ignore secondary failure - we are just trying to cleanup from first failure } } }
Only consider path in equality in order to handle gender changes
/** * Only consider path in equality in order to handle gender changes */
protected boolean equals(IResource one, IResource another) { return one.getFullPath().equals(another.getFullPath()); } public MultiStatus getStatus() { return status; } protected boolean isAncestor(IResource one, IResource another) { return one.getFullPath().isPrefixOf(another.getFullPath()) && !equals(one, another); } protected boolean isAncestorOfResourceToSkip(IResource resource) { if (skipList == null) return false; for (IResource target : skipList) { if (isAncestor(resource, target)) return true; } return false; } private void recursiveKeepHistory(IHistoryStore store, UnifiedTreeNode node) { final IResource target = node.getResource(); //we don't delete linked content, so no need to keep history if (target.isLinked() || target.isVirtual() || node.isSymbolicLink()) return; if (node.isFolder()) { monitor.subTask(NLS.bind(Messages.localstore_deleting, target.getFullPath())); for (Iterator<UnifiedTreeNode> children = node.getChildren(); children.hasNext();) recursiveKeepHistory(store, children.next()); } else { IFileInfo info = node.fileInfo; if (info == null) info = new FileInfo(node.getLocalName()); store.addState(target.getFullPath(), node.getStore(), info, true); } monitor.worked(1); ticks--; } protected void removeFromSkipList(IResource resource) { if (skipList != null) skipList.remove(resource); } protected boolean shouldSkip(IResource resource) { if (skipList == null) return false; for (int i = 0; i < skipList.size(); i++) if (equals(resource, skipList.get(i))) return true; return false; } @Override public boolean visit(UnifiedTreeNode node) { Policy.checkCanceled(monitor); Resource target = (Resource) node.getResource(); if (shouldSkip(target)) { removeFromSkipList(target); int skipTicks = target.countResources(IResource.DEPTH_INFINITE, false); monitor.worked(skipTicks); ticks -= skipTicks; return false; } if (isAncestorOfResourceToSkip(target)) return true; delete(node, keepHistory); return false; } }