try {
IValidationAdvisor.ComplianceLevel complianceLevel = options.getComplianceLevel();
if(complianceLevel == null)
complianceLevel = IValidationAdvisor.ComplianceLevel.PUPPET_2_7;
IPotentialProblemsAdvisor problemsAdvisor = options.getProblemsAdvisor();
if(problemsAdvisor == null)
problemsAdvisor = new DefaultPotentialProblemsAdvisor();
ppRunner.setUp(complianceLevel, problemsAdvisor);
rubyHelper.setUp();
}
catch(Exception e) {
addExceptionDiagnostic(diagnostics, "Internal Error: Exception while setting up diagnostics.", e);
return new BuildResult(rubyHelper.isRubyServicesAvailable()); // give up
}
ppRunner.configureEncoding(options.getEncodingProvider());
ppRunner.configureSearchPath(root, options.getSearchPath(), options.getEnvironment());
// get the configured search path
final PPSearchPath searchPath = ppRunner.getDefaultSearchPath();
// Modulefile processing
// Modulefiles must be processed first in order to figure out containers and container visibility.
final IPath rootPath = new Path(root.getAbsolutePath());
final IPath nodeRootPath = rootPath.append(NAME_OF_DIR_WITH_RESTRICTED_SCOPE);
// collect info in a structure
Multimap<ModuleName, MetadataInfo> moduleData = ArrayListMultimap.create();
for(File mdRoot : mdRoots) {
// load and remember all that loaded ok
File[] mdProvider = new File[1];
Metadata m;
try {
m = forge.createFromModuleDirectory(mdRoot, true, null, mdProvider, diagnostics);
}
catch(IOException e) {
addFileError(
diagnostics, mdProvider[0], mdRoot, "Can not parse file: " + e.getMessage(),
IValidationConstants.ISSUE__MODULEFILE_PARSE_ERROR);
m = null;
}
if(m == null)
worked(ticker, 1);
else {
File f = mdProvider[0];
ModuleName moduleName = m.getName();
if(options.isCheckModuleSemantics() && isOnPath(pathToFile(f.getAbsolutePath(), root), searchPath)) {
// remember the metadata and where it came from
// and if it represents a NODE as opposed to a regular MODULE
moduleData.put(
moduleName, new MetadataInfo(m, f, nodeRootPath.isPrefixOf(new Path(f.getAbsolutePath()))));
}
if(isValidationWanted(examinedFiles, f)) {
validateModuleMetadata(m, diagnostics, f, root, options, ticker.newChild(1));
}
else
worked(ticker, 1);
}
}
if(options.isCheckModuleSemantics()) {
for(ModuleName key : moduleData.keySet()) {
// check there is only one version of each module
Collection<MetadataInfo> versions = moduleData.get(key);
boolean redeclared = versions.size() > 1;
for(MetadataInfo info : versions) {
// processed dependencies for one version of a modulefile (in case of errors, there may not be as many ticks as
// originally requested)
// this ticks before the fact (but there is "one for the pot" left at the end),
// as this makes it easier to just do "continue" below.
worked(ticker, 1);
// skip checks for unwanted
final boolean shouldDiagnosticBeReported = isValidationWanted(examinedFiles, info.getFile());
// if(!) continue;
if(redeclared && shouldDiagnosticBeReported) {
addFileError(
diagnostics, info.getFile(), root, "Redefinition - equally named already exists",
IValidationConstants.ISSUE__MODULEFILE_REDEFINITION);
}
// Resolve all dependencies
for(Dependency d : info.getMetadata().getDependencies()) {
// check dependency name and version requirement
final ModuleName requiredName = d.getName();
if(requiredName == null) {
if(shouldDiagnosticBeReported)
addFileError(
diagnostics, info.getFile(), root, "Dependency without name",
IValidationConstants.ISSUE__MODULEFILE_DEPENDENCY_ERROR);
continue; // not meaningful to resolve this
// dependency
}
// find the best candidate (ignore the fact that there should just be one version of each
// module - there may be several, and one of the match).
// It is allowed to have modules without versions, they can only be matched by
// a dependency that does not have a version requirement.
//
Collection<MetadataInfo> candidates = moduleData.get(requiredName);
List<Version> candidateVersions = Lists.newArrayList();
List<MetadataInfo> unversioned = Lists.newArrayList();
if(candidates != null)
for(MetadataInfo mi : candidates) {
Version cv = mi.getMetadata().getVersion();
if(cv == null) {
unversioned.add(mi);
continue; // the (possibly) broken version
// is reported elsewhere
}
candidateVersions.add(cv);
}
// if the dependency has no version requirement use ">=0"
final VersionRange versionRequirement = d.getVersionRequirement();
if(versionRequirement == null) {
// find best match for >= 0 if there are candidates with versions
// the best will always win over unversioned.
if(candidateVersions.size() > 0) {
Collections.sort(candidateVersions);
Version best = candidateVersions.get(candidateVersions.size() - 1);
// get the matched MetaDataInfo as the resolution of the dependency
// and remember it
for(MetadataInfo mi : candidates) {
if(mi.getMetadata().getVersion().equals(best))
info.addResolvedDependency(d, mi);
}
}
// or there must be unversioned candidates
else if(unversioned.size() == 0)
if(shouldDiagnosticBeReported)
addFileDiagnostic(
diagnostics, (candidates.size() > 0
? Diagnostic.WARNING
: Diagnostic.ERROR), info.getFile(), root,
"Unresolved Dependency to: " + d.getName() + " (unversioned).",
IValidationConstants.ISSUE__MODULEFILE_UNSATISFIED_DEPENDENCY);
else {
// pick the first as resolution
// worry about ambiguity elsewhere
info.addResolvedDependency(d, unversioned.get(0));
}
}
else {
// there was a version requirement, it must match something with a version.
Version best = d.getVersionRequirement().findBestMatch(candidateVersions);
if(best == null) {
info.addUnresolvedDependency(d);
if(shouldDiagnosticBeReported)
addFileDiagnostic(
diagnostics,
(candidates.size() > 0
? Diagnostic.WARNING
: Diagnostic.ERROR),
info.getFile(),
root,
"Unresolved Dependency to: " + d.getName() + " version: " +
d.getVersionRequirement(),
IValidationConstants.ISSUE__MODULEFILE_UNSATISFIED_DEPENDENCY);
}
else {
// get the matched MetaDataInfo as the resolution of the dependency
// and remember it
for(MetadataInfo mi : candidates) {
if(mi.getMetadata().getVersion().equals(best))
info.addResolvedDependency(d, mi);
}
}
}
}
}
}
IPotentialProblemsAdvisor advisor = options.getProblemsAdvisor();
if(advisor != null && advisor.circularDependencyPreference().isWarningOrError()) {
ValidationPreference preference = options.getProblemsAdvisor().circularDependencyPreference();
checkCircularDependencies(moduleData, diagnostics, root);
for(MetadataInfo mi : moduleData.values()) {
if(isValidationWanted(examinedFiles, mi.getFile())) {
for(String circularity : mi.getCircularityMessages())