Skip to content

Commit

Permalink
[JENKINS-16122] Revamped parsing update file to support properly
Browse files Browse the repository at this point in the history
distributed builds.
  • Loading branch information
Vlatombe committed Jul 7, 2013
1 parent 78ae144 commit a148d53
Show file tree
Hide file tree
Showing 18 changed files with 305 additions and 226 deletions.
18 changes: 5 additions & 13 deletions src/main/java/hudson/plugins/clearcase/AbstractClearCaseScm.java
Expand Up @@ -203,7 +203,6 @@ public static ChangeSetLevel defaultLevel() {
private boolean recreateView;
private String viewPath;
private ChangeSetLevel changeset;
private String updtFileName;
@Deprecated
private transient ViewStorageFactory viewStorageFactory;
private ViewStorage viewStorage;
Expand Down Expand Up @@ -661,28 +660,29 @@ public boolean checkout(AbstractBuild build, Launcher launcher, FilePath workspa

if (computeChangeLogBeforeCheckout) {
returnValue = saveChangeLog(build, launcher, listener, changelogFile, clearToolLauncher, variableResolver, saveChangeLogAction,
coNormalizedViewName, returnValue);
coNormalizedViewName, returnValue, null);
}
// --- CHECKOUT ---
if (!checkoutAction.checkout(launcher, workspace, coNormalizedViewName)) {
throw new AbortException();
}
if (computeChangeLogAfterCheckout) {
setUpdtFileName(checkoutAction.getUpdtFileName());
FilePath updtFile = checkoutAction.getUpdtFile();
returnValue = saveChangeLog(build, launcher, listener, changelogFile, clearToolLauncher, variableResolver, saveChangeLogAction,
coNormalizedViewName, returnValue);
coNormalizedViewName, returnValue, updtFile);
}

return returnValue;
}

private boolean saveChangeLog(AbstractBuild build, Launcher launcher, BuildListener listener, File changelogFile, ClearToolLauncher clearToolLauncher,
VariableResolver<String> variableResolver, SaveChangeLogAction saveChangeLogAction, String coNormalizedViewName, boolean returnValue)
VariableResolver<String> variableResolver, SaveChangeLogAction saveChangeLogAction, String coNormalizedViewName, boolean returnValue, FilePath updtFile)
throws IOException, InterruptedException {
List<? extends ChangeLogSet.Entry> changelogEntries;
@SuppressWarnings("unchecked") Run prevBuild = build.getPreviousBuild();
Date lastBuildTime = getBuildTime(prevBuild);
HistoryAction historyAction = createHistoryAction(variableResolver, clearToolLauncher, build, /*getUseRecurseForChangelog()*/ false);
historyAction.setUpdtFile(updtFile);
changelogEntries = historyAction.getChanges(lastBuildTime, getViewPath(variableResolver), coNormalizedViewName, getBranchNames(variableResolver), getViewPaths(variableResolver, build, launcher, false));
// Save change log
if (CollectionUtils.isEmpty(changelogEntries)) {
Expand Down Expand Up @@ -956,12 +956,4 @@ protected void setExtendedViewPath(VariableResolver<String> variableResolver, Cl
Logger.getLogger(AbstractClearCaseScm.class.getName()).log(Level.WARNING, "Exception when running 'cleartool pwv'", e);
}
}

public String getUpdtFileName() {
return updtFileName;
}

public void setUpdtFileName(String updtFileName) {
this.updtFileName = updtFileName;
}
}
2 changes: 1 addition & 1 deletion src/main/java/hudson/plugins/clearcase/ClearCaseSCM.java
Expand Up @@ -356,7 +356,7 @@ protected HistoryAction createHistoryAction(VariableResolver<String> variableRes
boolean useRecurse) throws IOException, InterruptedException {
ClearTool ct = createClearTool(variableResolver, launcher);
BaseHistoryAction action = new BaseHistoryAction(ct, isUseDynamicView(), configureFilters(variableResolver, build, launcher.getLauncher()),
getChangeset(), useRecurse, getDescriptor().getLogMergeTimeWindow(), getUpdtFileName());
getChangeset(), useRecurse, getDescriptor().getLogMergeTimeWindow());

setExtendedViewPath(variableResolver, ct, action);

Expand Down
23 changes: 21 additions & 2 deletions src/main/java/hudson/plugins/clearcase/ClearTool.java
Expand Up @@ -396,8 +396,19 @@ public static enum DefaultPromotionLevel {
* @param viewPath The view path name (relative to the workspace)
* @param option The type of setcs that needs to be performed
* @param configSpec the name of the file containing a config spec
* @deprecated use setcs2 instead.
*/
@Deprecated
void setcs(String viewPath, SetcsOption option, String configSpec) throws IOException, InterruptedException;

/**
* Sets the config spec of the view
*
* @param viewPath The view path name (relative to the workspace)
* @param option The type of setcs that needs to be performed
* @param configSpec the name of the file containing a config spec
*/
CleartoolUpdateResult setcs2(String viewPath, SetcsOption current, String configSpec) throws IOException, InterruptedException;

/**
* Synchronizes the Dynamic UCM view with the streams recommended baseline
Expand Down Expand Up @@ -442,11 +453,19 @@ public static enum SetcsOption {
*
* @param viewPath the name of the view
* @param loadRules optional load rules, null if not used.
* @deprecated use update2 instead
*/
@Deprecated
void update(String viewPath, String[] loadRules) throws IOException, InterruptedException;
/**
* Updates the elements in the view
*
* @param viewPath the name of the view
* @param loadRules optional load rules, null if not used.
* @return A tuple given access to the update logs and warnings returned
*/
CleartoolUpdateResult update2(String viewPath, String[] loadRules) throws IOException, InterruptedException;

String getUpdtFileName();

CleartoolVersion version() throws IOException, InterruptedException, CleartoolVersionParsingException;

boolean doesSetcsSupportOverride() throws IOException, InterruptedException;
Expand Down
129 changes: 63 additions & 66 deletions src/main/java/hudson/plugins/clearcase/ClearToolExec.java
Expand Up @@ -29,6 +29,7 @@
import hudson.Util;
import hudson.plugins.clearcase.util.DeleteOnCloseFileInputStream;
import hudson.plugins.clearcase.util.PathUtil;
import hudson.remoting.VirtualChannel;
import hudson.util.ArgumentListBuilder;
import hudson.util.IOUtils;
import hudson.util.VariableResolver;
Expand All @@ -52,6 +53,7 @@
import java.util.Locale;
import java.util.Properties;
import java.util.TimeZone;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand All @@ -62,19 +64,21 @@

public abstract class ClearToolExec implements ClearTool {

private static final CleartoolVersion CLEARTOOL_VERSION_7 = new CleartoolVersion("7");
private static final Pattern PATTERN_UNABLE_TO_REMOVE_DIRECTORY_NOT_EMPTY = Pattern
.compile("cleartool: Error: Unable to remove \"(.*)\": Directory not empty.");

private transient Pattern viewListPattern;
private transient CleartoolVersion version;

protected ClearToolLauncher launcher;
protected VariableResolver<String> variableResolver;
protected String optionalMkviewParameters;
protected String updtFileName;
private static final Logger LOGGER = Logger.getLogger(ClearToolExec.class.getName());
private static final CleartoolVersion CLEARTOOL_VERSION_7 = new CleartoolVersion("7");
private static final Pattern PATTERN_UNABLE_TO_REMOVE_DIRECTORY_NOT_EMPTY = Pattern.compile("cleartool: Error: Unable to remove \"(.*)\": Directory not empty.");
private static final Pattern PATTERN_VIEW_ACCESS_PATH = Pattern.compile("View server access path: (.*)");
private static final Pattern PATTERN_VIEW_UUID = Pattern.compile("View uuid: (.*)");


private transient Pattern viewListPattern;
private transient CleartoolVersion version;

protected ClearToolLauncher launcher;
protected VariableResolver<String> variableResolver;
protected String optionalMkviewParameters;
protected String updtFileName;

public ClearToolExec(VariableResolver<String> variableResolver, ClearToolLauncher launcher, String optionalMkviewParameters) {
this.variableResolver = variableResolver;
this.launcher = launcher;
Expand Down Expand Up @@ -280,26 +284,21 @@ public Properties getViewData(String viewTag) throws IOException, InterruptedExc
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, true);
// 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) {
if (!exceptions.isEmpty()) {
if (!output.contains("No matching entries found for view")) {
throw exceptions.get(0);
}
String[] lines = output.split("\n");
for (String line : lines) {
Matcher matcher = uuidPattern.matcher(line);
Matcher matcher = PATTERN_VIEW_UUID.matcher(line);
if (matcher.find() && matcher.groupCount() == 1)
resPrp.put("UUID", matcher.group(1));

matcher = globalPathPattern.matcher(line);
matcher = PATTERN_VIEW_ACCESS_PATH.matcher(line);
if (matcher.find() && matcher.groupCount() == 1)
resPrp.put("STORAGE_DIR", matcher.group(1));
}
Expand Down Expand Up @@ -824,7 +823,10 @@ protected String runAndProcessOutput(ArgumentListBuilder cmd, InputStream in, Fi
}
exceptions.add(e);
}
BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(baos.toByteArray())));
byte[] byteArray = baos.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
InputStreamReader inputStreamReader = new InputStreamReader(byteArrayInputStream);
BufferedReader reader = new BufferedReader(inputStreamReader);
baos.close();
String line = reader.readLine();
StringBuilder builder = new StringBuilder();
Expand All @@ -845,11 +847,16 @@ protected String runAndProcessOutput(ArgumentListBuilder cmd, InputStream in, Fi
* @see http://www.ipnom.com/ClearCase-Commands/setcs.html
*/
@Override
@Deprecated
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 {
public CleartoolUpdateResult setcs2(String viewPath, SetcsOption option, String configSpec) throws IOException, InterruptedException {
return setcs(null, viewPath, option, configSpec);
}

private CleartoolUpdateResult 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 {
Expand Down Expand Up @@ -877,17 +884,18 @@ private void setcs(String viewTag, String viewPath, SetcsOption option, String c
if (viewPath != null) {
workingDirectory = new FilePath(getRootViewPath(launcher), viewPath);
}
getLauncher().getListener().getLogger().println("Running cleartool setcs, this operation may take a while");
PrintStream logger = getLauncher().getListener().getLogger();
logger.println("Running cleartool setcs, this operation may take a while");
String output = runAndProcessOutput(cmd, new ByteArrayInputStream("yes".getBytes()), workingDirectory, false, null, false);
if (configSpecFile != null) {
configSpecFile.delete();
}

processUpdtFileName(output);

if (output.contains("cleartool: Warning: An update is already in progress for view")) {
throw new IOException("View update failed: " + output);
}
FilePath logFile = extractUpdtFile(launcher.getChannel(), output);
displayLogFile(logger, logFile);
return new CleartoolUpdateResult(logFile);
}

/**
Expand All @@ -896,7 +904,7 @@ private void setcs(String viewTag, String viewPath, SetcsOption option, String c
* @see http://www.ipnom.com/ClearCase-Commands/setcs.html
*/
public void setcsCurrent(String viewPath) throws IOException, InterruptedException {
setcs(viewPath, SetcsOption.CURRENT, null);
setcs2(viewPath, SetcsOption.CURRENT, null);
}

/**
Expand Down Expand Up @@ -937,16 +945,20 @@ public void unregisterView(String uuid) throws IOException, InterruptedException

}

@Deprecated
@Override
public void update(String viewPath, String[] loadRules) throws IOException, InterruptedException {
update2(viewPath, loadRules);
}

@Override
public CleartoolUpdateResult update2(String viewPath, String[] loadRules) throws IOException, InterruptedException {
FilePath workspace = getLauncher().getWorkspace();
FilePath filePath = workspace.child(viewPath);
FilePath logFile = createLogFilename(workspace);
ArgumentListBuilder cmd = new ArgumentListBuilder();
cmd.add("update");
cmd.add("-force");
cmd.add("-overwrite");
cmd.add("-log", logFile.getRemote());
if (!ArrayUtils.isEmpty(loadRules)) {
cmd.add("-add_loadrules");
for (String loadRule : loadRules) {
Expand All @@ -957,7 +969,16 @@ public void update(String viewPath, String[] loadRules) throws IOException, Inte
PrintStream logger = getLauncher().getListener().getLogger();
logger.println("Running cleartool update, this operation may take a while");
String output = runAndProcessOutput(cmd, new ByteArrayInputStream("yes\nyes\n".getBytes()), filePath, true, exceptions, false);
if (logFile.exists()) {
FilePath logFile = extractUpdtFile(workspace.getChannel(), output);
displayLogFile(logger, logFile);
if (!exceptions.isEmpty()) {
handleHijackedDirectoryCCBug(viewPath, filePath, exceptions, output);
}
return new CleartoolUpdateResult(logFile);
}

private void displayLogFile(PrintStream logger, FilePath logFile) throws IOException, InterruptedException {
if (logFile != null && logFile.exists()) {
InputStream is = null;
InputStreamReader reader = null;
BufferedReader rd = null;
Expand All @@ -975,13 +996,8 @@ public void update(String viewPath, String[] loadRules) throws IOException, Inte
IOUtils.closeQuietly(is);
}
}
if (!exceptions.isEmpty()) {
handleHijackedDirectoryCCBug(viewPath, filePath, exceptions, output);
} else {
processUpdtFileName(output);
}
}

@Override
public CleartoolVersion version() throws IOException, InterruptedException, CleartoolVersionParsingException {
if (version == null) {
Expand All @@ -1004,39 +1020,20 @@ public CleartoolVersion version() throws IOException, InterruptedException, Clea
return version;
}

private FilePath createLogFilename(FilePath workspace) throws IOException, InterruptedException {
Date now = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmssZ");
FilePath updateLogsDir = workspace.child("updatelogs");
if (!updateLogsDir.exists()) {
updateLogsDir.mkdirs();
}
try {
updateLogsDir.deleteContents();
} catch (IOException e) {
launcher.getListener().getLogger().println("[WARN] Couldn't delete content of " + updateLogsDir);
}
FilePath logFile = updateLogsDir.child(sdf.format(now) + ".updt");
return logFile;
}

private void processUpdtFileName(String output) {
private FilePath extractUpdtFile(VirtualChannel channel, String output) {
Pattern updtPattern = Pattern.compile("Log has been written to \"(.*)\".*");
String[] lines = output.split("\n");
String fileName = null;
for (String line : lines) {
Matcher matcher = updtPattern.matcher(line);
if (matcher.find() && matcher.groupCount() == 1) {
setUpdtFileName(matcher.group(1));
fileName = matcher.group(1);
}
}
}

public void setUpdtFileName(String updtFileName) {
this.updtFileName = updtFileName;
}

public String getUpdtFileName() {
return updtFileName;
if (fileName == null) {
return null;
}
return new FilePath(channel, fileName);
}

/**
Expand Down Expand Up @@ -1070,10 +1067,10 @@ private void handleHijackedDirectoryCCBug(String viewPath, FilePath filePath, Li
} else {
// We forced some hijacked directory removal, relaunch update
logger.println("Relaunching update after removal of hijacked directories");
update(viewPath, null);
update2(viewPath, null);
}
}

@Override
public boolean doesSetcsSupportOverride() throws IOException, InterruptedException {
try {
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/hudson/plugins/clearcase/ClearToolLauncher.java
Expand Up @@ -27,6 +27,7 @@
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.TaskListener;
import hudson.remoting.VirtualChannel;

import java.io.IOException;
import java.io.InputStream;
Expand Down Expand Up @@ -89,6 +90,12 @@ public interface ClearToolLauncher {
* @return the Hudsonlauncher
*/
Launcher getLauncher();

/**
* Returns the virtual channel this launcher is using
* @return
*/
VirtualChannel getChannel();

String getCmdString(String[] cmd);

Expand Down

0 comments on commit a148d53

Please sign in to comment.