Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Verify loaders exist at build. #12

Merged
3 changes: 2 additions & 1 deletion src/com/fivium/scriptrunner2/CommandLineOption.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public enum CommandLineOption {
, ADDITIONAL_PROPERTIES("props")
, INSTALL_PROMOTE_USER("newpromoteuser")
, INSTALL_PROMOTE_PASSWORD("newpromotepassword")
, NO_UNIMPLICATED_FILES("nounimplicatedfiles");
, NO_UNIMPLICATED_FILES("nounimplicatedfiles")
, VERIFY_LOADERS("verifyloaders");

private final String mArgString;

Expand Down
1 change: 1 addition & 0 deletions src/com/fivium/scriptrunner2/CommandLineWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public class CommandLineWrapper {
gCommandLineOptions.addOption(CommandLineOption.ADDITIONAL_PROPERTIES.getArgString(), true, "(Build only) Location of the additional properties file for the builder.");

gCommandLineOptions.addOption(CommandLineOption.NO_UNIMPLICATED_FILES.getArgString(), false, "(Build only) Error (rather than warn) if files are found in source directory but not implicated by manifest builder rules.");
gCommandLineOptions.addOption(CommandLineOption.VERIFY_LOADERS.getArgString(), false, "(Build only) Validate that the Loader files can be found at build time.");

//gCommandLineOptions.addOption("help", false, "Prints help.");
}
Expand Down
3 changes: 2 additions & 1 deletion src/com/fivium/scriptrunner2/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ public static void main(String[] args) {
}
}
else if(lCommandLineOptions.hasOption(CommandLineOption.BUILD)){
ScriptBuilder.run(lCommandLineOptions);
ScriptBuilder lScriptBuilder = new ScriptBuilder(lCommandLineOptions);
lScriptBuilder.run();
Logger.logAndEcho("Build completed successfully");
}
else if(lCommandLineOptions.hasOption(CommandLineOption.INSTALL)){
Expand Down
144 changes: 119 additions & 25 deletions src/com/fivium/scriptrunner2/ScriptBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@

import com.fivium.scriptrunner2.builder.ManifestBuilder;
import com.fivium.scriptrunner2.ex.ExFatalError;
import com.fivium.scriptrunner2.ex.ExManifest;
import com.fivium.scriptrunner2.ex.ExManifestBuilder;
import com.fivium.scriptrunner2.ex.ExParser;
import com.fivium.scriptrunner2.loader.MetadataLoader;
import com.fivium.scriptrunner2.util.ArchiveUtil;
import com.fivium.scriptrunner2.util.XFUtil;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;

Expand All @@ -22,40 +26,56 @@
/**
* Class for co-ordinating the creation of a promotion archive file.
*/
public class ScriptBuilder {

public class ScriptBuilder
implements FileResolver {

/** Container for all command line options which were used to invoke ScriptRunner. */
private final CommandLineWrapper mCommandLineWrapper;

/** Source directory of the build. */
private final File mSourceDirectory;

/**
* Generates a promotion archive by creating a manifest and zipping up all the manifest's implicated files into a single
* file. All options for this procedure should be specified on the command line.
* @param pOptionWrapper All command line options.
* @throws ExManifestBuilder If the manifest cannot be built.
* @throws ExParser If the manifest override or additional properties cannot be parsed.
* Creates a new ScriptBuilder.
* @param pCommandLineWrapper All command line options.
* @throws ExFatalError If required command line options are missing or invalid.
*/
public static void run(CommandLineWrapper pOptionWrapper)
throws ExManifestBuilder, ExParser {
public ScriptBuilder(CommandLineWrapper pCommandLineWrapper) {
mCommandLineWrapper = pCommandLineWrapper;

//Determine source directory
String lSourceDirectoryString = pOptionWrapper.getOption(CommandLineOption.BUILD);

String lSourceDirectoryString = mCommandLineWrapper.getOption(CommandLineOption.BUILD);
if(XFUtil.isNull(lSourceDirectoryString)){
throw new ExFatalError("-" + CommandLineOption.BUILD.getArgString() + " argument must be specified");
}
Logger.logInfo("Source directory is " + lSourceDirectoryString);

File lSourceDirectory = new File(lSourceDirectoryString);


mSourceDirectory = new File(lSourceDirectoryString);
}

/**
* Generates a promotion archive by creating a manifest and zipping up all the manifest's implicated files into a single
* file. All options for this procedure should be specified on the command line.
* @throws ExManifest If validations of the manifest fail.
* @throws ExManifestBuilder If the manifest cannot be built.
* @throws ExParser If the manifest override or additional properties cannot be parsed.
* @throws ExFatalError If required command line options are missing or invalid.
*/
public void run()
throws ExManifest, ExManifestBuilder, ExParser {

//Determine promotion label

String lPromotionLabel = pOptionWrapper.getOption(CommandLineOption.PROMOTION_LABEL);
String lPromotionLabel = mCommandLineWrapper.getOption(CommandLineOption.PROMOTION_LABEL);
if(XFUtil.isNull(lPromotionLabel)){
throw new ExFatalError("-" + CommandLineOption.PROMOTION_LABEL.getArgString() + " argument must be specified");
}
Logger.logInfo("Promotion label is " + lPromotionLabel);

//Determine output location

String lOutputFileString = pOptionWrapper.getOption(CommandLineOption.OUTPUT_FILE_PATH);
String lOutputFileString = mCommandLineWrapper.getOption(CommandLineOption.OUTPUT_FILE_PATH);
File lOutputFile;
if(XFUtil.isNull(lOutputFileString)){
lOutputFile = new File(new File(System.getProperty("user.dir")), lPromotionLabel + ".zip");
Expand All @@ -66,7 +86,7 @@ public static void run(CommandLineWrapper pOptionWrapper)

//Determine additional properties file location

String lAdditionalPropsPath = pOptionWrapper.getOption(CommandLineOption.ADDITIONAL_PROPERTIES);
String lAdditionalPropsPath = mCommandLineWrapper.getOption(CommandLineOption.ADDITIONAL_PROPERTIES);
File lAdditionalPropsFile = null;
if(!XFUtil.isNull(lAdditionalPropsPath)){
lAdditionalPropsFile = new File(lAdditionalPropsPath);
Expand All @@ -75,7 +95,7 @@ public static void run(CommandLineWrapper pOptionWrapper)
}
}

File lManifestDestinationFile = new File(lSourceDirectory, ScriptRunner.MANIFEST_RELATIVE_FILE_PATH);
File lManifestDestinationFile = new File(mSourceDirectory, ScriptRunner.MANIFEST_RELATIVE_FILE_PATH);
//Ensure the /ScriptRunner leg exists (it always should)
lManifestDestinationFile.getParentFile().mkdirs();
PrintWriter lManifestDestinationWriter;
Expand All @@ -87,7 +107,7 @@ public static void run(CommandLineWrapper pOptionWrapper)
}

//Construct the manifest file
ManifestBuilder lManifestBuilder = new ManifestBuilder(lSourceDirectory, lPromotionLabel);
ManifestBuilder lManifestBuilder = new ManifestBuilder(mSourceDirectory, lPromotionLabel);
lManifestBuilder.buildManifest(lAdditionalPropsFile, lManifestDestinationWriter);

//Check that all files in the source directory have been implicated
Expand All @@ -98,35 +118,109 @@ public static void run(CommandLineWrapper pOptionWrapper)

if(lFilePathsInBaseDirectory.size() > 0){
String warningMessage = lFilePathsInBaseDirectory.size() + " files found in source directory but not implicated by manifest builder rules:";
if(pOptionWrapper.hasOption(CommandLineOption.NO_UNIMPLICATED_FILES)){
if(mCommandLineWrapper.hasOption(CommandLineOption.NO_UNIMPLICATED_FILES)){
StringBuilder errorMessage = new StringBuilder();
errorMessage.append(warningMessage + "\n");
for (String lPath : lFilePathsInBaseDirectory) {
errorMessage.append(lPath + "\n");
}
throw new ExManifestBuilder(errorMessage.toString());
} else {
}
else {
Logger.logWarning(warningMessage);
for (String lPath : lFilePathsInBaseDirectory) {
Logger.logInfo(lPath);
}
}
}

// If the argument has been specified attempt to parse the manifest
// and then verify that all the Loader files exist in the source directory.
if(mCommandLineWrapper.hasOption(CommandLineOption.VERIFY_LOADERS)) {
//Parse the newly created manifest.
PromotionManifestParser lParser = new PromotionManifestParser(lManifestDestinationFile);
try {
lParser.parse();
}
catch (FileNotFoundException e) {
throw new ExFatalError("Failed to parse manifest: file not found", e);
}
catch (IOException e) {
throw new ExFatalError("Failed to parse manifest: IOException", e);
}
catch (ExParser e) {
throw new ExFatalError("Failed to parse manifest: " + e.getMessage(), e);
}
catch (ExManifest e) {
throw new ExFatalError("Failed to load manifest: " + e.getMessage(), e);
}

//Verify all loaders exist
ArrayList<String> lUnverifiedLoaders = new ArrayList<String>();
for (MetadataLoader lLoader : lParser.getLoaderMap().values()) {
try {
this.resolveFile(lLoader.getLoaderFilePath());
}
catch (FileNotFoundException e) {
lUnverifiedLoaders.add(lLoader.getName());
}
}

if (!lUnverifiedLoaders.isEmpty()) {
StringBuilder errorMessage = new StringBuilder();
errorMessage.append(lUnverifiedLoaders.size() + " Loader files cannot be located:\n");
for (String loaderName : lUnverifiedLoaders) {
errorMessage.append(loaderName + "\n");
}
throw new ExManifest(errorMessage.toString());
}
}

//Get all non-ignored files to put in the zip
lImplicatedManifestFilePaths = lManifestBuilder.allImplicatedFilePaths(false);

//Get all files in the /ScriptRunner leg
Collection<File> lScripRunnerFileList = FileUtils.listFiles(new File(lSourceDirectory, ScriptRunner.SCRIPTRUNNER_DIRECTORY_NAME), TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
Collection<File> lScripRunnerFileList = FileUtils.listFiles(new File(mSourceDirectory, ScriptRunner.SCRIPTRUNNER_DIRECTORY_NAME), TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
for(File lFile : lScripRunnerFileList){
lImplicatedManifestFilePaths.add(lManifestBuilder.relativeFilePath(lFile));
}

Logger.logAndEcho("Building promotion file " + lOutputFile.getAbsolutePath());

//Create the final archive in the output location
ArchiveUtil.createZip(lSourceDirectory, lImplicatedManifestFilePaths, lOutputFile);
ArchiveUtil.createZip(mSourceDirectory, lImplicatedManifestFilePaths, lOutputFile);

}


/**
* Gets a file from this ScriptRunner's base directory.
* @param pPath A path to the desired file, relative to the source directory.
* @return The requested file.
* @throws FileNotFoundException If the file does not exist.
*/
public File resolveFile(String pPath)
throws FileNotFoundException {
File lFile = new File(mSourceDirectory, pPath);

if(!lFile.exists()){
throw new FileNotFoundException("Failed to locate file " + pPath + " in base directory");
}

return lFile;
}

/**
* Gets the path of the given file relativised to the current source directory and normalised.
* @param pFile File to get path of.
* @return Relativised file path.
*/
public String relativeFilePath(File pFile){
return ScriptRunner.normaliseFilePath(mSourceDirectory.toURI().relativize(pFile.toURI()).getPath());
}

@Override
public File getBaseDirectory() {
return mSourceDirectory;
}

}