/**
* The MIT License
*
* Copyright (c) 2007-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Erik Ramfelt,
* Henrik Lynggaard, Peter Liljenberg, Andrew Bayer, Vincent Latombe
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.plugins.clearcase;
import hudson.AbortException;
import hudson.FilePath;
import hudson.Util;
import hudson.plugins.clearcase.util.PathUtil;
import hudson.util.ArgumentListBuilder;
import hudson.util.VariableResolver;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
public abstract class ClearToolExec implements ClearTool {
private transient Pattern viewListPattern;
protected ClearToolLauncher launcher;
protected VariableResolver<String> variableResolver;
protected String optionalMkviewParameters;
public ClearToolExec(VariableResolver<String> variableResolver, ClearToolLauncher launcher, String optionalMkviewParameters) {
this.variableResolver = variableResolver;
this.launcher = launcher;
this.optionalMkviewParameters = optionalMkviewParameters;
}
public String catcs(String viewTag) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("catcs");
cmd.add("-tag", viewTag);
return runAndProcessOutput(cmd, null, null, false, null);
}
@Override
public Reader describe(String format, String objectSelector) throws IOException, InterruptedException {
Validate.notNull(objectSelector);
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("desc");
if (StringUtils.isNotBlank(format)) {
cmd.add("-fmt", format);
}
cmd.add(objectSelector);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
launcher.run(cmd.toCommandArray(), null, baos, null);
Reader reader = new InputStreamReader(new ByteArrayInputStream(baos.toByteArray()));
baos.close();
return reader;
}
@Override
public Reader diffbl(EnumSet<DiffBlOptions> type, String baseline1, String baseline2, String viewPath) {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("diffbl");
for (DiffBlOptions t : type) {
cmd.add(getOption(t));
}
cmd.add(baseline1);
cmd.add(baseline2);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
launcher.run(cmd.toCommandArray(), null, baos, launcher.getWorkspace().child(viewPath));
} catch (IOException e) {
} catch (InterruptedException e) {
}
return new InputStreamReader(new ByteArrayInputStream(baos.toByteArray()));
}
@Override
public boolean doesStreamExist(String streamSelector) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lsstream");
cmd.add("-short");
cmd.add(streamSelector);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
launcher.run(cmd.toCommandArray(), null, baos, null);
} catch (Exception e) {
// empty by design
}
baos.close();
String cleartoolResult = baos.toString();
return !(cleartoolResult.contains("stream not found"));
}
public boolean doesViewExist(String viewTag) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lsview");
cmd.add(viewTag);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
return launcher.run(cmd.toCommandArray(), null, baos, null);
} catch (IOException e) {
return false;
}
}
public void endView(String viewTag) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("endview");
cmd.add(viewTag);
String output = runAndProcessOutput(cmd, null, null, false, null);
if (output.contains("cleartool: Error")) {
throw new IOException("Failed to end view tag: " + output);
}
}
private String fixLoadRule(String loadRule) {
if (StringUtils.isBlank(loadRule)) {
return loadRule;
}
// Remove leading file separator, we don't need it when using add_loadrules
String quotedLR = ConfigSpec.cleanLoadRule(loadRule, getLauncher().getLauncher().isUnix());
if (quotedLR.startsWith("\"") && quotedLR.endsWith("\"")) {
return "\"" + quotedLR.substring(2);
} else {
return quotedLR.substring(1);
}
}
public ClearToolLauncher getLauncher() {
return launcher;
}
private Pattern getListPattern() {
if (viewListPattern == null) {
viewListPattern = Pattern.compile("(.)\\s*(\\S*)\\s*(\\S*)");
}
return viewListPattern;
}
private String getOption(DiffBlOptions type) {
switch (type) {
case ACTIVITIES:
return "-activities";
case VERSIONS:
return "-versions";
case BASELINES:
return "-baselines";
case FIRST_ONLY:
return "-first_only";
case NRECURSE:
return "-nrecurse";
default:
throw new IllegalArgumentException(type + " is not supported by this implementation");
}
}
private String getOption(SetcsOption option) {
switch (option) {
case CONFIGSPEC:
return null;
case CURRENT:
return "-current";
case STREAM:
return "-stream";
default:
throw new IllegalArgumentException(option + " is not supported by this implementation");
}
}
/**
* @param launcher
* @return The root view path
*/
protected abstract FilePath getRootViewPath(ClearToolLauncher launcher);
public Properties getViewData(String viewTag) throws IOException, InterruptedException {
Properties resPrp = new Properties();
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lsview");
cmd.add("-l", viewTag);
Pattern uuidPattern = Pattern.compile("View uuid: (.*)");
Pattern globalPathPattern = Pattern.compile("View server access path: (.*)");
boolean res = true;
IOException exception = null;
List<IOException> exceptions = new ArrayList<IOException>();
String output = runAndProcessOutput(cmd, null, null, true, exceptions);
// handle the use case in which view doesn't exist and therefore error is thrown
if (!exceptions.isEmpty() && !output.contains("No matching entries found for view")) {
throw exceptions.get(0);
}
if (res && exception == null) {
String[] lines = output.split("\n");
for (String line : lines) {
Matcher matcher = uuidPattern.matcher(line);
if (matcher.find() && matcher.groupCount() == 1)
resPrp.put("UUID", matcher.group(1));
matcher = globalPathPattern.matcher(line);
if (matcher.find() && matcher.groupCount() == 1)
resPrp.put("STORAGE_DIR", matcher.group(1));
}
}
return resPrp;
}
public boolean lock(String comment, String objectSelector) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lock");
cmd.add(objectSelector);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
launcher.run(cmd.toCommandArray(), null, baos, null);
String cleartoolResult = baos.toString();
if (cleartoolResult.contains("cleartool: Error")) {
return false;
}
baos.close();
return true;
}
public void logRedundantCleartoolError(String[] cmd, Exception ex) {
getLauncher().getListener().getLogger().println("Redundant Cleartool Error ");
if (cmd != null)
getLauncher().getListener().getLogger().println("command: " + getLauncher().getCmdString(cmd));
getLauncher().getListener().getLogger().println(ex.getMessage());
}
public Reader lsactivity(String activity, String commandFormat, String viewPath) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lsactivity");
cmd.add("-fmt", commandFormat);
cmd.add(activity);
// changed the path from workspace to getRootViewPath to make Dynamic UCM work
FilePath filePath = getRootViewPath(launcher).child(viewPath);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
launcher.run(cmd.toCommandArray(), null, baos, filePath);
InputStreamReader reader = new InputStreamReader(new ByteArrayInputStream(baos.toByteArray()));
baos.close();
return reader;
}
public String lsbl(String baselineName, String format) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lsbl");
if (StringUtils.isNotEmpty(format)) {
cmd.add("-fmt");
cmd.add(format);
}
cmd.add(baselineName);
return runAndProcessOutput(cmd, null, null, false, null);
}
@Override
public String lscurrentview(String viewPath) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lsview", "-cview", "-s");
List<IOException> exceptions = new ArrayList<IOException>();
String output = runAndProcessOutput(cmd, null, getLauncher().getWorkspace().child(viewPath), true, exceptions);
if (!exceptions.isEmpty()) {
if (output.contains("cleartool: Error: Cannot get view info for current view: not a ClearCase object.")) {
output = null;
} else {
throw exceptions.get(0);
}
}
return output;
}
public Reader lshistory(String format, Date lastBuildDate, String viewPath, String branch, String[] pathsInView) throws IOException, InterruptedException {
Validate.notNull(pathsInView);
Validate.notNull(viewPath);
SimpleDateFormat formatter = new SimpleDateFormat("d-MMM-yy.HH:mm:ss'UTC'Z", Locale.US);
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lshistory");
cmd.add("-all");
cmd.add("-since", formatter.format(lastBuildDate).toLowerCase());
cmd.add("-fmt", format);
// cmd.addQuoted(format);
if (StringUtils.isNotEmpty(branch)) {
cmd.add("-branch", "brtype:" + branch);
}
cmd.add("-nco");
FilePath filePath = getRootViewPath(launcher).child(viewPath);
for (String path : pathsInView) {
path = path.replace("\n", "").replace("\r", "");
if (path.matches(".*\\s.*")) {
cmd.addQuoted(path);
} else {
cmd.add(path);
}
}
Reader returnReader = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
launcher.run(cmd.toCommandArray(), null, baos, filePath);
} catch (IOException e) {
// We don't care if Clearcase returns an error code, we will process it afterwards
}
returnReader = new InputStreamReader(new ByteArrayInputStream(baos.toByteArray()));
baos.close();
return returnReader;
}
public String lsproject(String viewTag, String format) throws InterruptedException, IOException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lsproject");
cmd.add("-view");
cmd.add(viewTag);
if (StringUtils.isNotEmpty(format)) {
cmd.add("-fmt");
cmd.add(format);
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
launcher.run(cmd.toCommandArray(), null, baos, null);
} catch (IOException e) {
// We don't care if Clearcase returns an error code, we will process it afterwards
}
String output = baos.toString();
baos.close();
return output;
}
public String lsstream(String stream, String viewTag, String format) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lsstream");
if (StringUtils.isNotEmpty(viewTag)) {
cmd.add("-view", viewTag);
}
cmd.add("-fmt");
cmd.add(format);
if (StringUtils.isNotEmpty(stream)) {
cmd.add(stream);
}
return runAndProcessOutput(cmd, null, null, false, null);
}
public List<String> lsview(boolean onlyActiveDynamicViews) throws IOException, InterruptedException {
viewListPattern = getListPattern();
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lsview");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (launcher.run(cmd.toCommandArray(), null, baos, null)) {
return parseListOutput(new InputStreamReader(new ByteArrayInputStream(baos.toByteArray())), onlyActiveDynamicViews);
}
return new ArrayList<String>();
}
public List<String> lsvob(boolean onlyMounted) throws IOException, InterruptedException {
viewListPattern = getListPattern();
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("lsvob");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (launcher.run(cmd.toCommandArray(), null, baos, null)) {
return parseListOutput(new InputStreamReader(new ByteArrayInputStream(baos.toByteArray())), onlyMounted);
}
return new ArrayList<String>();
}
public List<Baseline> mkbl(String name, String viewTag, String comment, boolean fullBaseline, boolean identical, List<String> components, String dDependsOn, String aDependsOn) throws IOException, InterruptedException {
Validate.notNull(viewTag);
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("mkbl");
if (identical) {
cmd.add("-identical");
}
if (StringUtils.isNotBlank(comment)) {
cmd.add("-comment", comment);
}
if (fullBaseline) {
cmd.add("-full");
} else {
cmd.add("-incremental");
}
if (StringUtils.isNotEmpty(viewTag)) {
cmd.add("-view", viewTag);
}
// Make baseline only for specified components
if (CollectionUtils.isNotEmpty(components)) {
cmd.add("-comp", StringUtils.join(components, ','));
}
if (StringUtils.isNotEmpty(dDependsOn)) {
cmd.add("-ddepends_on", dDependsOn);
}
if (StringUtils.isNotEmpty(aDependsOn)) {
cmd.add("-adepends_on", aDependsOn);
}
cmd.add(name);
String output = runAndProcessOutput(cmd, null, null, false, null);
if (output.contains("cleartool: Error")) {
throw new IOException("Failed to make baseline, reason: " + output);
}
Pattern pattern = Pattern.compile("Created baseline \"(.+?)\" in component \"(.+?)\"");
Matcher matcher = pattern.matcher(output);
List<Baseline> createdBaselinesList = new ArrayList<Baseline>();
while (matcher.find() && matcher.groupCount() == 2 ) {
String baseline = matcher.group(1);
String component = matcher.group(2);
createdBaselinesList.add(new Baseline(baseline, component));
}
return createdBaselinesList;
}
public void mklabel(String viewName, String label) throws IOException, InterruptedException {
throw new AbortException();
}
public void mkstream(String parentStream, String stream) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("mkstream");
cmd.add("-in");
cmd.add(parentStream);
cmd.add(stream);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
launcher.run(cmd.toCommandArray(), null, baos, null);
baos.close();
}
public void mkview(String viewPath, String viewTag, String streamSelector) throws IOException, InterruptedException {
Validate.notEmpty(viewPath);
boolean isOptionalParamContainsHost = false;
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("mkview");
cmd.add("-snapshot");
if (streamSelector != null) {
cmd.add("-stream");
cmd.add(streamSelector);
}
cmd.add("-tag");
cmd.add(viewTag);
if ((optionalMkviewParameters != null) && (optionalMkviewParameters.length() > 0)) {
String variabledResolvedParams = Util.replaceMacro(optionalMkviewParameters, this.variableResolver);
cmd.addTokenized(variabledResolvedParams);
isOptionalParamContainsHost = optionalMkviewParameters.contains("-host");
}
if (!isOptionalParamContainsHost) {
cmd.add(viewPath);
}
launcher.run(cmd.toCommandArray(), null, null, null);
}
/**
* for dynamic views : viewPath == viewTag
*/
public void mkview(String viewPath, String viewTag, String streamSelector, String defaultStorageDir) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("mkview");
if (streamSelector != null) {
cmd.add("-stream");
cmd.add(streamSelector);
}
cmd.add("-tag");
cmd.add(viewTag);
boolean isOptionalParamContainsHost = false;
if (StringUtils.isNotEmpty(optionalMkviewParameters)) {
String variabledResolvedParams = Util.replaceMacro(optionalMkviewParameters, this.variableResolver);
cmd.addTokenized(variabledResolvedParams);
isOptionalParamContainsHost = optionalMkviewParameters.contains("-host");
}
// add the default storage directory only if gpath/hpath are not set (only for windows)
if (!isOptionalParamContainsHost && StringUtils.isNotEmpty(defaultStorageDir)) {
String separator = PathUtil.fileSepForOS(getLauncher().getLauncher().isUnix());
String viewStorageDir = defaultStorageDir + separator + viewTag;
String base = viewStorageDir;
FilePath fp = new FilePath(getLauncher().getLauncher().getChannel(), viewStorageDir);
int i = 1;
while (fp.exists()) {
viewStorageDir = base + "." + i++;
fp = new FilePath(getLauncher().getLauncher().getChannel(), viewStorageDir);
if (i == Integer.MAX_VALUE) {
throw new IOException("Cannot determine a view storage dir.");
}
}
cmd.add(viewStorageDir);
}
launcher.run(cmd.toCommandArray(), null, null, null);
}
public void mountVobs() throws IOException, InterruptedException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("mount");
cmd.add("-all");
try {
launcher.run(cmd.toCommandArray(), null, baos, null);
} catch (IOException ex) {
logRedundantCleartoolError(cmd.toCommandArray(), ex);
} finally {
baos.close();
}
}
private List<String> parseListOutput(Reader consoleReader, boolean onlyStarMarked) throws IOException {
List<String> views = new ArrayList<String>();
BufferedReader reader = new BufferedReader(consoleReader);
String line = reader.readLine();
while (line != null) {
Matcher matcher = viewListPattern.matcher(line);
if (matcher.find() && matcher.groupCount() == 3) {
if ((!onlyStarMarked) || (onlyStarMarked && matcher.group(1).equals("*"))) {
String vob = matcher.group(2);
int pos = Math.max(vob.lastIndexOf('\\'), vob.lastIndexOf('/'));
if (pos != -1) {
vob = vob.substring(pos + 1);
}
views.add(vob);
}
}
line = reader.readLine();
}
reader.close();
return views;
}
public void setBaselinePromotionLevel(String baselineName, DefaultPromotionLevel promotionLevel) throws IOException, InterruptedException {
setBaselinePromotionLevel(baselineName, promotionLevel.toString());
}
public void setBaselinePromotionLevel(String baselineName, String promotionLevel) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("chbl");
cmd.add("-c");
cmd.add("Hudson set baseline to promotion level " + promotionLevel);
cmd.add("-level");
cmd.add(promotionLevel);
cmd.add(baselineName);
runAndProcessOutput(cmd, null, null, false, null);
}
public String pwv(String viewPath) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("pwv");
cmd.add("-root");
FilePath vp = getRootViewPath(launcher).child(viewPath);
if (vp.exists()) {
return runAndProcessOutput(cmd, null, vp, false, null);
} else {
return null;
}
}
public void rebaseDynamic(String viewTag, String baseline) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("rebase");
cmd.add("-baseline", baseline);
cmd.add("-view", viewTag);
cmd.add("-complete");
cmd.add("-force");
launcher.run(cmd.toCommandArray(), null, null, null);
}
public void recommendBaseline(String streamSelector) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("chstream");
cmd.add("-rec");
cmd.add("-def");
cmd.add(streamSelector);
launcher.run(cmd.toCommandArray(), null, null, null);
}
public void rmview(String viewPath) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("rmview");
cmd.add("-force");
cmd.add(viewPath);
FilePath workspace = launcher.getWorkspace();
String output = runAndProcessOutput(cmd, null, workspace, false, null);
if (output.contains("cleartool: Error")) {
throw new IOException("Failed to remove view: " + output);
}
FilePath viewFilePath = workspace.child(viewPath);
if (viewFilePath.exists()) {
launcher.getListener().getLogger().println("Removing view folder as it was not removed when the view was removed.");
viewFilePath.deleteRecursive();
}
}
public void rmviewtag(String viewTag) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("rmview");
cmd.add("-force");
cmd.add("-tag");
cmd.add(viewTag);
String output = runAndProcessOutput(cmd, null, null, false, null);
if (output.contains("cleartool: Error")) {
throw new IOException("Failed to remove view tag: " + output);
}
}
public void rmtag(String viewTag) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("rmtag");
cmd.add("-view");
cmd.add(viewTag);
String output = runAndProcessOutput(cmd, null, null, false, null);
if (output.contains("cleartool: Error")) {
throw new IOException("Failed to remove view tag: " + output);
}
}
public void rmviewUuid(String viewUuid) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("rmview");
cmd.add("-force");
cmd.add("-avobs");
cmd.add("-uuid");
cmd.add(viewUuid);
String output = runAndProcessOutput(cmd, null, null, false, null);
if (output.contains("cleartool: Error")) {
throw new IOException("Failed to remove view: " + output);
}
}
protected String runAndProcessOutput(ArgumentListBuilder cmd, InputStream in, FilePath workFolder, boolean catchExceptions, List<IOException> exceptions)
throws IOException, InterruptedException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
launcher.run(cmd.toCommandArray(), in, baos, workFolder);
} catch (IOException e) {
if (!catchExceptions) {
throw e;
} else {
exceptions.add(e);
}
}
BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(baos.toByteArray())));
baos.close();
String line = reader.readLine();
StringBuilder builder = new StringBuilder();
while (line != null) {
if (builder.length() > 0) {
builder.append("\n");
}
builder.append(line);
line = reader.readLine();
}
reader.close();
return builder.toString();
}
/**
* To set the config spec of a snapshot view, you must be in or under the snapshot view root directory.
*
* @see http://www.ipnom.com/ClearCase-Commands/setcs.html
*/
@Override
public void setcs(String viewPath, SetcsOption option, String configSpec) throws IOException, InterruptedException {
setcs(null, viewPath, option, configSpec);
}
private void setcs(String viewTag, String viewPath, SetcsOption option, String configSpec) throws IOException, InterruptedException {
if (option == SetcsOption.CONFIGSPEC) {
Validate.notNull(configSpec, "Using option CONFIGSPEC, you must provide a non-null config spec");
} else {
Validate.isTrue(configSpec == null, "Not using option CONFIGSPEC, you must provide a null config spec");
}
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("setcs");
if (viewTag != null) {
cmd.add("-tag");
cmd.add(viewTag);
}
String optionStr = getOption(option);
if (optionStr != null) {
cmd.add(optionStr);
}
FilePath configSpecFile = null;
if (option == SetcsOption.CONFIGSPEC) {
configSpecFile = launcher.getWorkspace().createTextTempFile("configspec", ".txt", configSpec);
cmd.add(PathUtil.convertPathForOS(configSpecFile.absolutize().getRemote(), launcher.getLauncher().isUnix()));
}
FilePath workingDirectory = null;
if (viewPath != null) {
workingDirectory = new FilePath(getRootViewPath(launcher), viewPath);
}
String output = runAndProcessOutput(cmd, new ByteArrayInputStream("yes".getBytes()), workingDirectory, false, null);
if (configSpecFile != null) {
configSpecFile.delete();
}
if (output.contains("cleartool: Warning: An update is already in progress for view")) {
throw new IOException("View update failed: " + output);
}
}
/**
* To set the config spec of a snapshot view, you must be in or under the snapshot view root directory.
*
* @see http://www.ipnom.com/ClearCase-Commands/setcs.html
*/
public void setcsCurrent(String viewPath) throws IOException, InterruptedException {
setcs(viewPath, SetcsOption.CURRENT, null);
}
/**
* Synchronize the dynamic view with the latest recommended baseline for the stream. 1. Set the config spec on the
* view (Removed call to chstream - based on
* http://www.nabble.com/-clearcase-plugin--Use-of-chstream--generate-is-not-necessary-td25118511.html
*/
public void setcsTag(String viewTag, SetcsOption option, String configSpec) throws IOException, InterruptedException {
setcs(viewTag, null, option, configSpec);
}
public void startView(String viewTags) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("startview");
cmd.addTokenized(viewTags);
launcher.run(cmd.toCommandArray(), null, null, null);
}
public void unlock(String comment, String objectSelector) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("unlock");
cmd.add(objectSelector);
launcher.run(cmd.toCommandArray(), null, null, null);
}
public void unregisterView(String uuid) throws IOException, InterruptedException {
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("unregister");
cmd.add("-view");
cmd.add("-uuid");
cmd.add(uuid);
String output = runAndProcessOutput(cmd, null, null, false, null);
if (output.contains("cleartool: Error")) {
throw new IOException("Failed to unregister view: " + output);
}
}
@Override
public void update(String viewPath, String[] loadRules) throws IOException, InterruptedException {
FilePath filePath = getLauncher().getWorkspace().child(viewPath);
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("update");
cmd.add("-force");
cmd.add("-overwrite");
cmd.add("-log", "NUL");
if (!ArrayUtils.isEmpty(loadRules)) {
cmd.add("-add_loadrules");
for (String loadRule : loadRules) {
cmd.add(fixLoadRule(loadRule));
}
}
String output = runAndProcessOutput(cmd, new ByteArrayInputStream("yes".getBytes()), filePath, false, null);
if (output.contains("cleartool: Warning: An update is already in progress for view")) {
throw new IOException("View update failed: " + output);
}
}
}