hudson.tasks.Fingerprinter Maven / Gradle / Ivy
package hudson.tasks;
import hudson.Launcher;
import hudson.model.Action;
import hudson.model.Build;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
import hudson.model.Fingerprint;
import hudson.model.Hudson;
import hudson.model.Project;
import hudson.model.Result;
import hudson.model.Fingerprint.BuildPtr;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.types.FileSet;
import org.kohsuke.stapler.StaplerRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.Set;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Records fingerprints of the specified files.
*
* @author Kohsuke Kawaguchi
*/
public class Fingerprinter extends Publisher {
/**
* Comma-separated list of files/directories to be fingerprinted.
*/
private final String targets;
/**
* Also record all the finger prints of the build artifacts.
*/
private final boolean recordBuildArtifacts;
public Fingerprinter(String targets, boolean recordBuildArtifacts) {
this.targets = targets;
this.recordBuildArtifacts = recordBuildArtifacts;
}
public String getTargets() {
return targets;
}
public boolean getRecordBuildArtifacts() {
return recordBuildArtifacts;
}
public boolean perform(Build build, Launcher launcher, BuildListener listener) {
listener.getLogger().println("Recording fingerprints");
Map record = new HashMap();
MessageDigest md5;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
// I don't think this is possible, but check anyway
e.printStackTrace(listener.error("MD5 not installed"));
build.setResult(Result.FAILURE);
return true;
}
if(targets.length()!=0)
record(build, md5, listener, record, targets);
if(recordBuildArtifacts) {
ArtifactArchiver aa = (ArtifactArchiver) build.getProject().getPublishers().get(ArtifactArchiver.DESCRIPTOR);
if(aa==null) {
// configuration error
listener.error("Build artifacts are supposed to be fingerprinted, but build artifact archiving is not configured");
build.setResult(Result.FAILURE);
return true;
}
record(build, md5, listener, record, aa.getArtifacts() );
}
build.getActions().add(new FingerprintAction(build,record));
return true;
}
private void record(Build build, MessageDigest md5, BuildListener listener, Map record, String targets) {
Project p = build.getProject();
FileSet src = new FileSet();
File baseDir = p.getWorkspace().getLocal();
src.setDir(baseDir);
src.setIncludes(targets);
byte[] buf = new byte[8192];
DirectoryScanner ds = src.getDirectoryScanner(new org.apache.tools.ant.Project());
for( String f : ds.getIncludedFiles() ) {
File file = new File(baseDir,f);
// consider the file to be produced by this build only if the timestamp
// is newer than when the build has started.
boolean produced = build.getTimestamp().getTimeInMillis() <= file.lastModified();
try {
md5.reset(); // technically not necessary, but hey, just to be safe
DigestInputStream in =new DigestInputStream(new FileInputStream(file),md5);
try {
while(in.read(buf)>0)
; // simply discard the input
} finally {
in.close();
}
Fingerprint fp = Hudson.getInstance().getFingerprintMap().getOrCreate(
produced?build:null, file.getName(), md5.digest());
if(fp==null) {
listener.error("failed to record fingerprint for "+file);
continue;
}
fp.add(build);
record.put(f,fp.getHashString());
} catch (IOException e) {
e.printStackTrace(listener.error("Failed to compute digest for "+file));
}
}
}
public Descriptor getDescriptor() {
return DESCRIPTOR;
}
public static final Descriptor DESCRIPTOR = new Descriptor(Fingerprinter.class) {
public String getDisplayName() {
return "Record fingerprints of files to track usage";
}
public String getHelpFile() {
return "/help/project-config/fingerprint.html";
}
public Publisher newInstance(StaplerRequest req) {
return new Fingerprinter(
req.getParameter("fingerprint_targets").trim(),
req.getParameter("fingerprint_artifacts")!=null);
}
};
/**
* Action for displaying fingerprints.
*/
public static final class FingerprintAction implements Action {
private final Build build;
private final Map record;
private transient WeakReference © 2015 - 2025 Weber Informatics LLC | Privacy Policy