@Override public void onRenamed(Item item, String oldName, String newName) { if (item instanceof AbstractProject) { AbstractProject p = Hudson.getInstance().getItemByFullName(newName, AbstractProject.class); if (p != null) { RunList builds = p.getBuilds(); for (Object build : builds) { if (build instanceof AbstractBuild) { Collection<Fingerprint> fingerprints = ((AbstractBuild) build).getBuildFingerprints(); for (Fingerprint f : fingerprints) { try { f.rename(oldName, newName); } catch (IOException e) { logger.log( Level.WARNING, "Failed to update fingerprint record " + f.getFileName() + " when " + oldName + " was renamed to " + newName, e); } } } } } } }
/*package*/ static Fingerprint load(File file) throws IOException { XmlFile configFile = getConfigFile(file); if (!configFile.exists()) return null; long start = 0; if (logger.isLoggable(Level.FINE)) start = System.currentTimeMillis(); try { Fingerprint f = (Fingerprint) configFile.read(); if (logger.isLoggable(Level.FINE)) logger.fine( "Loading fingerprint " + file + " took " + (System.currentTimeMillis() - start) + "ms"); if (f.facets == null) f.facets = new PersistedList<FingerprintFacet>(f); for (FingerprintFacet facet : f.facets) facet._setOwner(f); return f; } catch (IOException e) { if (file.exists() && file.length() == 0) { // Despite the use of AtomicFile, there are reports indicating that people often see // empty XML file, presumably either due to file system corruption (perhaps by sudden // power loss, etc.) or abnormal program termination. // generally we don't want to wipe out user data just because we can't load it, // but if the file size is 0, which is what's reported in HUDSON-2012, then it seems // like recovering it silently by deleting the file is not a bad idea. logger.log(Level.WARNING, "Size zero fingerprint. Disk corruption? " + configFile, e); file.delete(); return null; } logger.log(Level.WARNING, "Failed to load " + configFile, e); throw e; } }
/** Examines the file and returns true if a file was deleted. */ private boolean check(File fingerprintFile) { try { Fingerprint fp = Fingerprint.load(fingerprintFile); if (!fp.isAlive()) { fingerprintFile.delete(); return true; } } catch (IOException e) { logger.log(Level.WARNING, "Failed to process " + fingerprintFile, e); } return false; }
/** * Gets the dependency relationship from this build (as the source) and that project (as the * sink.) * * @return range of build numbers that represent which downstream builds are using this build. The * range will be empty if no build of that project matches this, but it'll never be null. */ public RangeSet getDownstreamRelationship(AbstractProject that) { RangeSet rs = new RangeSet(); FingerprintAction f = getAction(FingerprintAction.class); if (f == null) return rs; // look for fingerprints that point to this build as the source, and merge them all for (Fingerprint e : f.getFingerprints().values()) { if (upstreamCulprits) { // With upstreamCulprits, we allow downstream relationships // from intermediate jobs rs.add(e.getRangeSet(that)); } else { BuildPtr o = e.getOriginal(); if (o != null && o.is(this)) rs.add(e.getRangeSet(that)); } } return rs; }
/** * Gets the dependency relationship from this build (as the sink) and that project (as the * source.) * * @return Build number of the upstream build that feed into this build, or -1 if no record is * available. */ public int getUpstreamRelationship(AbstractProject that) { FingerprintAction f = getAction(FingerprintAction.class); if (f == null) return -1; int n = -1; // look for fingerprints that point to the given project as the source, and merge them all for (Fingerprint e : f.getFingerprints().values()) { if (upstreamCulprits) { // With upstreamCulprits, we allow upstream relationships // from intermediate jobs Fingerprint.RangeSet rangeset = e.getRangeSet(that); if (!rangeset.isEmpty()) { n = Math.max(n, rangeset.listNumbersReverse().iterator().next()); } } else { BuildPtr o = e.getOriginal(); if (o != null && o.belongsTo(that)) n = Math.max(n, o.getNumber()); } } return n; }