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

making gatk --version print the version #5537

Merged
merged 4 commits into from
Jan 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ tasks.withType(Jar) {
manifest {
attributes 'Implementation-Title': 'The Genome Analysis Toolkit (GATK)',
'Implementation-Version': version,
'Toolkit-Short-Name' : 'GATK',
'Main-Class': project.mainClassName,
'Picard-Version': picardVersion,
'htsjdk-Version': htsjdkVersion
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/org/broadinstitute/hellbender/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import java.io.PrintStream;
import java.io.Serializable;
import java.util.*;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

/**
* This is the main class of Hellbender and is the way of executing individual command line programs.
Expand Down Expand Up @@ -338,6 +340,8 @@ private CommandLineProgram extractCommandLineProgram( final String[] args,

if (args.length < 1 || args[0].equals("-h") || args[0].equals("--help")) {
printUsage(System.out, classes, commandLineName);
} else if ( args.length == 1 && (args[0].equals("-" + SpecialArgumentsCollection.VERSION_FULLNAME) || args[0].equals("--" + SpecialArgumentsCollection.VERSION_FULLNAME))) {
printVersionInfo(System.out);
} else {
if (simpleNameToClass.containsKey(args[0])) {
final Class<?> clazz = simpleNameToClass.get(args[0]);
Expand Down Expand Up @@ -545,4 +549,23 @@ public String getSuggestedAlternateCommand(final Set<Class<?>> classes, final St
}
return message.toString();
}

/**
* Prints version information for the toolkit, including versions of important libraries.
* Subclasses may override to change this behavior.
*/
protected void printVersionInfo(PrintStream out){
final String toolkitName = RuntimeUtils.getToolkitName(this.getClass());
final String version = RuntimeUtils.getVersion(this.getClass());
System.out.println(String.format("%s v%s", toolkitName, version));
final Manifest manifest = RuntimeUtils.getManifest(this.getClass());
if( manifest != null){
final Attributes manifestAttributes = manifest.getMainAttributes();
final String htsjdkVersion = manifestAttributes.getValue("htsjdk-Version");
final String picardVersion = manifestAttributes.getValue("Picard-Version");
out.println("HTSJDK Version: " + (htsjdkVersion != null ? htsjdkVersion : "unknown"));
out.println("Picard Version: " + (picardVersion != null ? picardVersion : "unknown"));
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@
import org.broadinstitute.hellbender.utils.gcs.BucketUtils;
import org.broadinstitute.hellbender.utils.help.HelpConstants;
import org.broadinstitute.hellbender.utils.io.IOUtils;
import org.broadinstitute.hellbender.utils.runtime.RuntimeUtils;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.URL;
import java.nio.file.*;
import java.text.DecimalFormat;
import java.time.Duration;
Expand Down Expand Up @@ -293,7 +292,7 @@ protected void printStartupMessage(final ZonedDateTime startDateTime) {

/**
* If this tool is either Experimental or Beta, return a warning message advising against use in production
* environment.
* envirogetnment.
* @param useTerminalColor true if the message should include highlighting terminal colorization
* @return a warning message if the tool is Beta or Experimental, otherwise null
*/
Expand Down Expand Up @@ -353,17 +352,21 @@ protected void warnOnToolStatus() {
* May be overridden by subclasses to provide a custom implementation if desired.
*/
protected String getToolkitName() {
final String implementationTitle = getClass().getPackage().getImplementationTitle();
return implementationTitle != null ? implementationTitle : getClass().getPackage().getName();
return RuntimeUtils.getToolkitName(this.getClass());
}

/**
* @return An abbreviated name of the toolkit for this tool. Subclasses may override to provide
* a custom toolkit name.
* @return An abbreviated name of the toolkit for this tool. Looks for "Tool-Short-Name" in the manifest by default.
* Uses {@link #DEFAULT_TOOLKIT_SHORT_NAME} if the manifest is unavailable.
* Subclasses may override to do something different.
*/
protected String getToolkitShortName() {
// TODO: stored in the jar manifest, like {@link CommandLineProgram#getToolkitName}
return DEFAULT_TOOLKIT_SHORT_NAME;
final Manifest manifest = RuntimeUtils.getManifest(this.getClass());
if( manifest != null){
return manifest.getMainAttributes().getValue("Toolkit-Short-Name");
} else {
return DEFAULT_TOOLKIT_SHORT_NAME;
}
}

/**
Expand All @@ -373,10 +376,7 @@ protected String getToolkitShortName() {
* May be overridden by subclasses to provide a custom implementation if desired.
*/
public String getVersion() {
String versionString = this.getClass().getPackage().getImplementationVersion();
return versionString != null ?
versionString :
"Unavailable";
return RuntimeUtils.getVersion(this.getClass());
}

/**
Expand All @@ -394,21 +394,13 @@ protected String getSupportInformation() {
* May be overridden by subclasses to provide a custom implementation if desired.
*/
protected void printLibraryVersions() {
try {
final String classPath = getClass().getResource(getClass().getSimpleName() + ".class").toString();
if (classPath.startsWith("jar")) {
final String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF";
try ( final InputStream manifestStream = new URL(manifestPath).openStream() ) {
final Attributes manifestAttributes = new Manifest(manifestStream).getMainAttributes();
final String htsjdkVersion = manifestAttributes.getValue("htsjdk-Version");
final String picardVersion = manifestAttributes.getValue("Picard-Version");

logger.info("HTSJDK Version: " + (htsjdkVersion != null ? htsjdkVersion : "unknown"));
logger.info("Picard Version: " + (picardVersion != null ? picardVersion : "unknown"));
}
}
}
catch (IOException ignored) {
final Manifest manifest = RuntimeUtils.getManifest(this.getClass());
if( manifest != null ){
final Attributes manifestAttributes = manifest.getMainAttributes();
final String htsjdkVersion = manifestAttributes.getValue("htsjdk-Version");
final String picardVersion = manifestAttributes.getValue("Picard-Version");
logger.info("HTSJDK Version: " + (htsjdkVersion != null ? htsjdkVersion : "unknown"));
logger.info("Picard Version: " + (picardVersion != null ? picardVersion : "unknown"));
}
}

Expand All @@ -426,9 +418,8 @@ protected void printSettings() {
}
else {
// At DEBUG verbosity, print all the HTSJDK defaults:
Defaults.allDefaults().entrySet().stream().forEach(e->
logger.info("HTSJDK " + Defaults.class.getSimpleName() + "." + e.getKey() + " : " + e.getValue())
);
Defaults.allDefaults()
.forEach((key, value) -> logger.info("HTSJDK " + Defaults.class.getSimpleName() + "." + key + " : " + value));
}

// Log the configuration options:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package org.broadinstitute.hellbender.utils.runtime;

import org.apache.commons.lang3.StringUtils;
import org.broadinstitute.hellbender.utils.Utils;

import java.io.File;

import org.broadinstitute.hellbender.utils.Utils;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.jar.Manifest;

public final class RuntimeUtils {
public static final String[] PATHS;
Expand Down Expand Up @@ -50,4 +53,44 @@ public static String toolDisplayName(final Class<?> toolClass) {
toolClass.getSimpleName();
}

/**
* @param clazz class to use when looking up the Implementation-Title
* @return The name of this toolkit, uses "Implementation-Title" from the
* jar manifest of the given class, or (if that's not available) the package name.
*/
public static String getToolkitName(Class<?> clazz) {
final String implementationTitle = clazz.getPackage().getImplementationTitle();
return implementationTitle != null ? implementationTitle : clazz.getPackage().getName();
}

/**
* @return load the manifest file associated with the given class or null if loading fails
*/
public static Manifest getManifest(Class<?> clazz) {
final URL resourceURL = clazz.getResource(clazz.getSimpleName() + ".class");
if( resourceURL == null) {
return null;
}
final String classPath = resourceURL.toString();
if (classPath.startsWith("jar")) {
final String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF";
try ( final InputStream manifestStream = new URL(manifestPath).openStream() ) {
return new Manifest(manifestStream);
} catch (IOException e) {
return null;
}
} else {
return null;
}
}

/**
* @return get the implementation version of the given class
*/
public static String getVersion(Class<?> clazz){
String versionString = clazz.getPackage().getImplementationVersion();
return versionString != null ? versionString : "Unavailable";
}


}
6 changes: 6 additions & 0 deletions src/test/java/org/broadinstitute/hellbender/MainTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,10 @@ public void testNonZeroPicardReturnValue() {
}
}

@Test
public void testVersion(){
//assert that --version doesn't crash.
Assert.assertNull(new Main().instanceMain(new String[]{"--version"}));
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.broadinstitute.hellbender.utils.runtime;

import org.broadinstitute.hellbender.GATKBaseTest;
import org.broadinstitute.hellbender.Main;
import org.testng.Assert;
import org.testng.annotations.Test;

Expand All @@ -14,4 +15,11 @@ public void testWhichExists() {
public void testWhichNotExists() {
Assert.assertNull(RuntimeUtils.which("does_not_exist"), "Found nonexistent binary: does_not_exist");
}

@Test
public void testGetToolkitName(){
final String toolkitName = RuntimeUtils.getToolkitName(Main.class);
// test that it's one of the valid outcomes of getToolkitName, tests in intellij don't necessarily build the correct manifest but the docker tests might\
Assert.assertTrue(toolkitName.equals("The Genome Analysis Toolkit (GATK)") || toolkitName.equals("org.broadinstitute.hellbender"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,25 +103,6 @@ public void testStartupCommandExecution() throws IOException {
Assert.assertEquals(getLineFromTempFile(tempFile), "some output");
}

@Test(groups = "python", timeOut = 10000)
public void testStderrRedirect() {
final StreamingProcessController controller = initializePythonControllerWithAckFIFO(true);

// write to stderr, but we expect to get it from stdout due to redirection
controller.writeProcessInput("import sys" + NL + "sys.stderr.write('error output to stderr\\n')" + NL);
boolean ack = requestAndWaitForAck(controller);
Assert.assertTrue(ack);

ProcessOutput po = controller.getProcessOutput();

Assert.assertNotNull(po.getStdout());
Assert.assertNotNull(po.getStdout().getBufferString());
Assert.assertNotNull(po.getStdout().getBufferString().contains("error output to stderr"));

controller.terminate();
Assert.assertFalse(controller.getProcess().isAlive());
}

@Test(timeOut = 10000)
public void testFIFOLifetime() {
// cat is a red herring here; we're just testing that a FIFO is created, and then deleted after termination
Expand Down