package hudson.plugins.tfs.commands;
import com.google.common.base.Strings;
import com.microsoft.tfs.core.clients.versioncontrol.VersionControlConstants;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.Changeset;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.RecursionType;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.DateVersionSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.LabelVersionSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.VersionSpec;
import hudson.model.TaskListener;
import hudson.plugins.tfs.model.MockableVersionControlClient;
import hudson.plugins.tfs.model.Server;
import hudson.plugins.tfs.util.DateUtil;
import hudson.plugins.tfs.util.TextTableParser;
import hudson.remoting.Callable;
import org.apache.commons.lang.StringUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintStream;
import java.io.Reader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
/**
* TF command for retrieving the latest remote change set version in effect at the specified time.
*
* @author Olivier Dagenais
*
*/
public class RemoteChangesetVersionCommand extends AbstractCallableCommand<Integer, Exception> {
private static final String QueryingTemplate = "Querying for remote changeset at '%s' as of '%s'...";
private static final String ResultTemplate = "Query result is: Changeset #%d by '%s' on '%s'.";
private static final String FailedTemplate = "Query returned no result!";
private final String versionSpecString;
private final String path;
public RemoteChangesetVersionCommand(
final ServerConfigurationProvider server, final String remotePath, final VersionSpec versionSpec) {
super(server);
this.path = remotePath;
this.versionSpecString = toString(versionSpec);
}
public Callable<Integer, Exception> getCallable() {
return this;
}
public Integer call() throws Exception {
final Server server = createServer();
final MockableVersionControlClient vcc = server.getVersionControlClient();
final TaskListener listener = server.getListener();
final PrintStream logger = listener.getLogger();
final VersionSpec versionSpec = VersionSpec.parseSingleVersionFromSpec(versionSpecString, VersionControlConstants.AUTHENTICATED_USER);
final String specString = RemoteChangesetVersionCommand.toString(versionSpec);
final String queryingMessage = String.format(QueryingTemplate, path, specString);
logger.println(queryingMessage);
final Changeset[] serverChangeSets = vcc.queryHistory(
path,
versionSpec,
0 /* deletionId */,
RecursionType.FULL,
null /* user */,
null,
null,
1 /* maxCount */,
false /* includeFileDetails */,
true /* slotMode */,
false /* includeDownloadInfo */,
false /* sortAscending */
);
Integer changeSetNumber = null;
final String resultMessage;
if (serverChangeSets != null && serverChangeSets.length >= 1) {
final Changeset serverChangeset = serverChangeSets[0];
changeSetNumber = serverChangeset.getChangesetID();
final Date changeSetDate = serverChangeset.getDate().getTime();
final String author = serverChangeset.getCommitter();
final SimpleDateFormat simpleDateFormat = DateUtil.TFS_DATETIME_FORMATTER.get();
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
final String changeSetDateIso8601 = simpleDateFormat.format(changeSetDate);
resultMessage = String.format(ResultTemplate, changeSetNumber, author, changeSetDateIso8601);
} else {
resultMessage = FailedTemplate;
}
logger.println(resultMessage);
return changeSetNumber;
}
public static String toString(final VersionSpec versionSpec) {
// TODO: just call versionSpec.toString() once DateVersionSpec.toString() uses ISO 8601 format
if (versionSpec instanceof DateVersionSpec){
final DateVersionSpec dateVersionSpec = (DateVersionSpec) versionSpec;
return DateUtil.toString(dateVersionSpec);
}
else if (versionSpec instanceof LabelVersionSpec) {
final LabelVersionSpec labelVersionSpec = (LabelVersionSpec) versionSpec;
// TODO: It seems to me LabelVersionSpec.toString() should emit "Lfoo" when its scope is null
final String label = labelVersionSpec.getLabel();
final String scope = labelVersionSpec.getScope();
final StringBuilder sb = new StringBuilder(1 + label.length() + Strings.nullToEmpty(scope).length());
sb.append('L');
sb.append(label);
if (!Strings.isNullOrEmpty(scope)) {
sb.append('@');
sb.append(scope);
}
return sb.toString();
}
return versionSpec.toString();
}
public String parse(Reader consoleReader) throws ParseException, IOException {
TextTableParser parser = new TextTableParser(new BufferedReader(consoleReader), 1);
while (parser.nextRow()) {
return parser.getColumn(0);
}
return StringUtils.EMPTY;
}
}