Added version.projects property.

Added README.md.
This commit is contained in:
Erik C. Thauvin 2016-01-23 15:39:38 -08:00
parent aeee81544c
commit 57116e691f
15 changed files with 218 additions and 67 deletions

97
README.md Normal file
View file

@ -0,0 +1,97 @@
# Semantic Version Annotation Processor
An [annotation processor](https://docs.oracle.com/javase/8/docs/api/javax/annotation/processing/Processor.html) that automatically generates a `Version` class containing the [semantic version](http://semver.org/) (major, minor, patch, etc.) that is read from a `Properties` file or defined in the [annotation](https://docs.oracle.com/javase/tutorial/java/annotations/basics.html).
This processor was inspired by Cédric Beust's [version-processor](https://github.com/cbeust/version-processor).
## Examples
* Using annotation elements:
```java
@Version(major = 1, minor = 0, patch = 0, prerelease = "beta")
public class A {
// ...
```
* Or using a [properties](https://docs.oracle.com/javase/tutorial/essential/environment/properties.html) file:
```java
@Version(properties = "version.properties")
public class A {
// ...
```
and `version.properties` containing:
```ini
version.major=1
version.minor=0
version.patch=0
version.prerelease=beta
```
## Template
Upon running the annotator processor, a source file `GeneratedVersion.java` is automatically generated with static methods to access the semantic version data. The source is based on a fully customizable [Velocity](http://velocity.apache.org/) template.
```java
@Version(template = "myversion.vm")
public class A {
// ...
```
The [default template]() implements the following static methods:
Method | Description | Example
------------------|----------------------------------|------------------
`getProject` | The project name, if any. | `MyProject`
`getBuildDate` | The build date. | [`java.util.Date`](https://docs.oracle.com/javase/8/docs/api/java/util/Date.html)
`getVersion` | The full version string. | `1.0.0-alpha+001`
`getMajor` | The major version. | `1`
`getMinor` | The minor version. | `0`
`getPatch` | The patch version. | `0`
`getPreRelease` | The pre-release version, if any. | `alpha`
`getBuildMetadata`| The build metadata, if any. | `001`
## Elements & Properties
The following annotation elements and properties are available:
Element | Property | Description | Default
-------------|----------------------|----------------------------------|-------------
`project` | `version.project` | The project name. |
`major` | `version.major` | The major version number. | `1`
`minor` | `version.major` | The minor version number. | `0`
`patch` | `version.patch` | The patch version number. | `0`
`prerelease` | `version.prerelease` | The pre-release version. |
`buildmeta` | `version.buildmeta` | The build metadata version. |
`className` | | The name of the generated class. | `GeneratedVersion`
`properties` | | The properties file. |
`template` | | The template file. | `version.vm`
In order to easily incorporate with existing projects, the property keys may be assigned custom values:
```java
@Version(
properties = "example.properties",
majorKey = "example.major",
minorKey = "example.minor",
patchKey = "example.patch",
prereleaseKey = "example.prerelease",
buildmetaKey = "example.buildmeta",
projectKey = "example.project"
)
public class Example {
// ...
```
with `example.properties` containing:
```ini
example.project=Example
example.major=1
example.minor=0
example.patch=0
...
```

View file

@ -4,13 +4,36 @@ apply plugin: 'maven'
defaultTasks 'deploy'
version = '1.0'
def getVersion(isIncrement = false)
{
def propsFile = 'version.properties'
def majorKey = 'version.major'
def minorKey = 'version.minor'
def patchKey = 'version.patch'
def metaKey = 'version.buildmeta'
def preKey = 'version.prerelease'
if (isIncrement)
{
ant.propertyfile(file: propsFile) {
entry(key: patchKey,
type: 'int',
default: '-1',
operation: '+')
}
}
def p = new Properties()
file(propsFile).withInputStream { stream -> p.load(stream) }
def metadata = p.getProperty(metaKey, '')
def prerelease = p.getProperty(preKey, '')
return (p.getProperty(majorKey, '1') + '.' + p.getProperty(minorKey, '0') + '.' + p.getProperty(patchKey, '0') +
(prerelease.length() > 0 ? '-' + prerelease : '') + (metadata.length() > 0 ? '+' + metadata : ''))
}
version = getVersion()
def deployDir = 'deploy'
def isRelease = 'release' in gradle.startParameter.taskNames
def mavenGroupId = 'net.thauvin.erik'
//def buildProps = 'buildnumber.properties'
//def buildProp = 'build'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
@ -29,31 +52,9 @@ test {
}
compileJava {
/*
doFirst {
if (isRelease)
{
ant.propertyfile(file: buildProps) {
entry(key: buildProp,
type: 'int',
default: '-1',
operation: '+')
}
}
project.version = getVersion(isRelease)
}
*/
}
jar {
/*
doFirst {
def props = new Properties()
file(buildProps).withInputStream { stream -> props.load(stream) }
project.version = version + '.' + props.get(buildProp)
}
*/
archiveName = archiveName.toLowerCase()
}
clean {
@ -61,17 +62,13 @@ clean {
}
task copyToDeploy(type: Copy) {
from(configurations.runtime) {
exclude 'servlet-api-*.jar'
exclude 'jsp-api-*.jar'
}
from jar
into deployDir
}
task deploy(dependsOn: ['build', 'copyToDeploy']) {
description = "Copies all needed files to the ${deployDir} directory."
group = "Publishing"
description = 'Copies all needed files to the ${deployDir} directory.'
group = 'Publishing'
outputs.dir deployDir
inputs.files copyToDeploy
mustRunAfter clean
@ -81,7 +78,7 @@ uploadArchives {
repositories {
mavenDeployer {
repository(url: mavenLocal().url)
pom.artifactId = rootProject.name.toLowerCase()
pom.artifactId = rootProject.name
pom.groupId = mavenGroupId
}
}
@ -91,8 +88,8 @@ task wrapper(type: Wrapper) {
gradleVersion = gradle.gradleVersion
}
task release(dependsOn: ['deploy', 'wrapper', 'uploadArchives']) {
group = "Publishing"
description = "Releases new version."
task release(dependsOn: ['deploy', 'wrapper', 'uploadArchives']) << {
group = 'Publishing'
description = 'Releases new version.'
isRelease = true
}

View file

@ -13,15 +13,15 @@ def deployDir = 'deploy'
def getVersion(isIncrement = false)
{
def propsFile = 'version.properties'
def majorProp = 'version.major'
def minorProp = 'version.minor'
def patchProp = 'version.patch'
def metaProp = 'version.buildmeta'
def preProp = 'version.prerelease'
def majorKey = 'version.major'
def minorKey = 'version.minor'
def patchKey = 'version.patch'
def metaKey = 'version.buildmeta'
def preKey = 'version.prerelease'
if (isIncrement)
{
ant.propertyfile(file: propsFile) {
entry(key: patchProp,
entry(key: patchKey,
type: 'int',
default: '-1',
operation: '+')
@ -29,9 +29,9 @@ def getVersion(isIncrement = false)
}
def p = new Properties()
file(propsFile).withInputStream { stream -> p.load(stream) }
def metadata = p.getProperty(metaProp, '')
def prerelease = p.getProperty(preProp, '')
return (p.getProperty(majorProp, '1') + '.' + p.getProperty(minorProp, '0') + '.' + p.getProperty(patchProp, '0') +
def metadata = p.getProperty(metaKey, '')
def prerelease = p.getProperty(preKey, '')
return (p.getProperty(majorKey, '1') + '.' + p.getProperty(minorKey, '0') + '.' + p.getProperty(patchKey, '0') +
(prerelease.length() > 0 ? '-' + prerelease : '') + (metadata.length() > 0 ? '+' + metadata : ''))
}
@ -46,17 +46,17 @@ repositories {
}
dependencies {
compile "net.thauvin.erik:semver:+"
compile 'net.thauvin.erik:semver:+'
}
annotationProcessor {
project.version = getVersion(isRelease)
library "net.thauvin.erik:semver:+"
processor "net.thauvin.erik.semver.VersionProcessor"
library 'net.thauvin.erik:semver:+'
processor 'net.thauvin.erik.semver.VersionProcessor'
}
compileJava {
options.compilerArgs << "-proc:none"
options.compilerArgs << '-proc:none'
}
jar {
@ -74,17 +74,17 @@ task copyToDeploy(type: Copy) {
}
task deploy(dependsOn: ['build', 'copyToDeploy']) {
description = "Copies all needed files to the ${deployDir} directory."
group = "Publishing"
description = 'Copies all needed files to the ${deployDir} directory.'
group = 'Publishing'
outputs.dir deployDir
inputs.files copyToDeploy
mustRunAfter clean
}
task release(dependsOn: ['deploy', 'wrapper']) {
group = "Publishing"
description = "Releases new version."
task release(dependsOn: ['deploy', 'wrapper']) << {
group = 'Publishing'
description = 'Releases new version.'
isRelease = true
}

View file

@ -16,10 +16,10 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Gradle: net.thauvin.erik:semver:1.0" level="project" />
<orderEntry type="library" name="Gradle: org.apache.velocity:velocity:1.7" level="project" />
<orderEntry type="library" name="Gradle: commons-collections:commons-collections:3.2.1" level="project" />
<orderEntry type="library" name="Gradle: commons-lang:commons-lang:2.4" level="project" />
<orderEntry type="library" name="Gradle: net.thauvin.erik:semver:1.0.1-beta" level="project" />
</component>
<component name="org.twodividedbyzero.idea.findbugs">
<option name="_basePreferences">

View file

@ -13,11 +13,12 @@ import java.util.Date;
*/
public final class GeneratedVersion {
private final static String buildmeta = "";
private final static Date date = new Date(1453146881481L);
private final static Date date = new Date(1453591949581L);
private final static int major = 3;
private final static int minor = 1;
private final static int patch = 35;
private final static String prerelease = "beta";
private final static String project = "Example";
/**
* Returns the build date.
@ -77,6 +78,15 @@ public final class GeneratedVersion {
return "";
}
/**
* Returns the project name.
*
* @return The project name, if any.
*/
public static String getProject() {
return project;
}
/**
* Returns the build metadata.
*

View file

@ -51,7 +51,7 @@ public class Example
{
final SimpleDateFormat sdf = new SimpleDateFormat("'Built on' EEE, d MMM yyyy 'at' HH:mm:ss z");
System.out.println(Example.class.getSimpleName() + ' ' + GeneratedVersion.getVersion());
System.out.println(GeneratedVersion.getProject() + ' ' + GeneratedVersion.getVersion());
System.out.println(sdf.format(GeneratedVersion.getBuildDate()));
}
}

View file

@ -1,4 +1,5 @@
#Mon, 18 Jan 2016 00:09:19 -0800
version.project=Example
version.major=3
version.minor=1
version.patch=35

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="semver" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="1.0" type="JAVA_MODULE" version="4">
<module external.linked.project.id="semver" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="1.0.1-beta" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes/main" />
<output-test url="file://$MODULE_DIR$/build/classes/test" />

View file

@ -84,6 +84,7 @@
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="createEmptyContentRootDirectories" value="true" />
<option name="disableWrapperSourceDistributionNotification" value="true" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="C:/gradle" />
@ -298,7 +299,11 @@
</component>
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value />
<value>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
</value>
</option>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Erik's Code Style" />
</component>
@ -321,6 +326,9 @@
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.8.x" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
<component name="libraryTable">
<library name="Gradle: com.beust:jcommander:1.48">
<CLASSES>
@ -349,9 +357,9 @@
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/commons-lang/commons-lang/2.4/2b8c4b3035e45520ef42033e823c7d33e4b4402c/commons-lang-2.4-sources.jar!/" />
</SOURCES>
</library>
<library name="Gradle: net.thauvin.erik:semver:1.0">
<library name="Gradle: net.thauvin.erik:semver:1.0.1-beta">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/net/thauvin/erik/semver/1.0/semver-1.0.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/net/thauvin/erik/semver/1.0.1-beta/semver-1.0.1-beta.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />

View file

@ -64,6 +64,8 @@ public final class Constants
public static final String KEY_VERSION_PRERELEASE = "version.prerelease";
public static final String KEY_VERSION_PROJECT = "version.project";
public static final String VELOCITY_PROPERTIES = "velocity.properties";
/**

View file

@ -71,6 +71,10 @@ public @interface Version
String prereleaseKey() default Constants.KEY_VERSION_PRERELEASE;
String project() default Constants.EMPTY;
String projectKey() default Constants.KEY_VERSION_PROJECT;
String properties() default Constants.EMPTY;
String template() default Constants.DEFAULT_TEMPLATE;

View file

@ -54,6 +54,8 @@ public class VersionInfo
private String prerelease;
private String project;
public VersionInfo()
{
major = Constants.DEFAULT_MAJOR;
@ -61,6 +63,7 @@ public class VersionInfo
patch = Constants.DEFAULT_PATCH;
buildmeta = Constants.EMPTY;
prerelease = Constants.EMPTY;
project = Constants.EMPTY;
}
public VersionInfo(final Version version)
@ -70,6 +73,7 @@ public class VersionInfo
patch = version.patch();
buildmeta = version.buildmeta();
prerelease = version.prerelease();
project = version.project();
}
public String getBuildMetadata()
@ -127,6 +131,16 @@ public class VersionInfo
this.prerelease = prerelease;
}
public String getProject()
{
return project;
}
public void setProject(String project)
{
this.project = project;
}
public String getVersion()
{
return "" + major + '.' + minor + '.' + patch + (prerelease.length() > 0 ? '-' + prerelease : "") + (

View file

@ -93,6 +93,7 @@ public class VersionProcessor extends AbstractProcessor
{
p.load(reader);
versionInfo.setProject(p.getProperty(version.projectKey(), Constants.EMPTY));
versionInfo.setMajor(parseIntProperty(p, version.majorKey(), Constants.DEFAULT_MAJOR));
versionInfo.setMinor(parseIntProperty(p, version.minorKey(), Constants.DEFAULT_MINOR));
versionInfo.setPatch(parseIntProperty(p, version.patchKey(), Constants.DEFAULT_PATCH));
@ -151,15 +152,15 @@ public class VersionProcessor extends AbstractProcessor
@Override
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv)
{
for (final Element annotatedElement : roundEnv.getElementsAnnotatedWith(Version.class))
for (final Element element : roundEnv.getElementsAnnotatedWith(Version.class))
{
final Version version = annotatedElement.getAnnotation(Version.class);
if (annotatedElement.getKind() == ElementKind.CLASS)
final Version version = element.getAnnotation(Version.class);
if (element.getKind() == ElementKind.CLASS)
{
final Element enclosing = annotatedElement.getEnclosingElement();
if (enclosing.getKind() == ElementKind.PACKAGE)
final Element enclosingElement = element.getEnclosingElement();
if (enclosingElement.getKind() == ElementKind.PACKAGE)
{
final PackageElement packageElement = (PackageElement) enclosing;
final PackageElement packageElement = (PackageElement) enclosingElement;
try
{
final VersionInfo versionInfo = findValues(version);
@ -224,6 +225,7 @@ public class VersionProcessor extends AbstractProcessor
final VelocityContext vc = new VelocityContext();
vc.put("packageName", packageName);
vc.put("className", className);
vc.put("project", versionInfo.getProject());
vc.put("buildmeta", versionInfo.getBuildMetadata());
vc.put("epoch", versionInfo.getEpoch());
vc.put("patch", versionInfo.getPatch());

View file

@ -18,6 +18,7 @@ public final class ${className} {
private final static int minor = ${minor};
private final static int patch = ${patch};
private final static String prerelease = "${prerelease}";
private final static String project = "${project}";
/**
* Returns the build date.
@ -77,6 +78,15 @@ public final class ${className} {
return "";
}
/**
* Returns the project name.
*
* @return The project name, if any.
*/
public static String getProject() {
return project;
}
/**
* Returns the build metadata.
*

6
version.properties Normal file
View file

@ -0,0 +1,6 @@
#Sat, 23 Jan 2016 12:11:45 -0800
version.major=1
version.minor=0
version.patch=1
version.buildmeta=
version.prerelease=beta