GT-2865: Incorporating release name into setting directory name.

This commit is contained in:
Ryan Kurtz 2019-05-21 09:22:50 -04:00
parent 1340268ffa
commit dfd5e26376
17 changed files with 373 additions and 71 deletions

View File

@ -711,12 +711,12 @@ public class Application {
}
/**
* Returns the Release name for this build or null if unknown.
* Returns the release name for this build.
* @return the application release name.
*/
public static String getApplicationReleaseName() {
checkAppInitialized();
return app.layout.getApplicationProperties().getProperty(
ApplicationProperties.RELEASE_NAME_PROPERTY);
return app.layout.getApplicationProperties().getApplicationReleaseName();
}
/**

View File

@ -155,21 +155,32 @@ public class GenericRunInfo {
/**
* This is the same as {@link #getUserSettingsDirsByTime()} except that it doesn't include the
* current installation.
* current installation or installations with different release names.
*/
public static List<File> getPreviousApplicationSettingsDirsByTime() {
List<File> allApplicationDirs = getUserSettingsDirsByTime();
if (allApplicationDirs.isEmpty()) {
return allApplicationDirs;
}
List<File> applicationSettiingsDirs = new ArrayList<>();
File file = allApplicationDirs.get(0);
if (Application.getUserSettingsDirectory().getAbsolutePath().equals(
file.getAbsolutePath())) {
// remove the current application settings dir from the results
return allApplicationDirs.subList(1, allApplicationDirs.size());
ApplicationIdentifier myIdentifier = new ApplicationIdentifier(
Application.getApplicationLayout().getApplicationProperties());
for (File dir : getUserSettingsDirsByTime()) {
String dirName = dir.getName();
if (dirName.startsWith(".")) {
dirName = dirName.substring(1);
}
try {
ApplicationIdentifier identifier = new ApplicationIdentifier(dirName);
if (!identifier.equals(myIdentifier) &&
identifier.getApplicationReleaseName().equalsIgnoreCase(
myIdentifier.getApplicationReleaseName())) {
applicationSettiingsDirs.add(dir);
}
}
catch (IllegalArgumentException e) {
// The directory name didn't contain a valid application identifier...skip it
}
}
return allApplicationDirs;
return applicationSettiingsDirs;
}
/**

View File

@ -0,0 +1,74 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.framework;
import static org.junit.Assert.*;
import org.junit.Test;
import generic.test.AbstractGenericTest;
public class ApplicationIdentifierTest extends AbstractGenericTest {
@Test
public void testApplicationPropertiesIdentifier() {
// We should be able to create an ApplicationIdentifier object from the application info
// defined in the application properties file without an exception being thrown.
new ApplicationIdentifier(Application.getApplicationLayout().getApplicationProperties());
}
@Test
public void testApplicationVersionParsing() {
ApplicationIdentifier id = new ApplicationIdentifier("Ghidra_9.0.1_public_05212019");
assertEquals(id.getApplicationName(), "ghidra");
assertEquals(id.getApplicationVersion(), new ApplicationVersion("9.0.1"));
assertEquals(id.getApplicationReleaseName(), "PUBLIC");
assertEquals(id.toString(), "ghidra_9.0.1_PUBLIC");
try {
new ApplicationIdentifier("ghidra");
fail(
"Should not be able to parse only a name...a version and release name are required.");
}
catch (IllegalArgumentException e) {
// Getting here indicates success
}
try {
new ApplicationIdentifier("ghidra_9.0.1");
fail(
"Should not be able to parse only a name and version...a release name is required.");
}
catch (IllegalArgumentException e) {
// Getting here indicates success
}
}
@Test
public void testApplicationIdentifierEquals() {
ApplicationIdentifier id1 = new ApplicationIdentifier("ghidra_9.0_public");
ApplicationIdentifier id2 = new ApplicationIdentifier("Ghidra_9.0.0_PUBLIC");
assertEquals(id1, id2);
id1 = new ApplicationIdentifier("ghidra_9.0_public");
id2 = new ApplicationIdentifier("Ghidra_9.0.1_PUBLIC");
assertNotEquals(id1, id2);
id1 = new ApplicationIdentifier("ghidra_9.0_DEV");
id2 = new ApplicationIdentifier("ghidra_9.0_PUBLIC");
assertNotEquals(id1, id2);
}
}

View File

@ -35,11 +35,11 @@ public class ApplicationVersionTest extends AbstractGenericTest {
public void testApplicationVersionParsing() {
assertEquals(new ApplicationVersion("9.0").toString(), "9.0");
assertEquals(new ApplicationVersion("9.0.0").toString(), "9.0");
assertEquals(new ApplicationVersion("9.0.0-DEV").toString(), "9.0");
assertEquals(new ApplicationVersion("9.0.0-BETA").toString(), "9.0-BETA");
assertEquals(new ApplicationVersion("9.1").toString(), "9.1");
assertEquals(new ApplicationVersion("9.1.1").toString(), "9.1.1");
assertEquals(new ApplicationVersion("9.1.1-DEV").toString(), "9.1.1");
assertEquals(new ApplicationVersion("9.1.1-BETA").toString(), "9.1.1-BETA");
try {
new ApplicationVersion("9");
@ -52,16 +52,35 @@ public class ApplicationVersionTest extends AbstractGenericTest {
@Test
public void testApplicationVersionGetters() {
ApplicationVersion applicationVersion = new ApplicationVersion("9.0.1-DEV");
ApplicationVersion applicationVersion = new ApplicationVersion("9.0.1-BETA");
assertEquals(applicationVersion.getMajor(), 9);
assertEquals(applicationVersion.getMinor(), 0);
assertEquals(applicationVersion.getPatch(), 1);
}
@Test
public void testApplicationVersionEquals() {
ApplicationVersion applicationVersion1 = new ApplicationVersion("9.0");
ApplicationVersion applicationVersion2 = new ApplicationVersion("9.0.0");
assertTrue(applicationVersion1.equals(applicationVersion2));
applicationVersion1 = new ApplicationVersion("9.0");
applicationVersion2 = new ApplicationVersion("9.0.0-BETA");
assertFalse(applicationVersion1.equals(applicationVersion2));
applicationVersion1 = new ApplicationVersion("9.0.0");
applicationVersion2 = new ApplicationVersion("9.0.1");
assertFalse(applicationVersion1.equals(applicationVersion2));
applicationVersion1 = new ApplicationVersion("9.0");
applicationVersion2 = new ApplicationVersion("10.0");
assertNotEquals(applicationVersion1, applicationVersion2);
}
@Test
public void testApplicationVersionCompare() {
ApplicationVersion applicationVersion1 = new ApplicationVersion("9.0");
ApplicationVersion applicationVersion2 = new ApplicationVersion("9.0.0-DEV");
ApplicationVersion applicationVersion2 = new ApplicationVersion("9.0.0-BETA");
assertTrue(applicationVersion1.compareTo(applicationVersion2) == 0);
applicationVersion1 = new ApplicationVersion("9.0");

View File

@ -0,0 +1,157 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.framework;
/**
* Class to represent an application's unique identifier. An application identifier is made up
* of an application name, an application version, and an application release name.
* <pre>
* The identifier format is (\.+) - \d\.\d(\.\d)?(\-.+)? _ (\.+)
* name version release name
* </pre>
* Application names will be converted to all lowercase and application release names will be
* converted to all uppercase.
* <p>
* Examples:
* <li>ghidra-7.4_DEV
*/
public class ApplicationIdentifier {
private String applicationName;
private ApplicationVersion applicationVersion;
private String applicationReleaseName;
/**
* Creates a new {@link ApplicationIdentifier} object from an {@link ApplicationProperties}.
*
* @param applicationProperties An {@link ApplicationProperties}.
* @throws IllegalArgumentException if required elements from the {@link ApplicationProperties}
* were missing or otherwise failed to parse. The exception's message has more detailed
* information about why it failed.
*/
public ApplicationIdentifier(ApplicationProperties applicationProperties)
throws IllegalArgumentException {
applicationName = applicationProperties.getApplicationName().toLowerCase();
if (applicationName.isEmpty()) {
throw new IllegalArgumentException("Application name is undefined.");
}
applicationVersion = new ApplicationVersion(applicationProperties.getApplicationVersion());
applicationReleaseName = applicationProperties.getApplicationReleaseName().toUpperCase();
if (applicationReleaseName.isEmpty()) {
throw new IllegalArgumentException("Application release name is undefined.");
}
}
/**
* Creates a new {@link ApplicationIdentifier} object from the given string.
*
* @param identifier An identifier string.
* @throws IllegalArgumentException if the identifier string failed to parse. The
* exception's message has more detailed information about why it failed.
*/
public ApplicationIdentifier(String identifier) throws IllegalArgumentException {
parse(identifier);
}
/**
* Gets the application name.
*
* @return The application name.
*/
public String getApplicationName() {
return applicationName;
}
/**
* Gets the {@link ApplicationVersion application version}.
*
* @return The {@link ApplicationVersion application version}.
*/
public ApplicationVersion getApplicationVersion() {
return applicationVersion;
}
/**
* Gets the application release name.
*
* @return The application release name.
*/
public String getApplicationReleaseName() {
return applicationReleaseName;
}
@Override
public String toString() {
return applicationName + "_" + applicationVersion + "_" + applicationReleaseName;
}
@Override
public int hashCode() {
return (applicationName + applicationReleaseName).hashCode() *
applicationVersion.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ApplicationIdentifier other = (ApplicationIdentifier) obj;
if (!applicationName.equals(other.applicationName)) {
return false;
}
if (!applicationReleaseName.equals(other.applicationReleaseName)) {
return false;
}
if (!applicationVersion.equals(other.applicationVersion)) {
return false;
}
return true;
}
/**
* Parses application identifier components out of the given version string.
*
* @param identifier An identifier string.
* @throws IllegalArgumentException if the identifier string failed to parse. The
* exception's message has more detailed information about why it failed.
*/
private void parse(String identifier) throws IllegalArgumentException {
if (identifier == null) {
throw new IllegalArgumentException("Identifier is null");
}
String[] identifierParts = identifier.split("_");
if (identifierParts.length >= 3) {
applicationName = identifierParts[0].toLowerCase();
applicationVersion = new ApplicationVersion(identifierParts[1]);
applicationReleaseName = identifierParts[2].toUpperCase();
// Ignore any parts after the release name...they are not part of the identifier
}
else {
throw new IllegalArgumentException(
"Identifier has " + identifierParts.length + " parts but 3 are required");
}
}
}

View File

@ -105,16 +105,6 @@ public class ApplicationProperties extends Properties {
public static final String TEST_RELEASE_PROPERTY = "application.test.release";
public static final String RELEASE_SOURCE_PROPERTY = "application.release.source";
/**
* The default application name to use if {@link #APPLICATION_NAME_PROPERTY} is undefined.
*/
private static final String DEFAULT_APPLICATION_NAME = "NO_APP_NAME_DEFINED";
/**
* The default version to use if {@link #APPLICATION_VERSION_PROPERTY} is undefined.
*/
private static final String DEFAULT_APPLICATION_VERSION = "0.1";
/**
* Attempts to create an instance of this class by looking for the a properties file
* with the give name in the current working directory.
@ -233,12 +223,12 @@ public class ApplicationProperties extends Properties {
/**
* Gets the application's name.
*
* @return The application's name.
* @return The application's name (empty string if undefined).
*/
public String getApplicationName() {
String appName = getProperty(ApplicationProperties.APPLICATION_NAME_PROPERTY);
if (appName == null) {
return DEFAULT_APPLICATION_NAME;
if (appName == null || appName.trim().isEmpty()) {
return "";
}
return appName;
}
@ -246,15 +236,28 @@ public class ApplicationProperties extends Properties {
/**
* Gets the application's version.
*
* @return The application's version.
* @return The application's version (empty string if undefined).
*/
public String getApplicationVersion() {
String appVersion = getProperty(ApplicationProperties.APPLICATION_VERSION_PROPERTY);
if (appVersion == null) {
return DEFAULT_APPLICATION_VERSION;
if (appVersion == null || appVersion.trim().isEmpty()) {
return "";
}
return appVersion;
}
/**
* Gets the application's release name.
*
* @return The application's release name (empty string if undefined).
*/
public String getApplicationReleaseName() {
String appReleaseName = getProperty(ApplicationProperties.RELEASE_NAME_PROPERTY);
if (appReleaseName == null || appReleaseName.trim().isEmpty()) {
return "";
}
return appReleaseName;
}
/**
* Gets the application's build date.
@ -263,8 +266,8 @@ public class ApplicationProperties extends Properties {
*/
public String getApplicationBuildDate() {
String appBuildDate = getProperty(ApplicationProperties.BUILD_DATE_PROPERTY);
if (appBuildDate == null) {
// Use today if property is not found
if (appBuildDate == null || appBuildDate.trim().isEmpty()) {
// Use today if property is not defined
appBuildDate = new SimpleDateFormat("yyyy-MMM-dd").format(new Date());
}
return appBuildDate;

View File

@ -20,16 +20,20 @@ package ghidra.framework;
* <p>
* The version format is \d\.\d(\.\d)?(\-.+)?
* <p>
* Note: this class has a natural ordering that is inconsistent with equals (the <code>tag</code>
* part of the version is disregarded in the {@link #compareTo(ApplicationVersion)} method).
* <p>
* Examples:
* <li>7.4
* <li>7.4.1
* <li>7.4.1-DEV
* <li>7.4.1-BETA
*/
public class ApplicationVersion implements Comparable<ApplicationVersion> {
private int major;
private int minor;
private int patch;
private String tag;
/**
* Creates a new {@link ApplicationVersion} object from the given version string.
@ -69,12 +73,30 @@ public class ApplicationVersion implements Comparable<ApplicationVersion> {
return patch;
}
/**
* Gets the tag.
*
* @return The tag. Could be the empty string.
*/
public String getTag() {
return tag;
}
@Override
public String toString() {
if (patch == 0) {
return String.format("%d.%d", major, minor);
StringBuilder builder = new StringBuilder();
builder.append(major);
builder.append(".");
builder.append(minor);
if (patch > 0) {
builder.append(".");
builder.append(patch);
}
return String.format("%d.%d.%d", major, minor, patch);
if (!tag.isEmpty()) {
builder.append("-");
builder.append(tag);
}
return builder.toString();
}
@Override
@ -107,6 +129,7 @@ public class ApplicationVersion implements Comparable<ApplicationVersion> {
result = prime * result + major;
result = prime * result + minor;
result = prime * result + patch;
result += tag.hashCode();
return result;
}
@ -131,11 +154,14 @@ public class ApplicationVersion implements Comparable<ApplicationVersion> {
if (patch != other.patch) {
return false;
}
if (!tag.equals(other.tag)) {
return false;
}
return true;
}
/**
* Parses the major, minor, and optional patch integers out of the given version string.
* Parses the major, minor, patch, and tag components out of the given version string.
*
* @param version A version string.
* @throws IllegalArgumentException if the version string failed to parse. The
@ -146,8 +172,12 @@ public class ApplicationVersion implements Comparable<ApplicationVersion> {
throw new IllegalArgumentException("Version is null");
}
tag = "";
int dashIndex = version.indexOf('-');
if (dashIndex != -1) {
if (dashIndex + 1 < version.length()) {
tag = version.substring(dashIndex + 1);
}
version = version.substring(0, dashIndex);
}

View File

@ -20,8 +20,7 @@ import java.util.ArrayList;
import java.util.Collection;
import generic.jar.ResourceFile;
import ghidra.framework.ApplicationProperties;
import ghidra.framework.OperatingSystem;
import ghidra.framework.*;
import ghidra.util.Msg;
import ghidra.util.SystemUtilities;
@ -68,8 +67,7 @@ public class ApplicationUtilities {
}
}
catch (IOException e) {
Msg.error(ApplicationUtilities.class, "Invalid class path entry: " + pathEntry,
e);
Msg.error(ApplicationUtilities.class, "Invalid class path entry: " + pathEntry, e);
}
}
return null;
@ -181,23 +179,25 @@ public class ApplicationUtilities {
public static File getDefaultUserSettingsDir(ApplicationProperties applicationProperties,
ResourceFile installationDirectory) throws FileNotFoundException {
String userSettingsDir = System.getProperty("user.home");
if (userSettingsDir == null || userSettingsDir.isEmpty()) {
String homedir = System.getProperty("user.home");
if (homedir == null || homedir.isEmpty()) {
throw new FileNotFoundException("System property \"user.home\" is not set!");
}
String prefix =
"." + applicationProperties.getApplicationName().replaceAll("\\s", "").toLowerCase();
ApplicationIdentifier applicationIdentifier =
new ApplicationIdentifier(applicationProperties);
File applicationParentDir = new File(userSettingsDir, prefix);
String suffix = applicationProperties.getApplicationVersion();
File userSettingsParentDir =
new File(homedir, "." + applicationIdentifier.getApplicationName());
String userSettingsDirName = "." + applicationIdentifier;
if (SystemUtilities.isInDevelopmentMode()) {
// Add the appication's installation directory name to this variable, so that each
// Add the application's installation directory name to this variable, so that each
// branch's project user directory is unique.
suffix += "_location_" + installationDirectory.getName();
userSettingsDirName += "_location_" + installationDirectory.getName();
}
return new File(applicationParentDir, prefix + "-" + suffix);
return new File(userSettingsParentDir, userSettingsDirName);
}
}

View File

@ -1,6 +1,6 @@
application.name=Ghidra
application.version=9.1-DEV
application.release.name=PUBLIC
application.version=9.1
application.release.name=DEV
application.layout.version=1
application.gradle.version=5.0
application.java.min=11

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<site>
<feature url="features/ghidra.ghidradev_2.0.1.qualifier.jar" id="ghidra.ghidradev" version="2.0.1.qualifier">
<feature url="features/ghidra.ghidradev_2.1.0.qualifier.jar" id="ghidra.ghidradev" version="2.1.0.qualifier">
<category name="ghidra.ghidradev"/>
</feature>
<category-def name="ghidra.ghidradev" label="Ghidra"/>

View File

@ -2,7 +2,7 @@
<feature
id="ghidra.ghidradev"
label="GhidraDev"
version="2.0.1.qualifier"
version="2.1.0.qualifier"
provider-name="Ghidra">
<description>

View File

@ -19,7 +19,7 @@
<h1>GhidraDev README</h1>
<p>GhidraDev provides support for developing and debugging Ghidra scripts and modules in Eclipse.
</p>
<p>The information provided in this document is effective as of GhidraDev 2.0.1 and is subject to
<p>The information provided in this document is effective as of GhidraDev 2.1.0 and is subject to
change with future releases.</p>
<ul>
@ -53,6 +53,8 @@ change with future releases.</p>
</ul>
<h2><a name="ChangeHistory"></a>Change History</h2>
<p><u><b>2.1.0</b>:</u> Added support for Ghidra 9.1. GhidraDev 2.1.0 will be unable to create
new Eclipse projects for versions of Ghidra earlier than 9.1.</p>
<p><u><b>2.0.1</b>:</u> Fixed exception that occurred when performing certain actions on a Ghidra
project that was imported from a previously exported Archive File.</p>
<p><u><b>2.0.0</b>:</u>

View File

@ -3,7 +3,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: GhidraDev
Bundle-SymbolicName: ghidra.ghidradev;singleton:=true
Bundle-Version: 2.0.1.qualifier
Bundle-Version: 2.1.0.qualifier
Bundle-Activator: ghidradev.Activator
Require-Bundle: org.eclipse.ant.core;bundle-version="3.5.200",
org.eclipse.buildship.core;bundle-version="3.0.0",

View File

@ -43,7 +43,7 @@ import utility.application.ApplicationLayout;
public class GhidraProjectCreatorPreferencePage extends PreferencePage
implements IWorkbenchPreferencePage {
private static ApplicationVersion MIN_GHIDRA_VERSION = new ApplicationVersion("9.0");
private static ApplicationVersion MIN_GHIDRA_VERSION = new ApplicationVersion("9.1");
private Table table;
private Button addButton;

View File

@ -33,8 +33,9 @@ public class JavaConfig {
private LaunchProperties launchProperties;
private File javaHomeSaveFile;
private String applicationName;
private String applicationVersion;
private String applicationName; // example: Ghidra
private String applicationVersion; // example: 9.0.1
private String applicationReleaseName; // example: PUBLIC, DEV, etc
private int minSupportedJava;
private int maxSupportedJava;
private String compilerComplianceLevel;
@ -277,6 +278,8 @@ public class JavaConfig {
// Required properties
applicationName = getDefinedProperty(applicationProperties, "application.name");
applicationVersion = getDefinedProperty(applicationProperties, "application.version");
applicationReleaseName =
getDefinedProperty(applicationProperties, "application.release.name");
compilerComplianceLevel =
getDefinedProperty(applicationProperties, "application.java.compiler");
try {
@ -349,13 +352,16 @@ public class JavaConfig {
}
// Get the java home save file from user home directory (it might not exist yet).
String prefix = "." + applicationName.replaceAll("\\s", "").toLowerCase();
String suffix = applicationVersion;
File userSettingsParentDir = new File(userHomeDir, "." + applicationName.toLowerCase());
String userSettingsDirName = userSettingsParentDir.getName() + "_" + applicationVersion +
"_" + applicationReleaseName.toUpperCase();
if (isDev) {
suffix += "_location_" + installDir.getParentFile().getName();
userSettingsDirName += "_location_" + installDir.getParentFile().getName();
}
File userSettingsDir =
new File(userHomeDir, prefix + File.separator + prefix + "-" + suffix);
File userSettingsDir = new File(userSettingsParentDir, userSettingsDirName);
javaHomeSaveFile = new File(userSettingsDir, JAVA_HOME_SAVE_NAME);
}

View File

@ -15,8 +15,8 @@ import org.apache.tools.ant.filters.*
def currentPlatform = getCurrentPlatformName()
def PROJECT_DIR = file (rootProject.projectDir.absolutePath)
ext.DISTRIBUTION_DIR = file("$buildDir/dist")
ext.ZIP_NAME_PREFIX = "${rootProject.DISTRO_PREFIX}_${rootProject.RELEASE_NAME}_${rootProject.BUILD_DATE_SHORT}"
ext.ZIP_DIR_PREFIX = rootProject.DISTRO_PREFIX
ext.ZIP_NAME_PREFIX = "${rootProject.DISTRO_PREFIX}_${rootProject.BUILD_DATE_SHORT}"
ext.ZIP_DIR_PREFIX = "${rootProject.DISTRO_PREFIX}"
FileTree javadocFiles = fileTree (rootProject.projectDir.toString()) {

View File

@ -11,8 +11,8 @@ file("Ghidra/application.properties").withReader { reader ->
version = ghidraProps.getProperty('application.version')
project.ext.RELEASE_VERSION = version
project.ext.RELEASE_NAME = ghidraProps.getProperty('application.release.name')
project.ext.DISTRO_PREFIX = "ghidra_${version}"
project.ext.JAVA_COMPILER = ghidraProps.getProperty('application.java.compiler')
project.ext.DISTRO_PREFIX = "ghidra_${version}_${RELEASE_NAME}"
// Build dates may or may not be already present in the application.properties file.
// If they are not present, we will set the dates so Gradle can use them, and we will