/**
* The MIT License
*
* Copyright (c) 2007-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Erik Ramfelt,
* Henrik Lynggaard, Peter Liljenberg, Andrew Bayer
*
* 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.action;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.Run;
import hudson.plugins.clearcase.Baseline;
import hudson.plugins.clearcase.ClearCaseDataAction;
import hudson.plugins.clearcase.ClearTool;
import hudson.plugins.clearcase.ClearTool.SetcsOption;
import hudson.plugins.clearcase.ucm.UcmCommon;
import java.io.IOException;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
/**
* Check out action for dynamic views. This will not update any files from the repository as it is a dynamic view. It
* only makes sure the view is started as config specs don't exist in UCM
*/
public class UcmDynamicCheckoutAction implements CheckOutAction {
private static final String CONFIGURED_STREAM_VIEW_SUFFIX = "_hudson_view";
private static final String BUILD_STREAM_PREFIX = "hudson_stream.";
private static final String BASELINE_NAME = "hudson_co_";
private static final String BASELINE_COMMENT = "hudson_co_";
private ClearTool cleartool;
private String stream;
private boolean createDynView;
private String winDynStorageDir;
private String unixDynStorageDir;
private AbstractBuild build;
private boolean freezeCode;
private boolean recreateView;
public UcmDynamicCheckoutAction(ClearTool cleartool, String stream, boolean createDynView, String winDynStorageDir, String unixDynStorageDir,
AbstractBuild build, boolean freezeCode, boolean recreateView) {
super();
this.cleartool = cleartool;
this.stream = stream;
this.createDynView = createDynView;
this.winDynStorageDir = winDynStorageDir;
this.unixDynStorageDir = unixDynStorageDir;
this.build = build;
this.freezeCode = freezeCode;
this.recreateView = recreateView;
}
public boolean checkout(Launcher launcher, FilePath workspace, String viewTag) throws IOException, InterruptedException {
// add stream to data action (to be used by ClearCase report)
ClearCaseDataAction dataAction = build.getAction(ClearCaseDataAction.class);
if (dataAction != null) {
// sync the project in order to allow other builds to safely check if there is
// already a build running on the same stream
synchronized (build.getProject()) {
dataAction.setStream(stream);
}
}
if (createDynView) {
if (freezeCode) {
checkoutCodeFreeze(viewTag);
} else {
prepareView(viewTag, stream);
cleartool.startView(viewTag);
cleartool.setcsTag(viewTag, SetcsOption.STREAM, null);
}
} else {
cleartool.startView(viewTag);
cleartool.setcsTag(viewTag, SetcsOption.STREAM, null);
}
return true;
}
public boolean checkoutCodeFreeze(String viewName) throws IOException, InterruptedException {
// validate no other build is running on the same stream
synchronized (build.getProject()) {
ClearCaseDataAction clearcaseDataAction = null;
Run previousBuild = build.getPreviousBuild();
while (previousBuild != null) {
clearcaseDataAction = previousBuild.getAction(ClearCaseDataAction.class);
if (previousBuild.isBuilding() && clearcaseDataAction != null && clearcaseDataAction.getStream().equals(stream))
throw new IOException("Can't run build on stream " + stream + " when build " + previousBuild.getNumber()
+ " is currently running on the same stream.");
previousBuild = previousBuild.getPreviousBuild();
}
}
// prepare stream and views
prepareBuildStreamAndViews(viewName, stream);
// make baselines
SimpleDateFormat formatter = new SimpleDateFormat("d-MMM-yy_HH_mm_ss", Locale.US);
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
String dateStr = formatter.format(build.getTimestamp().getTime()).toLowerCase();
cleartool.mkbl((BASELINE_NAME + dateStr), getConfiguredStreamViewName(), (BASELINE_COMMENT + dateStr), false, false, null, null, null);
// get latest baselines on the configured stream
List<Baseline> latestBlsOnConfgiuredStream = UcmCommon.getLatestBlsWithCompOnStream(cleartool, stream,
getConfiguredStreamViewName());
// fix Not labeled baselines
for (Baseline baseLineDesc : latestBlsOnConfgiuredStream) {
if (baseLineDesc.isNotLabeled() && baseLineDesc.getComponentDesc().isModifiable()) {
// if the base is not labeled create identical one
List<String> readWriteCompList = new ArrayList<String>();
readWriteCompList.add(baseLineDesc.getComponentDesc().getName());
List<Baseline> baseLineDescList = cleartool.mkbl((BASELINE_NAME
+ dateStr), getConfiguredStreamViewName(), (BASELINE_COMMENT + dateStr), false, true, readWriteCompList, null, null);
String newBaseline = baseLineDescList.get(0).getBaselineName() + "@" + UcmCommon.getVob(baseLineDesc.getComponentDesc().getName());
baseLineDesc.setBaselineName(newBaseline);
}
}
// rebase build stream
UcmCommon.rebase(cleartool, viewName, latestBlsOnConfgiuredStream);
// add baselines to build - to be later used by getChange
ClearCaseDataAction dataAction = build.getAction(ClearCaseDataAction.class);
if (dataAction != null)
dataAction.setLatestBlsOnConfiguredStream(latestBlsOnConfgiuredStream);
return true;
}
private void prepareBuildStreamAndViews(String viewTag, String stream) throws IOException, InterruptedException {
// verify that view exists on the configured stream and start it
if (!cleartool.doesViewExist(getConfiguredStreamViewName())) {
String dynStorageDir = cleartool.getLauncher().getLauncher().isUnix() ? unixDynStorageDir : winDynStorageDir;
cleartool.mkview(null, getConfiguredStreamViewName(), stream, dynStorageDir);
}
cleartool.startView(getConfiguredStreamViewName());
// do we have build stream? if not create it
if (!cleartool.doesStreamExist(getBuildStream())) {
cleartool.mkstream(stream, getBuildStream());
}
// create view on build stream
prepareView(viewTag, getBuildStream());
}
private void prepareView(String viewTag, String stream) throws IOException, InterruptedException {
String dynStorageDir = cleartool.getLauncher().getLauncher().isUnix() ? unixDynStorageDir : winDynStorageDir;
if (cleartool.doesViewExist(viewTag)) {
if (recreateView) {
cleartool.rmviewtag(viewTag);
cleartool.mkview(null, viewTag, stream, dynStorageDir);
}
} else {
cleartool.mkview(null, viewTag, stream, dynStorageDir);
}
}
public static String getConfiguredStreamViewName(String jobName, String stream) {
jobName = jobName.replace(" ", "");
return UcmCommon.getNoVob(stream) + "_" + jobName + "_" + CONFIGURED_STREAM_VIEW_SUFFIX;
}
private String getConfiguredStreamViewName() {
return getConfiguredStreamViewName(build.getProject().getName(), stream);
}
/**
* @return unique build stream name
*/
private String getBuildStream() {
String jobName = build.getProject().getName().replace(" ", "");
return BUILD_STREAM_PREFIX + jobName + "." + stream;
}
@Override
public boolean isViewValid(Launcher launcher, FilePath workspace, String viewTag) throws IOException, InterruptedException {
if (cleartool.doesViewExist(viewTag)) {
cleartool.startView(viewTag);
return true;
}
return false;
}
}