package hudson.plugins.tfs.actions;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.DateVersionSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.VersionSpec;
import hudson.FilePath;
import hudson.model.TaskListener;
import hudson.plugins.tfs.commands.RemoteChangesetVersionCommand;
import hudson.plugins.tfs.model.ChangeSet;
import hudson.plugins.tfs.model.Project;
import hudson.plugins.tfs.model.Server;
import hudson.plugins.tfs.model.Workspace;
import hudson.plugins.tfs.model.Workspaces;
import java.io.IOException;
import java.io.PrintStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
public class CheckoutAction {
private final String workspaceName;
private final String projectPath;
private final Collection<String> cloakedPaths;
private final String localFolder;
private final boolean useUpdate;
public CheckoutAction(String workspaceName, String projectPath, Collection<String> cloakedPaths, String localFolder, boolean useUpdate) {
this.workspaceName = workspaceName;
this.projectPath = projectPath;
this.cloakedPaths = cloakedPaths;
this.localFolder = localFolder;
this.useUpdate = useUpdate;
}
public List<ChangeSet> checkout(Server server, FilePath workspacePath, Calendar lastBuildTimestamp, Calendar currentBuildTimestamp) throws IOException, InterruptedException, ParseException {
final VersionSpec lastBuildVersionSpec;
if (lastBuildTimestamp != null) {
lastBuildVersionSpec = new DateVersionSpec(lastBuildTimestamp);
}
else{
lastBuildVersionSpec = null;
}
final VersionSpec currentBuildVersionSpec = new DateVersionSpec(currentBuildTimestamp);
return checkout(server, workspacePath, lastBuildVersionSpec, currentBuildVersionSpec);
}
public List<ChangeSet> checkout(final Server server, final FilePath workspacePath, final VersionSpec lastBuildVersionSpec, final VersionSpec currentBuildVersionSpec) throws IOException, InterruptedException {
Project project = getProject(server, workspacePath);
final String versionSpecString = RemoteChangesetVersionCommand.toString(currentBuildVersionSpec);
final String normalizedFolder = determineCheckoutPath(workspacePath, localFolder);
project.getFiles(normalizedFolder, versionSpecString);
if (lastBuildVersionSpec != null) {
return project.getVCCHistory(lastBuildVersionSpec, currentBuildVersionSpec, true, Integer.MAX_VALUE);
}
return new ArrayList<ChangeSet>();
}
public List<ChangeSet> checkoutBySingleVersionSpec(Server server, FilePath workspacePath, String singleVersionSpec) throws IOException, InterruptedException {
Project project = getProject(server, workspacePath);
final String normalizedFolder = determineCheckoutPath(workspacePath, localFolder);
project.getFiles(normalizedFolder, singleVersionSpec);
return project.getDetailedHistory(singleVersionSpec);
}
static String determineCheckoutPath(final FilePath workspacePath, final String localFolder) {
final FilePath combinedPath = new FilePath(workspacePath, localFolder);
final String result = combinedPath.getRemote();
return result;
}
private Project getProject(final Server server, final FilePath workspacePath)
throws IOException, InterruptedException {
final Workspaces workspaces = server.getWorkspaces();
final Project project = server.getProject(projectPath);
final FilePath localFolderPath = workspacePath.child(localFolder);
final String localPath = localFolderPath.getRemote();
final TaskListener listener = server.getListener();
final PrintStream logger = listener.getLogger();
final HashSet<String> workspaceNamesToDelete = new HashSet<String>();
final String existingWorkspaceName = workspaces.getWorkspaceMapping(localPath);
if (workspaces.exists(workspaceName)) {
if (!useUpdate) {
workspaceNamesToDelete.add(workspaceName);
}
if (existingWorkspaceName == null) {
logger.println("Warning: Although the server thinks the workspace exists, no mapping was found.");
workspaceNamesToDelete.add(workspaceName);
}
else if (existingWorkspaceName.equalsIgnoreCase(workspaceName)) {
// workspace exists and "localPath" is mapped there: everything is fine.
}
else {
// workspace exists AND "localPath" is mapped in another workspace???
final String template = "WARNING: Workspace '%s' already exists AND '%s' is also mapped in workspace '%s'. Is there a configuration error?";
final String message = String.format(template, workspaceName, localPath, existingWorkspaceName);
logger.println(message);
workspaceNamesToDelete.add(workspaceName);
workspaceNamesToDelete.add(existingWorkspaceName);
}
final boolean localFolderExists = localFolderPath.exists();
if (!localFolderExists) {
logger.println("Warning: The local folder is missing.");
workspaceNamesToDelete.add(workspaceName);
}
}
else {
// there is (apparently) no workspace called "workspaceName"...
if (existingWorkspaceName != null && !existingWorkspaceName.equalsIgnoreCase(workspaceName)) {
// "localPath" is mapped under another workspace name: delete the old one
final String template = "Workspace was apparently renamed, will delete the old one: '%s'.";
final String message = String.format(template, existingWorkspaceName);
logger.println(message);
workspaceNamesToDelete.add(existingWorkspaceName);
}
}
for (final String workspaceNameToDelete : workspaceNamesToDelete) {
final Workspace workspace = workspaces.getWorkspace(workspaceNameToDelete);
workspaces.deleteWorkspace(workspace);
}
Workspace workspace;
if (! workspaces.exists(workspaceName)) {
if ((!useUpdate || workspaceNamesToDelete.size() > 0) && localFolderPath.exists()) {
localFolderPath.deleteContents();
}
final String serverPath = project.getProjectPath();
workspace = workspaces.newWorkspace(workspaceName, serverPath, cloakedPaths, localPath);
} else {
workspace = workspaces.getWorkspace(workspaceName);
}
return project;
}
}