1 /******************************************************************************* 2 * Copyright (c) 2000, 2010 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.team.internal.ccvs.ui.operations; 15 16 import org.eclipse.core.resources.*; 17 import org.eclipse.core.runtime.*; 18 import org.eclipse.osgi.util.NLS; 19 import org.eclipse.swt.widgets.Shell; 20 import org.eclipse.team.core.RepositoryProvider; 21 import org.eclipse.team.core.TeamException; 22 import org.eclipse.team.internal.ccvs.core.*; 23 import org.eclipse.team.internal.ccvs.core.client.Command; 24 import org.eclipse.team.internal.ccvs.core.client.Session; 25 import org.eclipse.team.internal.ccvs.core.connection.CVSServerException; 26 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; 27 import org.eclipse.team.internal.ccvs.core.resources.RemoteFolderTree; 28 import org.eclipse.team.internal.ccvs.ui.CVSUIMessages; 29 import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin; 30 import org.eclipse.team.internal.ccvs.ui.Policy; 31 32 /** 33 * Create a folder and any missing parents in the repository 34 */ 35 public class ShareProjectOperation extends CVSOperation { 36 37 private ICVSRepositoryLocation location; 38 private IProject project; 39 private String moduleName; 40 private Shell shell; 41 ShareProjectOperation(Shell shell, ICVSRepositoryLocation location, IProject project, String moduleName)42 public ShareProjectOperation(Shell shell, ICVSRepositoryLocation location, IProject project, String moduleName) { 43 super(null); 44 this.shell = shell; 45 this.moduleName = moduleName; 46 this.project = project; 47 this.location = location; 48 } 49 50 @Override execute(IProgressMonitor monitor)51 protected void execute(IProgressMonitor monitor) throws CVSException, InterruptedException { 52 try { 53 monitor.beginTask(getTaskName(), 100); 54 // Create the remote module 55 final ICVSRemoteFolder remote = createRemoteFolder(Policy.subMonitorFor(monitor, 50)); 56 // Map the project to the module in a workspace runnable 57 final TeamException[] exception = new TeamException[] {null}; 58 ResourcesPlugin.getWorkspace().run((IWorkspaceRunnable) monitor1 -> { 59 try { 60 mapProjectToRemoteFolder(remote, monitor1); 61 } catch (TeamException e) { 62 exception[0] = e; 63 } 64 }, ResourcesPlugin.getWorkspace().getRuleFactory().modifyRule(project), 0, Policy.subMonitorFor(monitor, 100)); 65 if (exception[0] != null) 66 throw exception[0]; 67 } catch (CoreException e) { 68 throw CVSException.wrapException(e); 69 } finally { 70 monitor.done(); 71 } 72 } 73 74 /** 75 * Create the remote folder to which the project is being mapped 76 * (as well as any ancestors) and return it. If the remote folder does not 77 * exist remotely, this method will create it. 78 * @param monitor a progress monitor 79 * @return the existing remote folder to which the project is being mapped 80 * @throws CVSException 81 */ createRemoteFolder(IProgressMonitor monitor)82 protected ICVSRemoteFolder createRemoteFolder(IProgressMonitor monitor) throws CVSException { 83 String projectName = project.getName(); 84 if (moduleName == null) 85 moduleName = projectName; 86 87 RemoteFolderTree root = new RemoteFolderTree(null, location, Path.EMPTY.toString(), null); 88 Path path = new Path(null, moduleName); 89 90 try { 91 monitor.beginTask(getTaskName(), 100 * path.segmentCount()); 92 return ensureTreeExists(root, path, monitor); 93 } catch (TeamException e) { 94 throw CVSException.wrapException(e); 95 } finally { 96 monitor.done(); 97 } 98 } 99 100 /** 101 * Map the project to the remote folder by associating the CVS 102 * Repository Provider with the project and, at the very least, 103 * assigning the folder sync info for the remote folder as the 104 * folder sync info for the project. 105 * @param remote the remote folder to which the project is being mapped 106 * @param monitor a progress monitor 107 * @throws CVSException 108 */ mapProjectToRemoteFolder(final ICVSRemoteFolder remote, IProgressMonitor monitor)109 protected void mapProjectToRemoteFolder(final ICVSRemoteFolder remote, IProgressMonitor monitor) throws TeamException { 110 monitor.beginTask(null, IProgressMonitor.UNKNOWN); 111 purgeAnyCVSFolders(Policy.subMonitorFor(monitor, IProgressMonitor.UNKNOWN)); 112 // Link the project to the newly created module 113 monitor.subTask(NLS.bind(CVSUIMessages.ShareProjectOperation_3, new String[] { project.getName(), remote.getRepositoryRelativePath() })); 114 ICVSFolder folder = (ICVSFolder)CVSWorkspaceRoot.getCVSResourceFor(project); 115 folder.setFolderSyncInfo(remote.getFolderSyncInfo()); 116 //Register it with Team. If it already is, no harm done. 117 RepositoryProvider.map(project, CVSProviderPlugin.getTypeId()); 118 monitor.done(); 119 } 120 121 /* 122 * Create handles for all the children in the moduleName path 123 */ createChild(RemoteFolderTree parent, String name, IProgressMonitor monitor)124 private RemoteFolderTree createChild(RemoteFolderTree parent, String name, IProgressMonitor monitor) throws CVSException, TeamException { 125 RemoteFolderTree child = new RemoteFolderTree(parent, name, location, new Path(null, parent.getRepositoryRelativePath()).append(name).toString(), null); 126 parent.setChildren(new ICVSRemoteResource[] { child }); 127 if (child.exists(Policy.subMonitorFor(monitor, 50))) { 128 // The child exists so get the handle that was received from the server 129 return (RemoteFolderTree)parent.getFolder(name); 130 } else { 131 // Create the folder remotely 132 createFolder(child, Policy.subMonitorFor(monitor, 50)); 133 return child; 134 } 135 } 136 137 /* 138 * Ensure that all the folders in the tree exist 139 */ ensureTreeExists(RemoteFolderTree folder, IPath path, IProgressMonitor monitor)140 private ICVSRemoteFolder ensureTreeExists(RemoteFolderTree folder, IPath path, IProgressMonitor monitor) throws TeamException { 141 if (path.isEmpty()) return folder; 142 String name = path.segment(0); 143 RemoteFolderTree child = createChild(folder, name, monitor); 144 return ensureTreeExists(child, path.removeFirstSegments(1), monitor); 145 } 146 createFolder(RemoteFolderTree folder, IProgressMonitor monitor)147 private void createFolder(RemoteFolderTree folder, IProgressMonitor monitor) throws TeamException { 148 Session s = new Session(location, folder.getParent()); 149 s.open(monitor, true /* open for modification */); 150 try { 151 IStatus status = Command.ADD.execute(s, 152 Command.NO_GLOBAL_OPTIONS, 153 Command.NO_LOCAL_OPTIONS, 154 new String[] { folder.getName() }, 155 null, 156 monitor); 157 // If we get a warning, the operation most likely failed so check that the status is OK 158 if (status.getCode() == CVSStatus.SERVER_ERROR || ! status.isOK()) { 159 throw new CVSServerException(status); 160 } 161 } finally { 162 s.close(); 163 } 164 } 165 166 @Override getTaskName()167 protected String getTaskName() { 168 return NLS.bind(CVSUIMessages.ShareProjectOperation_0, new String[] { project.getName(), moduleName }); 169 } 170 171 /** 172 * @return Returns the project. 173 */ getProject()174 public IProject getProject() { 175 return project; 176 } 177 178 @Override getShell()179 public Shell getShell() { 180 return shell; 181 } 182 183 /** 184 * Purge any CVS folders. 185 * 186 * @param monitor a progress monitor 187 */ purgeAnyCVSFolders(final IProgressMonitor monitor)188 private void purgeAnyCVSFolders(final IProgressMonitor monitor) { 189 try { 190 monitor.beginTask(null, IProgressMonitor.UNKNOWN); 191 ICVSFolder folder = CVSWorkspaceRoot.getCVSFolderFor(project); 192 folder.accept(new ICVSResourceVisitor() { 193 @Override 194 public void visitFile(ICVSFile file) throws CVSException { 195 // nothing to do for files 196 } 197 @Override 198 public void visitFolder(ICVSFolder folder) throws CVSException { 199 monitor.subTask(NLS.bind(CVSUIMessages.ShareProjectOperation_2, new String[] { folder.getIResource().getFullPath().toString() } )); 200 if (folder.isCVSFolder()) { 201 // for now, just unmanage 202 folder.unmanage(null); 203 } 204 } 205 }, true /* recurse */); 206 } catch (CVSException e) { 207 // log the exception and return null 208 CVSUIPlugin.log(e); 209 } finally { 210 monitor.done(); 211 } 212 } 213 } 214