/** * The MIT License * * Copyright (c) 2007-2010, 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.ucm; import static hudson.plugins.clearcase.util.OutputFormat.COMMENT; import static hudson.plugins.clearcase.util.OutputFormat.LINEEND; 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.action.UcmDynamicCheckoutAction; import hudson.plugins.clearcase.history.Filter; import hudson.plugins.clearcase.history.HistoryEntry; import hudson.scm.ChangeLogSet.Entry; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.TimeZone; public class FreezeCodeUcmHistoryAction extends UcmHistoryAction { private static final String BASELINE_NAME = "hudson_poll_"; private static final String BASELINE_COMMENT = "hudson_poll_"; private final AbstractBuild<?, ?> build; private final String viewDrive; private final String stream; public FreezeCodeUcmHistoryAction(ClearTool cleartool, boolean useDynamicView, Filter filter, String stream, String viewDrive, AbstractBuild<?, ?> build, ClearCaseUCMSCMRevisionState oldBaseline, ClearCaseUCMSCMRevisionState newBaseline) { super(cleartool, useDynamicView, filter, oldBaseline, newBaseline); this.build = build; this.stream = stream; this.viewDrive = viewDrive; } @Override public List<? extends Entry> getChanges(Date time, String viewPath, String viewName, String[] branchNames, String[] viewPaths) throws IOException, InterruptedException { List<HistoryEntry> entries = new ArrayList<HistoryEntry>(); // get latest baselines on the configured stream (set as an action on the build by the checkout operation) ClearCaseDataAction latestBaselinesAction = build.getAction(ClearCaseDataAction.class); List<Baseline> latestBlsOnConfiguredStream = latestBaselinesAction.getLatestBlsOnConfiguredStream(); // find the previous build running on the same stream ClearCaseDataAction clearcaseDataAction = null; Run<?, ?> previousBuild = build.getPreviousBuild(); while (previousBuild != null && clearcaseDataAction == null) { clearcaseDataAction = previousBuild.getAction(ClearCaseDataAction.class); if (clearcaseDataAction != null && !(clearcaseDataAction.getStream().equals(getStream()))) { clearcaseDataAction = null; previousBuild = previousBuild.getPreviousBuild(); } } // get previous build baselines (set as an action on the previous build by the checkout operation) List<Baseline> previousBuildBls = null; if (clearcaseDataAction != null) { cleartool.getLauncher().getListener().getLogger().println( "Checking changes by comparing this build and the last build (" + previousBuild.getNumber() + ") that ran on stream " + getStream()); previousBuildBls = clearcaseDataAction.getLatestBlsOnConfiguredStream(); } else { cleartool.getLauncher().getListener().getLogger().println("Found no previous build that ran on stream " + getStream()); } // compare if (latestBlsOnConfiguredStream != null && previousBuildBls != null) { // calculate changed versions List<String> changedVerionsList = getChangedVersions(latestBlsOnConfiguredStream, previousBuildBls); // get HistoryEntry list out of changed version entries = translateChangedVersionsToEnteries(changedVerionsList); } List<HistoryEntry> filtered = filterEntries(entries); List<? extends Entry> changelog = buildChangelog(viewName, filtered); return changelog; } @Override public boolean hasChanges(Date time, String viewPath, String viewTag, String[] branchNames, String[] viewPaths) throws IOException, InterruptedException { // make baseline on the configured stream. SimpleDateFormat formatter = new SimpleDateFormat("d-MMM-yy_HH_mm_ss", Locale.US); formatter.setTimeZone(TimeZone.getTimeZone("UTC")); String dateStr = formatter.format(new Date()).toLowerCase(); cleartool.mkbl((BASELINE_NAME + dateStr), UcmDynamicCheckoutAction.getConfiguredStreamViewName(build.getProject().getName(), getStream()), (BASELINE_COMMENT + dateStr), false, false, null, null, null); // get latest baselines on the configured stream List<Baseline> latestBlsOnConfgiuredStream = UcmCommon.getLatestBlsWithCompOnStream(cleartool, getStream(), UcmDynamicCheckoutAction.getConfiguredStreamViewName(build.getProject().getName(), getStream())); // find the previous build running on the same stream Run<?, ?> previousBuild = build.getPreviousBuild(); ClearCaseDataAction clearcaseDataAction = previousBuild.getAction(ClearCaseDataAction.class); // get previous build baselines (set as an action on the previous build by the checkout operation) List<Baseline> previousBuildBls = null; if (clearcaseDataAction != null) previousBuildBls = clearcaseDataAction.getLatestBlsOnConfiguredStream(); // check if any baselines added/removed/changed if (latestBlsOnConfgiuredStream != null && previousBuildBls != null) { if (latestBlsOnConfgiuredStream.size() != previousBuildBls.size()) return true; for (Baseline blCurr : latestBlsOnConfgiuredStream) { boolean foundBl = false; for (Baseline blPrev : previousBuildBls) { if (blCurr.getBaselineName().equals(blPrev.getBaselineName())) { foundBl = true; break; } } if (!foundBl) return true; } } return false; } private List<HistoryEntry> translateChangedVersionsToEnteries(List<String> changedVerionsList) throws IOException, InterruptedException { List<HistoryEntry> entries = new ArrayList<HistoryEntry>(); StringBuilder entriesDesc = new StringBuilder(); // build output that parseLsHistory can read... for (String version : changedVerionsList) { String versionDesc = UcmCommon.getVersionDescription(cleartool, version, getHistoryFormatHandler().getFormat() + COMMENT + LINEEND); entriesDesc.append(versionDesc + "\n"); } // call parseLsHistory in order to create the HistoryEntry list BufferedReader buffReader = new BufferedReader(new StringReader(entriesDesc.toString())); try { parseLsHistory(buffReader, entries); } catch (ParseException e) { throw new IOException(e.getMessage()); } return entries; } private List<String> getChangedVersions(List<Baseline> newBls, List<Baseline> oldBls) throws IOException, InterruptedException { List<String> changedVersionList = new ArrayList<String>(); // compare baselines for (Baseline blDesc : newBls) { // ignore read-only components if (!blDesc.getComponentDesc().isModifiable()) continue; String previousBl = getBaseLineNameForComponent(oldBls, blDesc.getComponentName()); // check if baselines changed if (previousBl != null && !previousBl.equals(blDesc.getBaselineName())) { String viewName = UcmDynamicCheckoutAction.getConfiguredStreamViewName(build.getProject().getName(), getStream()); // run diffbl List<String> changedVersionListPerBl = UcmCommon.getDiffBlVersions(cleartool, viewDrive + "/" + viewName, previousBl, blDesc .getBaselineName()); changedVersionList.addAll(changedVersionListPerBl); } } return changedVersionList; } private String getBaseLineNameForComponent(List<Baseline> baselineList, String compName) { for (Baseline blDesc : baselineList) { if (UcmCommon.getNoVob(blDesc.getComponentName()).equals(UcmCommon.getNoVob(compName))) return blDesc.getBaselineName(); } return null; } public String getStream() { return stream; } }