[jdeb] 01/01: Imported Upstream version 1.3
Tony Mancill
tmancill at moszumanska.debian.org
Sun Dec 6 20:11:14 UTC 2015
This is an automated email from the git hooks/post-receive script.
tmancill pushed a commit to annotated tag upstream/1.3
in repository jdeb.
commit 387f080428d57cd97a6d12ea16c0fd6af835af41
Author: tony mancill <tmancill at debian.org>
Date: Sat Aug 30 22:58:24 2014 -0700
Imported Upstream version 1.3
---
.gitignore | 3 +-
.travis.yml | 2 +-
HISTORY.md | 45 +-
README.md | 16 +-
docs/ant.md | 16 +
docs/maven.md | 123 ++++-
pom.xml | 128 +++--
src/examples/maven/pom.xml | 8 +-
src/it/extension/pom.xml | 23 +
src/it/extension/src/deb/control/control | 7 +
.../main/java/org/vafer/jdeb/examples/Main.java | 7 +
src/it/extension/verify.groovy | 1 +
src/it/pom-only/pom.xml | 1 +
.../java/org/vafer/jdeb/ChangesFileBuilder.java | 160 +++---
src/main/java/org/vafer/jdeb/Compression.java | 164 +++---
src/main/java/org/vafer/jdeb/Console.java | 9 +-
src/main/java/org/vafer/jdeb/ControlBuilder.java | 451 ++++++++-------
src/main/java/org/vafer/jdeb/DataBuilder.java | 614 ++++++++++-----------
src/main/java/org/vafer/jdeb/DataConsumer.java | 4 +-
src/main/java/org/vafer/jdeb/DataProducer.java | 2 +-
src/main/java/org/vafer/jdeb/DebMaker.java | 349 ++++++++++--
.../java/org/vafer/jdeb/PackagingException.java | 2 +-
src/main/java/org/vafer/jdeb/ant/Data.java | 12 +-
src/main/java/org/vafer/jdeb/ant/DebAntTask.java | 8 +-
src/main/java/org/vafer/jdeb/ant/Link.java | 218 ++++----
src/main/java/org/vafer/jdeb/ant/Mapper.java | 10 +-
src/main/java/org/vafer/jdeb/ant/TaskConsole.java | 17 +-
.../java/org/vafer/jdeb/changes/ChangeSet.java | 2 +-
.../org/vafer/jdeb/changes/ChangesProvider.java | 2 +-
.../jdeb/changes/TextfileChangesProvider.java | 2 +-
.../jdeb/debian/BinaryPackageControlFile.java | 16 +-
.../java/org/vafer/jdeb/debian/ChangesFile.java | 32 +-
.../java/org/vafer/jdeb/debian/ControlField.java | 260 ++++-----
.../java/org/vafer/jdeb/debian/ControlFile.java | 102 +++-
src/main/java/org/vafer/jdeb/mapping/LsMapper.java | 2 +-
src/main/java/org/vafer/jdeb/mapping/Mapper.java | 2 +-
.../java/org/vafer/jdeb/mapping/NullMapper.java | 2 +-
.../java/org/vafer/jdeb/mapping/PermMapper.java | 2 +-
.../org/vafer/jdeb/maven/AbstractPluginMojo.java | 47 --
src/main/java/org/vafer/jdeb/maven/Data.java | 97 ++--
src/main/java/org/vafer/jdeb/maven/DebMojo.java | 434 +++++++++++----
src/main/java/org/vafer/jdeb/maven/Mapper.java | 45 +-
.../vafer/jdeb/maven/MissingSourceBehavior.java | 3 +-
.../java/org/vafer/jdeb/maven/MojoConsole.java | 17 +-
.../vafer/jdeb/producers/AbstractDataProducer.java | 24 +-
.../vafer/jdeb/producers/DataProducerArchive.java | 2 +-
.../jdeb/producers/DataProducerDirectory.java | 47 +-
.../org/vafer/jdeb/producers/DataProducerFile.java | 17 +-
.../vafer/jdeb/producers/DataProducerFileSet.java | 10 +-
.../vafer/jdeb/producers/DataProducerFiles.java | 58 ++
.../org/vafer/jdeb/producers/DataProducerLink.java | 11 +-
.../jdeb/producers/DataProducerPathTemplate.java | 15 +-
.../java/org/vafer/jdeb/producers/Producers.java | 116 ++++
.../java/org/vafer/jdeb/signing/PGPSigner.java | 328 ++++++-----
.../java/org/vafer/jdeb/utils/FilteredFile.java | 10 +-
.../vafer/jdeb/utils/InformationInputStream.java | 2 +-
.../vafer/jdeb/utils/InformationOutputStream.java | 2 +-
.../org/vafer/jdeb/utils/MapVariableResolver.java | 2 +-
.../vafer/jdeb/utils/PGPSignatureOutputStream.java | 57 ++
src/main/java/org/vafer/jdeb/utils/Utils.java | 263 +++++++--
.../org/vafer/jdeb/utils/VariableResolver.java | 2 +-
src/main/resources/META-INF/plexus/components.xml | 50 ++
src/test/java/org/vafer/jdeb/ArchiveVisitor.java | 62 +--
src/test/java/org/vafer/jdeb/ArchiveWalker.java | 209 +++----
.../java/org/vafer/jdeb/DataBuilderTestCase.java | 165 +++---
src/test/java/org/vafer/jdeb/DebMakerTestCase.java | 10 +-
.../java/org/vafer/jdeb/EmptyDataProducer.java | 56 +-
src/test/java/org/vafer/jdeb/NullConsole.java | 60 +-
.../org/vafer/jdeb/ant/AntSelectorTestCase.java | 2 +-
.../org/vafer/jdeb/ant/DebAntTaskTestCase.java | 32 +-
.../changes/TextfileChangesProviderTestCase.java | 2 +-
.../org/vafer/jdeb/debian/ChangesFileTestCase.java | 4 +-
.../vafer/jdeb/debian/ControlFieldTestCase.java | 88 +--
.../jdeb/debian/PackageControlFileTestCase.java | 28 +-
.../org/vafer/jdeb/mapping/LsMapperTestCase.java | 2 +-
.../java/org/vafer/jdeb/maven/DataTestCase.java | 2 +-
.../jdeb/producers/DataProducerFilesTestCase.java | 89 +++
.../DataProducerPathTemplateTestCase.java | 2 +-
.../org/vafer/jdeb/signing/DebMakerTestCase.java | 113 ++++
.../org/vafer/jdeb/signing/PGPSignerTestCase.java | 14 +-
.../org/vafer/jdeb/utils/FilteredFileTestCase.java | 11 +-
.../jdeb/utils/InformationInputStreamTestCase.java | 2 +-
.../java/org/vafer/jdeb/utils/UtilsTestCase.java | 55 +-
.../resources/org/vafer/jdeb/deb/control/control | 1 +
src/test/resources/testbuild.xml | 14 +
85 files changed, 3574 insertions(+), 1932 deletions(-)
diff --git a/.gitignore b/.gitignore
index 5f74209..97c5ada 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,4 +9,5 @@ dependency-reduced-pom.xml
*.iws
*.ipr
/.idea
-.release
\ No newline at end of file
+.release
+*~
diff --git a/.travis.yml b/.travis.yml
index 1c86c94..6d16074 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
language: java
jdk:
+ - oraclejdk8
- oraclejdk7
- - oraclejdk6
- openjdk7
- openjdk6
diff --git a/HISTORY.md b/HISTORY.md
index bf3d6ae..ce8029e 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,11 +1,44 @@
-## Version 1.1, released ?
+## Version 1.3.1, in progress
+## Version 1.3, released 25.07.2014
+
+* [CHG] Switched from maven2 to maven3
+* [FIX] Fixed badly formatted version for "milestone", "m", "a", "b" and "cr" (they where not matched as beta versions)
+* [FIX] Add two spaces in the md5sums file between the checksum and the filename to be compatible with GNU coreutils md5sum
+
+## Version 1.2, released 22.06.2014
+
+* [CHG] Deprecated "submodules" in favour of "skipSubmodules"
+* [FIX] Warned about missing signing settings even when not signing
+* [FIX] Fixed variable replacement issue on line endings
+* [ADD] Support <packaging>deb</packaging> in Maven
+* [ADD] Support for "signMethod" and "signRole"
+* [ADD] Added "skipPOMs"
+
+## Version 1.1.1, released 10.03.2014
+
+* [FIX] renamed SNAPSHOT handling to snapshotExpand & snapshotEnv
+
+## Version 1.1, released 28.02.2014
+
+* [CHG] Renamed configuration option 'disabled' to 'skip'
+* [ADD] Added support for conffiles (Thanks to Lukas Roedl)
+* [ADD] Added "files" data producer (Thanks to Roman Kashitsyn)
+* [FIX] Better token parsing
+* [ADD] Added support "Distribution" field
+* [ADD] Added support of maven-encrypted passphrases
* [ADD] xz compression support
* [ADD] Added link support to the Ant task
+* [ADD] Added support for system properties in parsed files (Thanks to David Sauer)
* [ADD] Support permission in (hard) link setup
+* [ADD] User defined fields in the control file are now supported (Thanks to Marco Soeima)
+* [ADD] Added the ability to disable an execution during Maven build (Thanks to Jonathan Piron)
* [FIX] On Windows, parent directories are now created automatically when adding files to the data archive
* [CHG] Links are now symbolic by default
-
+* [CHG] Alpha, Beta and RC versions are transformed to a package version ordered before the final release (ex: 1.0~RC1)
+* [FIX] Permission mappers now work properly with Ant (Thanks to Christian Egli)
+* [FIX] Symbolic links longer than 100 characters are now supported
+* [FIX] The signed changes files now pass the validation with gpg --verify (Thanks to Max Garmash and Roman Kashitsyn)
## Version 1.0.1, released 28.02.2013
@@ -49,7 +82,7 @@ Some smaller fixes, Support for the 1.8 format, Changes support working.
* [FIX] Default path for changes file with Maven
* [FIX] Unresolved variables are now treated as null
-* [CHG] "Changes" support version 1.8
+* [CHG] "Changes" support version 1.8
* [CHG] Warn if control files have non-unix line endings
* [CHG] Throw an exception for unknown mappers
* [REM] InvalidDescriptorException, wasn't really used anyway
@@ -80,9 +113,9 @@ Many improvements on the Ant task.
Quite a few fixes related to locale settings.
Support for bzip2 and more descriptor keys.
-* [FIX] English locale for date format.
-* [FIX] Proper installation size to be kbytes instead of bytes.
-* [FIX] Close streams properly.
+* [FIX] English locale for date format.
+* [FIX] Proper installation size to be kbytes instead of bytes.
+* [FIX] Close streams properly.
* [CHG] The Ant task now breaks on errors.
* [ADD] Support for bzip2 compression in data element of the Ant task.
* [ADD] Compression attribute to specify data file compression (bzip2, gzip, none).
diff --git a/README.md b/README.md
index 16850e9..1ab576b 100644
--- a/README.md
+++ b/README.md
@@ -5,20 +5,18 @@
This library provides an Ant task and a Maven plugin to create Debian packages
from Java builds in a truly cross platform manner. Build your Debian packages
on any platform that has Java support. Windows, Linux, OS X - it doesn't require
-additional native tools installed. The API underneath is well abstracted and
-can easily be adopted for other areas as well.
+additional native tools installed.
Check the documentation on how to use it with [Maven](http://github.com/tcurdt/jdeb/blob/master/docs/maven.md)
or [Ant](http://github.com/tcurdt/jdeb/blob/master/docs/ant.md). Especially don't forget to check out the
[examples](http://github.com/tcurdt/jdeb/blob/master/src/examples/). Current
-[javadocs](http://tcurdt.github.com/jdeb/release/1.0.1/apidocs/) and a source
-[xref](http://tcurdt.github.com/jdeb/release/1.0.1/xref/) is also available.
+[javadocs](http://tcurdt.github.com/jdeb/release/1.3/apidocs/) and a source
+[xref](http://tcurdt.github.com/jdeb/release/1.3/xref/) is also available.
## Where to get it
The jars are available in the [Maven central repository](http://repo1.maven.org/maven2/org/vafer/jdeb/).
-The source releases you can get in the [download section](http://github.com/tcurdt/jdeb/downloads).
If feel adventures or want to help out feel free to get the latest code
[via git](http://github.com/tcurdt/jdeb/tree/master).
@@ -26,11 +24,15 @@ If feel adventures or want to help out feel free to get the latest code
git clone git://github.com/tcurdt/jdeb.git
+## Working towards jdeb 2.0
+
+Over the years jdeb has grown more and more powerful - but also got more complex. In order to simplify the usage and apply what we have learned we are taking a step back. If you want to help to shape the usage of jdeb 2.0 feel free to contribute on the [gist](https://gist.github.com/tcurdt/9275523) where we want to iterate on the maven and ant interfaces.
+
+
## Related projects
Some links to other cross platform tools to package Linux applications:
-
+* [apt-repo](https://github.com/theoweiss/apt-repo)
* [ant-deb-task](http://code.google.com/p/ant-deb-task)
* [jRPM](http://jrpm.sourceforge.net)
-* [RedLine](http://www.freecompany.org/redline)
* [Install-Toolkit](http://install-toolkit.sourceforge.net)
diff --git a/docs/ant.md b/docs/ant.md
index a27cb87..b07a69c 100644
--- a/docs/ant.md
+++ b/docs/ant.md
@@ -166,3 +166,19 @@ Then you can sign your changes file with:
<b>Security Note</b>: Hard coding the passphrase in the `<deb>` task can be a serious
security hole. Consider using variable substitution and asking the passphrase
to the user with the `<input>` task, or retrieving it from a secured `.properties` file.
+
+## Conffiles file
+
+If you package up a directory as Debian package you can also add the affected files to
+the conffiles file. You only have to set the `conffile` attribute to `true`.
+
+```xml
+ <target name="package">
+ <taskdef name="deb" classname="org.vafer.jdeb.ant.DebAntTask"/>
+ <deb destfile="jdeb.deb" control="${deb}/control">
+ <data src="src/main/resources/deb/data" type="directory" conffile="true">
+ <exclude name="**/.svn"/>
+ </data>
+ </deb>
+ </target>
+```
diff --git a/docs/maven.md b/docs/maven.md
index 83e825c..87b4f6c 100644
--- a/docs/maven.md
+++ b/docs/maven.md
@@ -9,7 +9,7 @@ the plugin to your POM like this
<plugin>
<artifactId>jdeb</artifactId>
<groupId>org.vafer</groupId>
- <version>1.0</version>
+ <version>1.3</version>
<executions>
<execution>
<phase>package</phase>
@@ -35,11 +35,48 @@ the plugin to your POM like this
</build>
```
+Or if you want to build a custom deb file
+
+```xml
+ <!-- Indicate it's a deb package which will automatically execute jdeb goal -->
+ <packaging>deb</packaging>
+
+ <build>
+ <extensions>
+ <!-- Add support for the "deb" packaging -->
+ <extension>
+ <groupId>org.vafer</groupId>
+ <artifactId>jdeb</artifactId>
+ <version>1.3</version>
+ </extension>
+ </extensions>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>jdeb</artifactId>
+ <groupId>org.vafer</groupId>
+ <!-- Customize deb package -->
+ <configuration>
+ <dataSet>
+ <data>
+ <src>${project.build.directory}/preparedfiles</src>
+ <type>directory</type>
+ <mapper>
+ <type>perm</type>
+ <prefix>/usr/lib/xwiki/myproject</prefix>
+ </mapper>
+ </data>
+ </dataSet>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+```
+
At least the one main control file is required to control the creation of the
debian package. This required control file should be found in the control
-directory. By default the control file name is also `control` which gives a
-path of `src/deb/control/control` by default. This control file contains the
-metadata about the Debian package. Usually it will look something along the lines of
+directory (inside the data dir). By default the control file name is also `control` which gives a path of `src/deb/control/control` by default. This control file contains the metadata about the Debian package. Usually it will look something along the lines of
Package: [[name]]
Version: [[version]]
@@ -51,6 +88,7 @@ metadata about the Debian package. Usually it will look something along the line
Description: jetty java servlet container
Distribution: development
+but check out the [exmample](https://github.com/tcurdt/jdeb/tree/master/src/examples/maven) to get a better overview.
If the environment variables `DEBEMAIL` and `DEBFULLNAME` are both set this
will overrule the `Maintainer` field set in there. The `Installed-Size` will
@@ -86,13 +124,21 @@ changesIn | The changes to add
changesOut | The changes file generated | No
changesSave | (NYI) The merged changes file | No
compression | (NYI) Compression method for the data file (`gzip`, `bzip2`, `xz` or `none`) | No; defaults to `gzip`
-keyring | (NYI) The file containing the PGP keys | No
-key | (NYI) The name of the key to be used in the keyring | No
-passphrase | (NYI) The passphrase to use the key | No
+signPackage | If the debian package should be signed | No
+signMethod | Which utility is used for verification (`dpkg-sig`, `debsig-verify`) | No; defaults to `debsig-verify`
+signRole | Determines the filename of the signature, debsig only verifies `origin` | No; defaults to `origin`
+signCfgPrefix | Prefix for when reading keyring, key and passphrase from settings.xml | No; defaults to `jdeb.`
+keyring | The file containing the PGP keys | No
+key | The name of the key to be used in the keyring | No
+passphrase | The passphrase to use the key | No
attach | Attach artifact to project | No; defaults to `true`
-submodules | Execute the goal on all sub-modules | No; defaults to `true`
-timestamped | Turn SNAPSHOT into timestamps | No; defaults to `false`
+snapshotExpand| Expand SNAPSHOT into the content of an environment variable or timestamp. | No; defaults to `false`
+snapshotEnv | Name of the environment variable. If it's empty defaults to a timestamp. | No; defaults to `SNAPSHOT`
verbose | Verbose logging | No; defaults to `true`, will be `false` in the future
+skip | Indicates if an execution should be skipped | No; defaults to `false`
+skipSubmodules| Skip goal on all submodules | No; defaults to `false`
+skipPOMs | Skip goal on POM artifacts | No; defaults to `true`
+
If you use the `dataSet` element, you'll need to populate it with a one or
more `data` elements. A `data` element is used to specify a directory, a
@@ -106,10 +152,12 @@ src | The directory, tarball, file to include in the package
dst | New filename at destination (type must be `file`) | No
linkName | The path of the link (type must be `link`) | Yes for link
linkTarget | The target of the link (type must be `link`) | Yes for link
-type | Type of the data source. (archive, directory, file, link or template) | No; but will be Yes in the future
+symlink | Indicate if the link is a symblolic link (type must be `link`) | No; defaults to `true`
+type | Type of the data source. (archive, directory, file, files, link or template) | No; but will be Yes in the future
missingSrc | Fail if src file/folder is missing (ignore or fail) | No; defaults to `fail`
includes | A comma seperated list of files to include from the directory or tarball | No; defaults to all files
excludes | A comma seperated list of files to exclude from the directory or tarball | No; defaults to no exclutions
+conffile | A boolean value to define if the files should be included in the conffiles | No; defaults to `false`
mapper | The files to exclude from the directory or tarball | No
paths/(path..) | One or more string literal paths that will created in the package | No; Yes for type `template`
@@ -123,12 +171,12 @@ uid | Numerical uid | No; defa
gid | Numerical gid | No; defaults to 0
user | User name | No; defaults to "root"
group | User group | No; defaults to "root"
-filemode | File permissions as octet | No; deftauls to 644
+filemode | File permissions as octet | No; defaults to 644
dirmode | Dir permissions as octet | No; defaults to 755
strip | Strip n path components from the original file | No; defaults to 0
Below is an example of how you could configure your jdeb maven plugin to
-include a directory, a tarball, and a file in your deb package:
+include a directory, a tarball, and a file in your deb package and then sign it with the key 8306FE21 in /home/user/.gnupg/secring.gpg:
```xml
<build>
@@ -136,7 +184,7 @@ include a directory, a tarball, and a file in your deb package:
<plugin>
<artifactId>jdeb</artifactId>
<groupId>org.vafer</groupId>
- <version>1.0</version>
+ <version>1.3</version>
<executions>
<execution>
<phase>package</phase>
@@ -144,6 +192,12 @@ include a directory, a tarball, and a file in your deb package:
<goal>jdeb</goal>
</goals>
<configuration>
+ <signPackage>true</signPackage>
+ <signMethod>dpkg-sig</signMethod>
+ <signRole>builder</signRole>
+ <keyring>/home/user/.gnupg/secring.gpg</keyring>
+ <key>8306FE21</key>
+ <passphrase>abcdef</passphrase>
<dataSet>
@@ -183,6 +237,16 @@ include a directory, a tarball, and a file in your deb package:
<missingSrc>ignore</missingSrc>
</data>
+ <!-- Multiple files example -->
+ <data>
+ <type>files</type>
+ <paths>
+ <path>README.txt</path>
+ <path>CHANGES.txt</path>
+ </paths>
+ <dst>/var/lib/${artifactId}</dst>
+ </data>
+
<!-- Template example -->
<data>
<type>template</type>
@@ -209,6 +273,19 @@ include a directory, a tarball, and a file in your deb package:
<linkTarget>/a/sym/link/to/the/scr/file</linkTarget>
<symlink>true</symlink>
</data>
+
+ <!-- Conffiles example -->
+ <data>
+ <src>${project.build.directory}/data</src>
+ <type>directory</type>
+ <includes/>
+ <excludes>**/.svn</excludes>
+ <conffile>true</conffile>
+ <mapper>
+ <type>ls</type>
+ <src>mapping.txt</src>
+ </mapper>
+ </data>
</dataSet>
</configuration>
@@ -218,3 +295,23 @@ include a directory, a tarball, and a file in your deb package:
</plugins>
</build>
```
+If you don't want to store your key information in the POM you can store this is your settings.xml, here's an example settings.xml:
+
+```xml
+ <settings>
+ <profiles>
+ <profile>
+ <id>jdeb-signing</id>
+ <properties>
+ <jdeb.keyring>/home/user/.gnupg/secring.gpg</jdeb.keyring>
+ <jdeb.key>8306FE21</jdeb.key>
+ <jdeb.passphrase>abcdef</jdeb.passphrase>
+ </properties>
+ </profile>
+ </profiles>
+ <activeProfiles>
+ <activeProfile>jdeb-signing</activeProfile>
+ </activeProfiles>
+ </settings>
+```
+keyring, key and passphrase can then be omitted from the POM entirely.
diff --git a/pom.xml b/pom.xml
index d6d4991..1731c8d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
<artifactId>jdeb</artifactId>
<packaging>maven-plugin</packaging>
<name>jdeb</name>
- <version>1.0.2-SNAPSHOT</version>
+ <version>1.3</version>
<description>
This library provides an Ant task and a Maven plugin to create Debian packages from Java builds in a truly cross
platform manner. Build your Debian packages on any platform that has Java support. Windows, Linux, OS X - it doesn't
@@ -34,16 +34,25 @@
</developer>
</developers>
<contributors>
+ <contributor><name>Alexander Horz</name></contributor>
+ <contributor><name>Ben McCann</name></contributor>
<contributor><name>Bryan Sant</name></contributor>
+ <contributor><name>Christian Egli</name></contributor>
<contributor><name>Christian Rigdon</name></contributor>
+ <contributor><name>David Sauer</name></contributor>
<contributor><name>Elliot West</name></contributor>
<contributor><name>Jeroen Rosenberg</name></contributor>
+ <contributor><name>Lukas Roedl</name></contributor>
<contributor><name>Manuel Woelker</name></contributor>
+ <contributor><name>Marco Soeima</name></contributor>
+ <contributor><name>Max Garmash</name></contributor>
+ <contributor><name>Nepomuk Seiler</name></contributor>
<contributor><name>Patrick Schultz</name></contributor>
<contributor><name>Petr Kozelka</name></contributor>
- <contributor><name>Scott Kuehn</name></contributor>
<contributor><name>Ralph van Etten</name></contributor>
- <contributor><name>Alexander Horz</name></contributor>
+ <contributor><name>Roman Kashitsyn</name></contributor>
+ <contributor><name>Scott Kuehn</name></contributor>
+ <contributor><name>Sergio Fernández</name></contributor>
</contributors>
<licenses>
<license>
@@ -62,13 +71,35 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
+ <mavenVersion>3.2.2</mavenVersion>
+ <mavenPluginPluginVersion>3.3</mavenPluginPluginVersion>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-site-plugin</artifactId>
- <version>3.1</version>
+ <version>3.4</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-plugin-plugin</artifactId>
+ <version>${mavenPluginPluginVersion}</version>
+ <configuration>
+ <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
+ <extractors>
+ <extractor>java-annotations</extractor>
+ </extractors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>mojo-descriptor</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>descriptor</goal>
+ </goals>
+ </execution>
+ </executions>
</plugin>
</plugins>
</pluginManagement>
@@ -76,7 +107,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
- <version>2.5.1</version>
+ <version>3.1</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
@@ -86,7 +117,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
- <version>1.7.1</version>
+ <version>2.3</version>
<executions>
<execution>
<phase>package</phase>
@@ -96,10 +127,22 @@
<configuration>
<!-- <dependencyReducedPomLocation>${basedir}/target/dependency-reduced-pom.xml</dependencyReducedPomLocation> -->
<minimizeJar>true</minimizeJar>
+ <filters>
+ <filter>
+ <artifact>*:*</artifact>
+ <excludes>
+ <exclude>META-INF/*.SF</exclude>
+ <exclude>META-INF/*.DSA</exclude>
+ <exclude>META-INF/*.RSA</exclude>
+ </excludes>
+ </filter>
+ </filters>
<artifactSet>
<includes>
<include>org.apache.commons:commons-compress</include>
<include>commons-io:commons-io</include>
+ <include>org.bouncycastle:bcpg-jdk15on</include>
+ <include>org.bouncycastle:bcprov-jdk15on</include>
</includes>
</artifactSet>
<relocations>
@@ -107,6 +150,10 @@
<pattern>org.apache.commons</pattern>
<shadedPattern>org.vafer.jdeb.shaded.compress</shadedPattern>
</relocation>
+ <relocation>
+ <pattern>org.bouncycastle</pattern>
+ <shadedPattern>org.vafer.jdeb.shaded.bc</shadedPattern>
+ </relocation>
</relocations>
</configuration>
</execution>
@@ -115,7 +162,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
- <version>2.11</version>
+ <version>2.17</version>
<configuration>
<forkMode>never</forkMode>
<includes>
@@ -131,27 +178,23 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-invoker-plugin</artifactId>
- <version>1.6</version>
+ <version>1.9</version>
<configuration>
- <!-- <debug>true</debug> -->
- <projectsDirectory>src/it</projectsDirectory>
<cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
- <preBuildHookScript>setup</preBuildHookScript>
- <postBuildHookScript>verify</postBuildHookScript>
<localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>
<settingsFile>src/it/settings.xml</settingsFile>
- <pomIncludes>
- <pomInclude>*/pom.xml</pomInclude>
- </pomIncludes>
+ <goals>
+ <goal>clean</goal>
+ <goal>package</goal>
+ </goals>
+ <debug>true</debug>
</configuration>
<executions>
<execution>
+ <id>integration-test</id>
<goals>
- <goal>integration-test</goal>
- <!--
- <goal>verify</goal>
- <goal>install</goal>
- -->
+ <goal>install</goal>
+ <goal>run</goal>
</goals>
</execution>
</executions>
@@ -162,49 +205,40 @@
<!-- mvn versions:display-dependency-updates -->
<!-- mvn versions:display-plugin-updates -->
<dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>2.4</version>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
- <version>1.5</version>
+ <version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
- <version>2.2.1</version>
+ <version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
- <version>2.2.1</version>
- </dependency>
- <dependency>
- <groupId>org.apache.maven</groupId>
- <artifactId>maven-project</artifactId>
- <version>2.2.1</version>
- </dependency>
- <dependency>
- <groupId>org.apache.maven</groupId>
- <artifactId>maven-artifact</artifactId>
- <version>2.2.1</version>
+ <version>${mavenVersion}</version>
</dependency>
<dependency>
- <groupId>org.codehaus.plexus</groupId>
- <artifactId>plexus-utils</artifactId>
- <version>1.4.1</version>
+ <groupId>org.apache.maven.plugin-tools</groupId>
+ <artifactId>maven-plugin-annotations</artifactId>
+ <version>${mavenPluginPluginVersion}</version>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
- <version>1.7.1</version>
+ <version>1.9.3</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk15on</artifactId>
- <version>1.48</version>
+ <version>1.51</version>
</dependency>
<dependency>
<groupId>junit</groupId>
@@ -212,6 +246,12 @@
<version>3.8.2</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>1.9.5</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<reporting>
<excludeDefaults>true</excludeDefaults>
@@ -250,17 +290,17 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
- <version>2.12</version>
+ <version>2.17</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
- <version>2.7.1</version>
+ <version>3.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
- <version>2.3</version>
+ <version>2.4</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
diff --git a/src/examples/maven/pom.xml b/src/examples/maven/pom.xml
index 9a61bc5..fc543cf 100644
--- a/src/examples/maven/pom.xml
+++ b/src/examples/maven/pom.xml
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.vafer</groupId>
<artifactId>jdeb-example</artifactId>
- <version>1.0</version>
+ <version>1.0-SNAPSHOT</version>
<description>description from pom</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -14,7 +14,7 @@
<plugin>
<artifactId>jdeb</artifactId>
<groupId>org.vafer</groupId>
- <version>1.0</version>
+ <version>1.3</version>
<executions>
<execution>
<phase>package</phase>
@@ -23,6 +23,10 @@
</goals>
<configuration>
<verbose>true</verbose>
+ <snapshotExpand>true</snapshotExpand>
+ <!-- expand "SNAPSHOT" to what is in the "USER" env variable -->
+ <snapshotEnv>USER</snapshotEnv>
+ <verbose>true</verbose>
<controlDir>${basedir}/src/deb/control</controlDir>
<dataSet>
diff --git a/src/it/extension/pom.xml b/src/it/extension/pom.xml
new file mode 100644
index 0000000..1bbf950
--- /dev/null
+++ b/src/it/extension/pom.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.vafer</groupId>
+ <artifactId>jdeb-it</artifactId>
+ <version>1.0</version>
+ <packaging>deb</packaging>
+ <description>description from pom</description>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ </properties>
+ <build>
+ <extensions>
+ <!-- Add support for the "deb" packaging -->
+ <extension>
+ <groupId>org.vafer</groupId>
+ <artifactId>jdeb</artifactId>
+ <version>@project.version@</version>
+ </extension>
+ </extensions>
+ </build>
+</project>
diff --git a/src/it/extension/src/deb/control/control b/src/it/extension/src/deb/control/control
new file mode 100644
index 0000000..6cfaa51
--- /dev/null
+++ b/src/it/extension/src/deb/control/control
@@ -0,0 +1,7 @@
+Package: [[name]]
+Version: [[version]]
+Section: misc
+Priority: low
+Architecture: all
+Description: [[description]]
+Maintainer: tcurdt at vafer.org
diff --git a/src/it/extension/src/main/java/org/vafer/jdeb/examples/Main.java b/src/it/extension/src/main/java/org/vafer/jdeb/examples/Main.java
new file mode 100644
index 0000000..62a2434
--- /dev/null
+++ b/src/it/extension/src/main/java/org/vafer/jdeb/examples/Main.java
@@ -0,0 +1,7 @@
+package org.vafer.jdeb.examples;
+
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("jdeb example!");
+ }
+}
diff --git a/src/it/extension/verify.groovy b/src/it/extension/verify.groovy
new file mode 100644
index 0000000..d2980bc
--- /dev/null
+++ b/src/it/extension/verify.groovy
@@ -0,0 +1 @@
+assert new File( basedir, 'target/jdeb-it_1.0_all.deb' ).exists();
diff --git a/src/it/pom-only/pom.xml b/src/it/pom-only/pom.xml
index 6a0cc16..3be21ed 100644
--- a/src/it/pom-only/pom.xml
+++ b/src/it/pom-only/pom.xml
@@ -24,6 +24,7 @@
</goals>
<configuration>
<verbose>true</verbose>
+ <skipPOMs>false</skipPOMs>
<controlDir>${basedir}/src/deb/control</controlDir>
</configuration>
</execution>
diff --git a/src/main/java/org/vafer/jdeb/ChangesFileBuilder.java b/src/main/java/org/vafer/jdeb/ChangesFileBuilder.java
index 5da3367..390fae8 100644
--- a/src/main/java/org/vafer/jdeb/ChangesFileBuilder.java
+++ b/src/main/java/org/vafer/jdeb/ChangesFileBuilder.java
@@ -1,80 +1,80 @@
-/*
- * Copyright 2013 The Apache Software Foundation.
- *
- * 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 org.vafer.jdeb;
-
-import java.io.File;
-import java.io.IOException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Date;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.output.NullOutputStream;
-import org.vafer.jdeb.changes.ChangesProvider;
-import org.vafer.jdeb.debian.BinaryPackageControlFile;
-import org.vafer.jdeb.debian.ChangesFile;
-import org.vafer.jdeb.utils.InformationOutputStream;
-
-/**
- * Builds the Debian changes file.
- */
-class ChangesFileBuilder {
-
- public ChangesFile createChanges(BinaryPackageControlFile packageControlFile, File binaryPackage, ChangesProvider changesProvider) throws IOException, PackagingException {
-
- ChangesFile changesFile = new ChangesFile();
- changesFile.setChanges(changesProvider.getChangesSets());
- changesFile.initialize(packageControlFile);
-
- changesFile.set("Date", ChangesFile.DATE_FORMAT.format(new Date()));
-
- try {
- // compute the checksums of the binary package
- InformationOutputStream md5output = new InformationOutputStream(new NullOutputStream(), MessageDigest.getInstance("MD5"));
- InformationOutputStream sha1output = new InformationOutputStream(md5output, MessageDigest.getInstance("SHA1"));
- InformationOutputStream sha256output = new InformationOutputStream(sha1output, MessageDigest.getInstance("SHA-256"));
-
- FileUtils.copyFile(binaryPackage, sha256output);
-
- // Checksums-Sha1:
- // 56ef4c6249dc3567fd2967f809c42d1f9b61adf7 45964 jdeb.deb
- changesFile.set("Checksums-Sha1", sha1output.getHexDigest() + " " + binaryPackage.length() + " " + binaryPackage.getName());
-
- // Checksums-Sha256:
- // 38c6fa274eb9299a69b739bcbdbd05c7ffd1d8d6472f4245ed732a25c0e5d616 45964 jdeb.deb
- changesFile.set("Checksums-Sha256", sha256output.getHexDigest() + " " + binaryPackage.length() + " " + binaryPackage.getName());
-
- StringBuilder files = new StringBuilder(md5output.getHexDigest());
- files.append(' ').append(binaryPackage.length());
- files.append(' ').append(packageControlFile.get("Section"));
- files.append(' ').append(packageControlFile.get("Priority"));
- files.append(' ').append(binaryPackage.getName());
- changesFile.set("Files", files.toString());
-
- } catch (NoSuchAlgorithmException e) {
- throw new PackagingException("Unable to compute the checksums for " + binaryPackage, e);
- }
-
- if (!changesFile.isValid()) {
- throw new PackagingException("Changes file fields are invalid " + changesFile.invalidFields() +
- ". The following fields are mandatory: " + changesFile.getMandatoryFields() +
- ". Please check your pom.xml/build.xml and your control file.");
- }
-
- return changesFile;
- }
-}
+/*
+ * Copyright 2014 The Apache Software Foundation.
+ *
+ * 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 org.vafer.jdeb;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Date;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.output.NullOutputStream;
+import org.vafer.jdeb.changes.ChangesProvider;
+import org.vafer.jdeb.debian.BinaryPackageControlFile;
+import org.vafer.jdeb.debian.ChangesFile;
+import org.vafer.jdeb.utils.InformationOutputStream;
+
+/**
+ * Builds the Debian changes file.
+ */
+class ChangesFileBuilder {
+
+ public ChangesFile createChanges(BinaryPackageControlFile packageControlFile, File binaryPackage, ChangesProvider changesProvider) throws IOException, PackagingException {
+
+ ChangesFile changesFile = new ChangesFile();
+ changesFile.setChanges(changesProvider.getChangesSets());
+ changesFile.initialize(packageControlFile);
+
+ changesFile.set("Date", ChangesFile.formatDate(new Date()));
+
+ try {
+ // compute the checksums of the binary package
+ InformationOutputStream md5output = new InformationOutputStream(new NullOutputStream(), MessageDigest.getInstance("MD5"));
+ InformationOutputStream sha1output = new InformationOutputStream(md5output, MessageDigest.getInstance("SHA1"));
+ InformationOutputStream sha256output = new InformationOutputStream(sha1output, MessageDigest.getInstance("SHA-256"));
+
+ FileUtils.copyFile(binaryPackage, sha256output);
+
+ // Checksums-Sha1:
+ // 56ef4c6249dc3567fd2967f809c42d1f9b61adf7 45964 jdeb.deb
+ changesFile.set("Checksums-Sha1", sha1output.getHexDigest() + " " + binaryPackage.length() + " " + binaryPackage.getName());
+
+ // Checksums-Sha256:
+ // 38c6fa274eb9299a69b739bcbdbd05c7ffd1d8d6472f4245ed732a25c0e5d616 45964 jdeb.deb
+ changesFile.set("Checksums-Sha256", sha256output.getHexDigest() + " " + binaryPackage.length() + " " + binaryPackage.getName());
+
+ StringBuilder files = new StringBuilder(md5output.getHexDigest());
+ files.append(' ').append(binaryPackage.length());
+ files.append(' ').append(packageControlFile.get("Section"));
+ files.append(' ').append(packageControlFile.get("Priority"));
+ files.append(' ').append(binaryPackage.getName());
+ changesFile.set("Files", files.toString());
+
+ } catch (NoSuchAlgorithmException e) {
+ throw new PackagingException("Unable to compute the checksums for " + binaryPackage, e);
+ }
+
+ if (!changesFile.isValid()) {
+ throw new PackagingException("Changes file fields are invalid " + changesFile.invalidFields() +
+ ". The following fields are mandatory: " + changesFile.getMandatoryFields() +
+ ". Please check your pom.xml/build.xml and your control file.");
+ }
+
+ return changesFile;
+ }
+}
diff --git a/src/main/java/org/vafer/jdeb/Compression.java b/src/main/java/org/vafer/jdeb/Compression.java
index 5ab1a6c..1d1c0e3 100644
--- a/src/main/java/org/vafer/jdeb/Compression.java
+++ b/src/main/java/org/vafer/jdeb/Compression.java
@@ -1,82 +1,82 @@
-/*
- * Copyright 2013 The jdeb developers.
- *
- * 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 org.vafer.jdeb;
-
-import java.io.OutputStream;
-
-import org.apache.commons.compress.compressors.CompressorException;
-import org.apache.commons.compress.compressors.CompressorStreamFactory;
-
-/**
- * Compression method used for the data file.
- *
- * @author Emmanuel Bourg
- */
-public enum Compression {
-
- NONE(""),
- GZIP(".gz"),
- BZIP2(".bz2"),
- XZ(".xz");
-
- private String extension;
-
- private Compression(String extension) {
- this.extension = extension;
- }
-
- /**
- * Returns the extension of the compression method
- */
- public String getExtension() {
- return extension;
- }
-
- public OutputStream toCompressedOutputStream(OutputStream out) throws CompressorException {
- switch (this) {
- case GZIP:
- return new CompressorStreamFactory().createCompressorOutputStream("gz", out);
- case BZIP2:
- return new CompressorStreamFactory().createCompressorOutputStream("bzip2", out);
- case XZ:
- return new CompressorStreamFactory().createCompressorOutputStream("xz", out);
- default:
- return out;
- }
- }
-
- /**
- * Returns the compression method corresponding to the specified name.
- * The matching is case insensitive.
- *
- * @param name the name of the compression method
- * @return the compression method, or null if not recognized
- */
- public static Compression toEnum(String name) {
- if ("gzip".equalsIgnoreCase(name) || "gz".equalsIgnoreCase(name)) {
- return GZIP;
- } else if ("bzip2".equalsIgnoreCase(name) || "bz2".equalsIgnoreCase(name)) {
- return BZIP2;
- } else if ("xz".equalsIgnoreCase(name)) {
- return XZ;
- } else if ("none".equalsIgnoreCase(name)) {
- return NONE;
- } else {
- return null;
- }
- }
-}
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb;
+
+import java.io.OutputStream;
+
+import org.apache.commons.compress.compressors.CompressorException;
+import org.apache.commons.compress.compressors.CompressorStreamFactory;
+
+/**
+ * Compression method used for the data file.
+ *
+ * @author Emmanuel Bourg
+ */
+public enum Compression {
+
+ NONE(""),
+ GZIP(".gz"),
+ BZIP2(".bz2"),
+ XZ(".xz");
+
+ private String extension;
+
+ private Compression(String extension) {
+ this.extension = extension;
+ }
+
+ /**
+ * Returns the extension of the compression method
+ */
+ public String getExtension() {
+ return extension;
+ }
+
+ public OutputStream toCompressedOutputStream(OutputStream out) throws CompressorException {
+ switch (this) {
+ case GZIP:
+ return new CompressorStreamFactory().createCompressorOutputStream("gz", out);
+ case BZIP2:
+ return new CompressorStreamFactory().createCompressorOutputStream("bzip2", out);
+ case XZ:
+ return new CompressorStreamFactory().createCompressorOutputStream("xz", out);
+ default:
+ return out;
+ }
+ }
+
+ /**
+ * Returns the compression method corresponding to the specified name.
+ * The matching is case insensitive.
+ *
+ * @param name the name of the compression method
+ * @return the compression method, or null if not recognized
+ */
+ public static Compression toEnum(String name) {
+ if ("gzip".equalsIgnoreCase(name) || "gz".equalsIgnoreCase(name)) {
+ return GZIP;
+ } else if ("bzip2".equalsIgnoreCase(name) || "bz2".equalsIgnoreCase(name)) {
+ return BZIP2;
+ } else if ("xz".equalsIgnoreCase(name)) {
+ return XZ;
+ } else if ("none".equalsIgnoreCase(name)) {
+ return NONE;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/vafer/jdeb/Console.java b/src/main/java/org/vafer/jdeb/Console.java
index b0b21cf..2e18553 100644
--- a/src/main/java/org/vafer/jdeb/Console.java
+++ b/src/main/java/org/vafer/jdeb/Console.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.vafer.jdeb;
/**
@@ -22,8 +23,10 @@ package org.vafer.jdeb;
*/
public interface Console {
- void info( String s );
+ void debug( String message );
+
+ void info( String message );
- void warn( String s );
+ void warn( String message );
}
diff --git a/src/main/java/org/vafer/jdeb/ControlBuilder.java b/src/main/java/org/vafer/jdeb/ControlBuilder.java
index fdb4e7e..8fa58ec 100644
--- a/src/main/java/org/vafer/jdeb/ControlBuilder.java
+++ b/src/main/java/org/vafer/jdeb/ControlBuilder.java
@@ -1,208 +1,243 @@
-/*
- * Copyright 2013 The jdeb developers.
- *
- * 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 org.vafer.jdeb;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.text.ParseException;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.zip.GZIPOutputStream;
-
-import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
-import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.output.NullOutputStream;
-import org.apache.tools.ant.DirectoryScanner;
-import org.vafer.jdeb.debian.BinaryPackageControlFile;
-import org.vafer.jdeb.mapping.PermMapper;
-import org.vafer.jdeb.utils.FilteredFile;
-import org.vafer.jdeb.utils.InformationInputStream;
-import org.vafer.jdeb.utils.Utils;
-import org.vafer.jdeb.utils.VariableResolver;
-
-/**
- * Builds the control archive of the Debian package.
- */
-class ControlBuilder {
-
- /** The name of the package maintainer scripts */
- private static final Set<String> MAINTAINER_SCRIPTS = new HashSet<String>(Arrays.asList("preinst", "postinst", "prerm", "postrm", "config"));
-
- /** The name of the other control files subject to token substitution */
- private static final Set<String> CONFIGURATION_FILENAMES = new HashSet<String>(Arrays.asList("conffiles", "templates", "triggers"));
-
- private Console console;
- private VariableResolver resolver;
-
- ControlBuilder(Console console, VariableResolver resolver) {
- this.console = console;
- this.resolver = resolver;
- }
-
- /**
- * Build control archive of the deb
- *
- * @param packageControlFile the package control file
- * @param controlFiles the other control information files (maintainer scripts, etc)
- * @param dataSize the size of the installed package
- * @param checksums the md5 checksums of the files in the data archive
- * @param output
- * @return
- * @throws java.io.FileNotFoundException
- * @throws java.io.IOException
- * @throws java.text.ParseException
- */
- void buildControl(BinaryPackageControlFile packageControlFile, File[] controlFiles, StringBuilder checksums, File output) throws IOException, ParseException {
- final File dir = output.getParentFile();
- if (dir != null && (!dir.exists() || !dir.isDirectory())) {
- throw new IOException("Cannot write control file at '" + output.getAbsolutePath() + "'");
- }
-
- final TarArchiveOutputStream outputStream = new TarArchiveOutputStream(new GZIPOutputStream(new FileOutputStream(output)));
- outputStream.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
-
- // create the final package control file out of the "control" file, copy all other files, ignore the directories
- for (File file : controlFiles) {
- if (file.isDirectory()) {
- // warn about the misplaced directory, except for directories ignored by default (.svn, cvs, etc)
- if (!isDefaultExcludes(file)) {
- console.info("Found directory '" + file + "' in the control directory. Maybe you are pointing to wrong dir?");
- }
- continue;
- }
-
- if (CONFIGURATION_FILENAMES.contains(file.getName()) || MAINTAINER_SCRIPTS.contains(file.getName())) {
- FilteredFile configurationFile = new FilteredFile(new FileInputStream(file), resolver);
- addControlEntry(file.getName(), configurationFile.toString(), outputStream);
-
- } else if (!"control".equals(file.getName())) {
- // initialize the information stream to guess the type of the file
- InformationInputStream infoStream = new InformationInputStream(new FileInputStream(file));
- Utils.copy(infoStream, NullOutputStream.NULL_OUTPUT_STREAM);
- infoStream.close();
-
- // fix line endings for shell scripts
- InputStream in = new FileInputStream(file);
- if (infoStream.isShell() && !infoStream.hasUnixLineEndings()) {
- byte[] buf = Utils.toUnixLineEndings(in);
- in = new ByteArrayInputStream(buf);
- }
-
- addControlEntry(file.getName(), IOUtils.toString(in), outputStream);
-
- in.close();
- }
- }
-
- if (packageControlFile == null) {
- throw new FileNotFoundException("No 'control' file found in " + Arrays.toString(controlFiles));
- }
-
- addControlEntry("control", packageControlFile.toString(), outputStream);
- addControlEntry("md5sums", checksums.toString(), outputStream);
-
- outputStream.close();
- }
-
-
- /**
- * Creates a package control file from the specified file and adds the
- * <tt>Date</tt>, <tt>Distribution</tt> and <tt>Urgency</tt> fields if missing.
- * The <tt>Installed-Size</tt> field is also initialized to the actual size of
- * the package. The <tt>Maintainer</tt> field is overridden by the <tt>DEBEMAIL</tt>
- * and <tt>DEBFULLNAME</tt> environment variables if defined.
- *
- * @param file the control file
- * @param pDataSize the size of the installed package
- */
- public BinaryPackageControlFile createPackageControlFile(File file, BigInteger pDataSize) throws IOException, ParseException {
- FilteredFile controlFile = new FilteredFile(new FileInputStream(file), resolver);
- BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile(controlFile.toString());
-
- if (packageControlFile.get("Distribution") == null) {
- packageControlFile.set("Distribution", "unknown");
- }
-
- if (packageControlFile.get("Urgency") == null) {
- packageControlFile.set("Urgency", "low");
- }
-
- packageControlFile.set("Installed-Size", pDataSize.divide(BigInteger.valueOf(1024)).toString());
-
- // override the Version if the DEBVERSION environment variable is defined
- final String debVersion = System.getenv("DEBVERSION");
- if (debVersion != null) {
- packageControlFile.set("Version", debVersion);
- console.info("Using version'" + debVersion + "' from the environment variables.");
- }
-
-
- // override the Maintainer field if the DEBFULLNAME and DEBEMAIL environment variables are defined
- final String debFullName = System.getenv("DEBFULLNAME");
- final String debEmail = System.getenv("DEBEMAIL");
-
- if (debFullName != null && debEmail != null) {
- final String maintainer = debFullName + " <" + debEmail + ">";
- packageControlFile.set("Maintainer", maintainer);
- console.info("Using maintainer '" + maintainer + "' from the environment variables.");
- }
-
- return packageControlFile;
- }
-
-
- private static void addControlEntry(final String pName, final String pContent, final TarArchiveOutputStream pOutput) throws IOException {
- final byte[] data = pContent.getBytes("UTF-8");
-
- final TarArchiveEntry entry = new TarArchiveEntry("./" + pName, true);
- entry.setSize(data.length);
- entry.setNames("root", "root");
-
- if (MAINTAINER_SCRIPTS.contains(pName)) {
- entry.setMode(PermMapper.toMode("755"));
- } else {
- entry.setMode(PermMapper.toMode("644"));
- }
-
- pOutput.putArchiveEntry(entry);
- pOutput.write(data);
- pOutput.closeArchiveEntry();
- }
-
- /**
- * Tells if the specified directory is ignored by default (.svn, cvs, etc)
- *
- * @param directory
- */
- private boolean isDefaultExcludes(File directory) {
- for (String pattern : DirectoryScanner.getDefaultExcludes()) {
- if (DirectoryScanner.match(pattern, directory.getAbsolutePath().replace("\\", "/"))) {
- return true;
- }
- }
-
- return false;
- }
-}
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.text.ParseException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.GZIPOutputStream;
+
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.NullOutputStream;
+import org.apache.tools.ant.DirectoryScanner;
+import org.vafer.jdeb.debian.BinaryPackageControlFile;
+import org.vafer.jdeb.mapping.PermMapper;
+import org.vafer.jdeb.utils.FilteredFile;
+import org.vafer.jdeb.utils.InformationInputStream;
+import org.vafer.jdeb.utils.Utils;
+import org.vafer.jdeb.utils.VariableResolver;
+
+/**
+ * Builds the control archive of the Debian package.
+ */
+class ControlBuilder {
+
+ /** The name of the package maintainer scripts */
+ private static final Set<String> MAINTAINER_SCRIPTS = new HashSet<String>(Arrays.asList("preinst", "postinst", "prerm", "postrm", "config"));
+
+ /** The name of the other control files subject to token substitution */
+ private static final Set<String> CONFIGURATION_FILENAMES = new HashSet<String>(Arrays.asList("conffiles", "templates", "triggers"));
+
+ private Console console;
+ private VariableResolver resolver;
+ private final String openReplaceToken;
+ private final String closeReplaceToken;
+
+ ControlBuilder(Console console, VariableResolver resolver, String openReplaceToken, String closeReplaceToken) {
+ this.console = console;
+ this.resolver = resolver;
+ this.openReplaceToken = openReplaceToken;
+ this.closeReplaceToken = closeReplaceToken;
+ }
+
+ /**
+ * Build control archive of the deb
+ *
+ * @param packageControlFile the package control file
+ * @param controlFiles the other control information files (maintainer scripts, etc)
+ * @param dataSize the size of the installed package
+ * @param checksums the md5 checksums of the files in the data archive
+ * @param output
+ * @return
+ * @throws java.io.FileNotFoundException
+ * @throws java.io.IOException
+ * @throws java.text.ParseException
+ */
+ void buildControl(BinaryPackageControlFile packageControlFile, File[] controlFiles, List<String> conffiles, StringBuilder checksums, File output) throws IOException, ParseException {
+ final File dir = output.getParentFile();
+ if (dir != null && (!dir.exists() || !dir.isDirectory())) {
+ throw new IOException("Cannot write control file at '" + output.getAbsolutePath() + "'");
+ }
+
+ final TarArchiveOutputStream outputStream = new TarArchiveOutputStream(new GZIPOutputStream(new FileOutputStream(output)));
+ outputStream.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
+
+ boolean foundConffiles = false;
+
+ // create the final package control file out of the "control" file, copy all other files, ignore the directories
+ for (File file : controlFiles) {
+ if (file.isDirectory()) {
+ // warn about the misplaced directory, except for directories ignored by default (.svn, cvs, etc)
+ if (!isDefaultExcludes(file)) {
+ console.warn("Found directory '" + file + "' in the control directory. Maybe you are pointing to wrong dir?");
+ }
+ continue;
+ }
+
+ if ("conffiles".equals(file.getName())) {
+ foundConffiles = true;
+ }
+
+ if (CONFIGURATION_FILENAMES.contains(file.getName()) || MAINTAINER_SCRIPTS.contains(file.getName())) {
+ FilteredFile configurationFile = new FilteredFile(new FileInputStream(file), resolver);
+ configurationFile.setOpenToken(openReplaceToken);
+ configurationFile.setCloseToken(closeReplaceToken);
+ addControlEntry(file.getName(), configurationFile.toString(), outputStream);
+
+ } else if (!"control".equals(file.getName())) {
+ // initialize the information stream to guess the type of the file
+ InformationInputStream infoStream = new InformationInputStream(new FileInputStream(file));
+ Utils.copy(infoStream, NullOutputStream.NULL_OUTPUT_STREAM);
+ infoStream.close();
+
+ // fix line endings for shell scripts
+ InputStream in = new FileInputStream(file);
+ if (infoStream.isShell() && !infoStream.hasUnixLineEndings()) {
+ byte[] buf = Utils.toUnixLineEndings(in);
+ in = new ByteArrayInputStream(buf);
+ }
+
+ addControlEntry(file.getName(), IOUtils.toString(in), outputStream);
+
+ in.close();
+ }
+ }
+
+ if ((conffiles != null) && (conffiles.size() > 0)) {
+ if (foundConffiles) {
+ console.info("Found file 'conffiles' in the control directory. Skipping conffiles generation.");
+ } else {
+ addControlEntry("conffiles", createPackageConffilesFile(conffiles), outputStream);
+ }
+ } else if ((conffiles != null) && (conffiles.size() == 0)) {
+ console.info("Skipping 'conffiles' generation. No entries provided.");
+ }
+
+ if (packageControlFile == null) {
+ throw new FileNotFoundException("No 'control' file found in " + controlFiles.toString());
+ }
+
+ addControlEntry("control", packageControlFile.toString(), outputStream);
+ addControlEntry("md5sums", checksums.toString(), outputStream);
+
+ outputStream.close();
+ }
+
+ private String createPackageConffilesFile(final List<String> conffiles) {
+ StringBuilder content = new StringBuilder();
+
+ if (conffiles != null && !conffiles.isEmpty()) {
+ for (String nextFileName : conffiles) {
+ content.append(nextFileName).append("\n");
+ }
+ }
+
+ return content.toString();
+ }
+
+
+ /**
+ * Creates a package control file from the specified file and adds the
+ * <tt>Date</tt>, <tt>Distribution</tt> and <tt>Urgency</tt> fields if missing.
+ * The <tt>Installed-Size</tt> field is also initialized to the actual size of
+ * the package. The <tt>Maintainer</tt> field is overridden by the <tt>DEBEMAIL</tt>
+ * and <tt>DEBFULLNAME</tt> environment variables if defined.
+ *
+ * @param file the control file
+ * @param pDataSize the size of the installed package
+ */
+ public BinaryPackageControlFile createPackageControlFile(File file, BigInteger pDataSize) throws IOException, ParseException {
+ FilteredFile controlFile = new FilteredFile(new FileInputStream(file), resolver);
+ BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile(controlFile.toString());
+
+ if (packageControlFile.get("Distribution") == null) {
+ packageControlFile.set("Distribution", "unknown");
+ }
+
+ if (packageControlFile.get("Urgency") == null) {
+ packageControlFile.set("Urgency", "low");
+ }
+
+ packageControlFile.set("Installed-Size", pDataSize.divide(BigInteger.valueOf(1024)).toString());
+
+ // override the Version if the DEBVERSION environment variable is defined
+ final String debVersion = System.getenv("DEBVERSION");
+ if (debVersion != null) {
+ packageControlFile.set("Version", debVersion);
+ console.debug("Using version'" + debVersion + "' from the environment variables.");
+ }
+
+
+ // override the Maintainer field if the DEBFULLNAME and DEBEMAIL environment variables are defined
+ final String debFullName = System.getenv("DEBFULLNAME");
+ final String debEmail = System.getenv("DEBEMAIL");
+
+ if (debFullName != null && debEmail != null) {
+ final String maintainer = debFullName + " <" + debEmail + ">";
+ packageControlFile.set("Maintainer", maintainer);
+ console.debug("Using maintainer '" + maintainer + "' from the environment variables.");
+ }
+
+ return packageControlFile;
+ }
+
+
+ private static void addControlEntry(final String pName, final String pContent, final TarArchiveOutputStream pOutput) throws IOException {
+ final byte[] data = pContent.getBytes("UTF-8");
+
+ final TarArchiveEntry entry = new TarArchiveEntry("./" + pName, true);
+ entry.setSize(data.length);
+ entry.setNames("root", "root");
+
+ if (MAINTAINER_SCRIPTS.contains(pName)) {
+ entry.setMode(PermMapper.toMode("755"));
+ } else {
+ entry.setMode(PermMapper.toMode("644"));
+ }
+
+ pOutput.putArchiveEntry(entry);
+ pOutput.write(data);
+ pOutput.closeArchiveEntry();
+ }
+
+ /**
+ * Tells if the specified directory is ignored by default (.svn, cvs, etc)
+ *
+ * @param directory
+ */
+ private boolean isDefaultExcludes(File directory) {
+ for (String pattern : DirectoryScanner.getDefaultExcludes()) {
+ if (DirectoryScanner.match(pattern, directory.getAbsolutePath().replace("\\", "/"))) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/src/main/java/org/vafer/jdeb/DataBuilder.java b/src/main/java/org/vafer/jdeb/DataBuilder.java
index 4768fe4..0acef78 100644
--- a/src/main/java/org/vafer/jdeb/DataBuilder.java
+++ b/src/main/java/org/vafer/jdeb/DataBuilder.java
@@ -1,307 +1,307 @@
-/*
- * Copyright 2013 The jdeb developers.
- *
- * 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 org.vafer.jdeb;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-import java.security.DigestOutputStream;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
-import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
-import org.apache.commons.compress.archivers.tar.TarConstants;
-import org.apache.commons.compress.archivers.zip.ZipEncoding;
-import org.apache.commons.compress.archivers.zip.ZipEncodingHelper;
-import org.apache.commons.compress.compressors.CompressorException;
-import org.vafer.jdeb.utils.Utils;
-
-/**
- * Builds the data archive of the Debian package.
- */
-class DataBuilder {
-
- private Console console;
-
- private ZipEncoding encoding;
-
- private static final class Total {
- private BigInteger count = BigInteger.valueOf(0);
-
- public void add( long size ) {
- count = count.add(BigInteger.valueOf(size));
- }
-
- public String toString() {
- return "" + count;
- }
- }
-
- DataBuilder(Console console) {
- this.console = console;
- this.encoding = ZipEncodingHelper.getZipEncoding(null);
- }
-
- private void checkField(String name, int length) throws IOException {
- if (name != null) {
- ByteBuffer b = encoding.encode(name);
- if (b.limit() > length) {
- throw new IllegalArgumentException("Field '" + name + "' too long, maximum is " + length);
- }
- }
- }
-
- /**
- * Build the data archive of the deb from the provided DataProducers
- *
- * @param producers
- * @param output
- * @param checksums
- * @param compression the compression method used for the data file
- * @return
- * @throws java.security.NoSuchAlgorithmException
- * @throws java.io.IOException
- * @throws org.apache.commons.compress.compressors.CompressorException
- */
- BigInteger buildData(Collection<DataProducer> producers, File output, final StringBuilder checksums, Compression compression) throws NoSuchAlgorithmException, IOException, CompressorException {
-
- final File dir = output.getParentFile();
- if (dir != null && (!dir.exists() || !dir.isDirectory())) {
- throw new IOException("Cannot write data file at '" + output.getAbsolutePath() + "'");
- }
-
- final TarArchiveOutputStream tarOutputStream = new TarArchiveOutputStream(compression.toCompressedOutputStream(new FileOutputStream(output)));
- tarOutputStream.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
-
- final MessageDigest digest = MessageDigest.getInstance("MD5");
-
- final Total dataSize = new Total();
-
- final List<String> addedDirectories = new ArrayList<String>();
- final DataConsumer receiver = new DataConsumer() {
- public void onEachDir( String dirname, String linkname, String user, int uid, String group, int gid, int mode, long size ) throws IOException {
- // Check link name
- checkField(linkname, TarConstants.NAMELEN);
- // Check user name
- checkField(user, TarConstants.UNAMELEN);
- // Check group name
- checkField(group, TarConstants.GNAMELEN);
-
- dirname = fixPath(dirname);
-
- createParentDirectories(dirname, user, uid, group, gid);
-
- // The directory passed in explicitly by the caller also gets the passed-in mode. (Unlike
- // the parent directories for now. See related comments at "int mode =" in
- // createParentDirectories, including about a possible bug.)
- createDirectory(dirname, user, uid, group, gid, mode, 0);
-
- console.info("dir: " + dirname);
- }
-
- public void onEachFile( InputStream inputStream, String filename, String linkname, String user, int uid, String group, int gid, int mode, long size ) throws IOException {
- // Check link name
- checkField(linkname, TarConstants.NAMELEN);
- // Check user name
- checkField(user, TarConstants.UNAMELEN);
- // Check group name
- checkField(group, TarConstants.GNAMELEN);
-
- filename = fixPath(filename);
-
- createParentDirectories(filename, user, uid, group, gid);
-
- final TarArchiveEntry entry = new TarArchiveEntry(filename, true);
-
- entry.setUserName(user);
- entry.setUserId(uid);
- entry.setGroupName(group);
- entry.setGroupId(gid);
- entry.setMode(mode);
- entry.setSize(size);
-
- tarOutputStream.putArchiveEntry(entry);
-
- dataSize.add(size);
- digest.reset();
-
- Utils.copy(inputStream, new DigestOutputStream(tarOutputStream, digest));
-
- final String md5 = Utils.toHex(digest.digest());
-
- tarOutputStream.closeArchiveEntry();
-
- console.info(
- "file:" + entry.getName() +
- " size:" + entry.getSize() +
- " mode:" + entry.getMode() +
- " linkname:" + entry.getLinkName() +
- " username:" + entry.getUserName() +
- " userid:" + entry.getUserId() +
- " groupname:" + entry.getGroupName() +
- " groupid:" + entry.getGroupId() +
- " modtime:" + entry.getModTime() +
- " md5: " + md5
- );
-
- // append to file md5 list
- checksums.append(md5).append(" ").append(entry.getName()).append('\n');
- }
-
- public void onEachLink(String path, String linkname, boolean symlink, String user, int uid, String group, int gid, int mode) throws IOException {
- // Check link name
- checkField(linkname, TarConstants.NAMELEN);
- // Check user name
- checkField(user, TarConstants.UNAMELEN);
- // Check group name
- checkField(group, TarConstants.GNAMELEN);
-
- path = fixPath(path);
-
- createParentDirectories(path, user, uid, group, gid);
-
- final TarArchiveEntry entry = new TarArchiveEntry(path, symlink ? TarArchiveEntry.LF_SYMLINK : TarArchiveEntry.LF_LINK);
- entry.setLinkName(linkname);
-
- entry.setUserName(user);
- entry.setUserId(uid);
- entry.setGroupName(group);
- entry.setGroupId(gid);
- entry.setMode(mode);
-
- tarOutputStream.putArchiveEntry(entry);
- tarOutputStream.closeArchiveEntry();
-
- console.info(
- "link:" + entry.getName() +
- " mode:" + entry.getMode() +
- " linkname:" + entry.getLinkName() +
- " username:" + entry.getUserName() +
- " userid:" + entry.getUserId() +
- " groupname:" + entry.getGroupName() +
- " groupid:" + entry.getGroupId()
- );
- }
-
-
- private void createDirectory( String directory, String user, int uid, String group, int gid, int mode, long size ) throws IOException {
- // All dirs should end with "/" when created, or the test DebAndTaskTestCase.testTarFileSet() thinks its a file
- // and so thinks it has the wrong permission.
- // This consistency also helps when checking if a directory already exists in addedDirectories.
-
- if (!directory.endsWith("/")) {
- directory += "/";
- }
-
- if (!addedDirectories.contains(directory)) {
- TarArchiveEntry entry = new TarArchiveEntry(directory, true);
- entry.setUserName(user);
- entry.setUserId(uid);
- entry.setGroupName(group);
- entry.setGroupId(gid);
- entry.setMode(mode);
- entry.setSize(size);
-
- tarOutputStream.putArchiveEntry(entry);
- tarOutputStream.closeArchiveEntry();
- addedDirectories.add(directory); // so addedDirectories consistently have "/" for finding duplicates.
- }
- }
-
- private void createParentDirectories( String filename, String user, int uid, String group, int gid ) throws IOException {
- String dirname = fixPath(new File(filename).getParent());
-
- // Debian packages must have parent directories created
- // before sub-directories or files can be installed.
- // For example, if an entry of ./usr/lib/foo/bar existed
- // in a .deb package, but the ./usr/lib/foo directory didn't
- // exist, the package installation would fail. The .deb must
- // then have an entry for ./usr/lib/foo and then ./usr/lib/foo/bar
-
- if (dirname == null) {
- return;
- }
-
- // The loop below will create entries for all parent directories
- // to ensure that .deb packages will install correctly.
- String[] pathParts = dirname.split("/");
- String parentDir = "./";
- for (int i = 1; i < pathParts.length; i++) {
- parentDir += pathParts[i] + "/";
- // Make it so the dirs can be traversed by users.
- // We could instead try something more granular, like setting the directory
- // permission to 'rx' for each of the 3 user/group/other read permissions
- // found on the file being added (ie, only if "other" has read
- // permission on the main node, then add o+rx permission on all the containing
- // directories, same w/ user & group), and then also we'd have to
- // check the parentDirs collection of those already added to
- // see if those permissions need to be similarly updated. (Note, it hasn't
- // been demonstrated, but there might be a bug if a user specifically
- // requests a directory with certain permissions,
- // that has already been auto-created because it was a parent, and if so, go set
- // the user-requested mode on that directory instead of this automatic one.)
- // But for now, keeping it simple by making every dir a+rx. Examples are:
- // drw-r----- fs/fs # what you get with setMode(mode)
- // drwxr-xr-x fs/fs # Usable. Too loose?
- int mode = TarArchiveEntry.DEFAULT_DIR_MODE;
-
- createDirectory(parentDir, user, uid, group, gid, mode, 0);
- }
- }
- };
-
- try {
- for (DataProducer data : producers) {
- data.produce(receiver);
- }
- } finally {
- tarOutputStream.close();
- }
-
- console.info("Total size: " + dataSize);
-
- return dataSize.count;
- }
-
- private String fixPath( String path ) {
- if (path == null || path.equals(".")) {
- return path;
- }
-
- // If we're receiving directory names from Windows, then we'll convert to use slash
- // This does eliminate the ability to use of a backslash in a directory name on *NIX,
- // but in practice, this is a non-issue
- if (path.contains("\\")) {
- path = path.replace('\\', '/');
- }
- // ensure the path is like : ./foo/bar
- if (path.startsWith("/")) {
- path = "." + path;
- } else if (!path.startsWith("./")) {
- path = "./" + path;
- }
- return path;
- }
-
-}
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.security.DigestOutputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
+import org.apache.commons.compress.archivers.tar.TarConstants;
+import org.apache.commons.compress.archivers.zip.ZipEncoding;
+import org.apache.commons.compress.archivers.zip.ZipEncodingHelper;
+import org.apache.commons.compress.compressors.CompressorException;
+import org.vafer.jdeb.utils.Utils;
+
+/**
+ * Builds the data archive of the Debian package.
+ */
+class DataBuilder {
+
+ private Console console;
+
+ private ZipEncoding encoding;
+
+ private static final class Total {
+ private BigInteger count = BigInteger.valueOf(0);
+
+ public void add( long size ) {
+ count = count.add(BigInteger.valueOf(size));
+ }
+
+ public String toString() {
+ return "" + count;
+ }
+ }
+
+ DataBuilder(Console console) {
+ this.console = console;
+ this.encoding = ZipEncodingHelper.getZipEncoding(null);
+ }
+
+ private void checkField(String name, int length) throws IOException {
+ if (name != null) {
+ ByteBuffer b = encoding.encode(name);
+ if (b.limit() > length) {
+ throw new IllegalArgumentException("Field '" + name + "' too long, maximum is " + length);
+ }
+ }
+ }
+
+ /**
+ * Build the data archive of the deb from the provided DataProducers
+ *
+ * @param producers
+ * @param output
+ * @param checksums
+ * @param compression the compression method used for the data file
+ * @return
+ * @throws java.security.NoSuchAlgorithmException
+ * @throws java.io.IOException
+ * @throws org.apache.commons.compress.compressors.CompressorException
+ */
+ BigInteger buildData(Collection<DataProducer> producers, File output, final StringBuilder checksums, Compression compression) throws NoSuchAlgorithmException, IOException, CompressorException {
+
+ final File dir = output.getParentFile();
+ if (dir != null && (!dir.exists() || !dir.isDirectory())) {
+ throw new IOException("Cannot write data file at '" + output.getAbsolutePath() + "'");
+ }
+
+ final TarArchiveOutputStream tarOutputStream = new TarArchiveOutputStream(compression.toCompressedOutputStream(new FileOutputStream(output)));
+ tarOutputStream.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
+
+ final MessageDigest digest = MessageDigest.getInstance("MD5");
+
+ final Total dataSize = new Total();
+
+ final List<String> addedDirectories = new ArrayList<String>();
+ final DataConsumer receiver = new DataConsumer() {
+ public void onEachDir( String dirname, String linkname, String user, int uid, String group, int gid, int mode, long size ) throws IOException {
+ // Check link name
+ checkField(linkname, TarConstants.NAMELEN);
+ // Check user name
+ checkField(user, TarConstants.UNAMELEN);
+ // Check group name
+ checkField(group, TarConstants.GNAMELEN);
+
+ dirname = fixPath(dirname);
+
+ createParentDirectories(dirname, user, uid, group, gid);
+
+ // The directory passed in explicitly by the caller also gets the passed-in mode. (Unlike
+ // the parent directories for now. See related comments at "int mode =" in
+ // createParentDirectories, including about a possible bug.)
+ createDirectory(dirname, user, uid, group, gid, mode, 0);
+
+ console.debug("dir: " + dirname);
+ }
+
+ public void onEachFile( InputStream inputStream, String filename, String linkname, String user, int uid, String group, int gid, int mode, long size ) throws IOException {
+ // Check link name
+ checkField(linkname, TarConstants.NAMELEN);
+ // Check user name
+ checkField(user, TarConstants.UNAMELEN);
+ // Check group name
+ checkField(group, TarConstants.GNAMELEN);
+
+ filename = fixPath(filename);
+
+ createParentDirectories(filename, user, uid, group, gid);
+
+ final TarArchiveEntry entry = new TarArchiveEntry(filename, true);
+
+ entry.setUserName(user);
+ entry.setUserId(uid);
+ entry.setGroupName(group);
+ entry.setGroupId(gid);
+ entry.setMode(mode);
+ entry.setSize(size);
+
+ tarOutputStream.putArchiveEntry(entry);
+
+ dataSize.add(size);
+ digest.reset();
+
+ Utils.copy(inputStream, new DigestOutputStream(tarOutputStream, digest));
+
+ final String md5 = Utils.toHex(digest.digest());
+
+ tarOutputStream.closeArchiveEntry();
+
+ console.debug(
+ "file:" + entry.getName() +
+ " size:" + entry.getSize() +
+ " mode:" + entry.getMode() +
+ " linkname:" + entry.getLinkName() +
+ " username:" + entry.getUserName() +
+ " userid:" + entry.getUserId() +
+ " groupname:" + entry.getGroupName() +
+ " groupid:" + entry.getGroupId() +
+ " modtime:" + entry.getModTime() +
+ " md5: " + md5
+ );
+
+ // append to file md5 list, two spaces to be compatible with GNU coreutils md5sum
+ checksums.append(md5).append(" ").append(entry.getName()).append('\n');
+ }
+
+ public void onEachLink(String path, String linkname, boolean symlink, String user, int uid, String group, int gid, int mode) throws IOException {
+ // Check link name
+ checkField(linkname, TarConstants.NAMELEN);
+ // Check user name
+ checkField(user, TarConstants.UNAMELEN);
+ // Check group name
+ checkField(group, TarConstants.GNAMELEN);
+
+ path = fixPath(path);
+
+ createParentDirectories(path, user, uid, group, gid);
+
+ final TarArchiveEntry entry = new TarArchiveEntry(path, symlink ? TarArchiveEntry.LF_SYMLINK : TarArchiveEntry.LF_LINK);
+ entry.setLinkName(linkname);
+
+ entry.setUserName(user);
+ entry.setUserId(uid);
+ entry.setGroupName(group);
+ entry.setGroupId(gid);
+ entry.setMode(mode);
+
+ tarOutputStream.putArchiveEntry(entry);
+ tarOutputStream.closeArchiveEntry();
+
+ console.debug(
+ "link:" + entry.getName() +
+ " mode:" + entry.getMode() +
+ " linkname:" + entry.getLinkName() +
+ " username:" + entry.getUserName() +
+ " userid:" + entry.getUserId() +
+ " groupname:" + entry.getGroupName() +
+ " groupid:" + entry.getGroupId()
+ );
+ }
+
+
+ private void createDirectory( String directory, String user, int uid, String group, int gid, int mode, long size ) throws IOException {
+ // All dirs should end with "/" when created, or the test DebAndTaskTestCase.testTarFileSet() thinks its a file
+ // and so thinks it has the wrong permission.
+ // This consistency also helps when checking if a directory already exists in addedDirectories.
+
+ if (!directory.endsWith("/")) {
+ directory += "/";
+ }
+
+ if (!addedDirectories.contains(directory)) {
+ TarArchiveEntry entry = new TarArchiveEntry(directory, true);
+ entry.setUserName(user);
+ entry.setUserId(uid);
+ entry.setGroupName(group);
+ entry.setGroupId(gid);
+ entry.setMode(mode);
+ entry.setSize(size);
+
+ tarOutputStream.putArchiveEntry(entry);
+ tarOutputStream.closeArchiveEntry();
+ addedDirectories.add(directory); // so addedDirectories consistently have "/" for finding duplicates.
+ }
+ }
+
+ private void createParentDirectories( String filename, String user, int uid, String group, int gid ) throws IOException {
+ String dirname = fixPath(new File(filename).getParent());
+
+ // Debian packages must have parent directories created
+ // before sub-directories or files can be installed.
+ // For example, if an entry of ./usr/lib/foo/bar existed
+ // in a .deb package, but the ./usr/lib/foo directory didn't
+ // exist, the package installation would fail. The .deb must
+ // then have an entry for ./usr/lib/foo and then ./usr/lib/foo/bar
+
+ if (dirname == null) {
+ return;
+ }
+
+ // The loop below will create entries for all parent directories
+ // to ensure that .deb packages will install correctly.
+ String[] pathParts = dirname.split("/");
+ String parentDir = "./";
+ for (int i = 1; i < pathParts.length; i++) {
+ parentDir += pathParts[i] + "/";
+ // Make it so the dirs can be traversed by users.
+ // We could instead try something more granular, like setting the directory
+ // permission to 'rx' for each of the 3 user/group/other read permissions
+ // found on the file being added (ie, only if "other" has read
+ // permission on the main node, then add o+rx permission on all the containing
+ // directories, same w/ user & group), and then also we'd have to
+ // check the parentDirs collection of those already added to
+ // see if those permissions need to be similarly updated. (Note, it hasn't
+ // been demonstrated, but there might be a bug if a user specifically
+ // requests a directory with certain permissions,
+ // that has already been auto-created because it was a parent, and if so, go set
+ // the user-requested mode on that directory instead of this automatic one.)
+ // But for now, keeping it simple by making every dir a+rx. Examples are:
+ // drw-r----- fs/fs # what you get with setMode(mode)
+ // drwxr-xr-x fs/fs # Usable. Too loose?
+ int mode = TarArchiveEntry.DEFAULT_DIR_MODE;
+
+ createDirectory(parentDir, user, uid, group, gid, mode, 0);
+ }
+ }
+ };
+
+ try {
+ for (DataProducer data : producers) {
+ data.produce(receiver);
+ }
+ } finally {
+ tarOutputStream.close();
+ }
+
+ console.debug("Total size: " + dataSize);
+
+ return dataSize.count;
+ }
+
+ private String fixPath( String path ) {
+ if (path == null || path.equals(".")) {
+ return path;
+ }
+
+ // If we're receiving directory names from Windows, then we'll convert to use slash
+ // This does eliminate the ability to use of a backslash in a directory name on *NIX,
+ // but in practice, this is a non-issue
+ if (path.contains("\\")) {
+ path = path.replace('\\', '/');
+ }
+ // ensure the path is like : ./foo/bar
+ if (path.startsWith("/")) {
+ path = "." + path;
+ } else if (!path.startsWith("./")) {
+ path = "./" + path;
+ }
+ return path;
+ }
+
+}
diff --git a/src/main/java/org/vafer/jdeb/DataConsumer.java b/src/main/java/org/vafer/jdeb/DataConsumer.java
index d108888..3bcdfa0 100644
--- a/src/main/java/org/vafer/jdeb/DataConsumer.java
+++ b/src/main/java/org/vafer/jdeb/DataConsumer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,7 @@ public interface DataConsumer {
void onEachDir( String dirname, String linkname, String user, int uid, String group, int gid, int mode, long size ) throws IOException;
void onEachFile( InputStream input, String filename, String linkname, String user, int uid, String group, int gid, int mode, long size ) throws IOException;
-
+
void onEachLink( String path, String linkName, boolean symlink, String user, int uid, String group, int gid, int mode) throws IOException;
}
diff --git a/src/main/java/org/vafer/jdeb/DataProducer.java b/src/main/java/org/vafer/jdeb/DataProducer.java
index 4218bf2..de85c5c 100644
--- a/src/main/java/org/vafer/jdeb/DataProducer.java
+++ b/src/main/java/org/vafer/jdeb/DataProducer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/main/java/org/vafer/jdeb/DebMaker.java b/src/main/java/org/vafer/jdeb/DebMaker.java
index 1254dc4..3cd5c23 100644
--- a/src/main/java/org/vafer/jdeb/DebMaker.java
+++ b/src/main/java/org/vafer/jdeb/DebMaker.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,25 +16,41 @@
package org.vafer.jdeb;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
+import java.util.List;
+import java.util.Locale;
import org.apache.commons.compress.archivers.ar.ArArchiveEntry;
import org.apache.commons.compress.archivers.ar.ArArchiveOutputStream;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
+import org.bouncycastle.crypto.digests.MD5Digest;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.openpgp.PGPSignature;
+import org.bouncycastle.openpgp.PGPSignatureGenerator;
+import org.bouncycastle.openpgp.PGPUtil;
+import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder;
+import org.bouncycastle.util.encoders.Hex;
import org.vafer.jdeb.changes.ChangeSet;
import org.vafer.jdeb.changes.ChangesProvider;
import org.vafer.jdeb.changes.TextfileChangesProvider;
import org.vafer.jdeb.debian.BinaryPackageControlFile;
import org.vafer.jdeb.debian.ChangesFile;
import org.vafer.jdeb.signing.PGPSigner;
+import org.vafer.jdeb.utils.PGPSignatureOutputStream;
import org.vafer.jdeb.utils.Utils;
import org.vafer.jdeb.utils.VariableResolver;
@@ -92,14 +108,34 @@ public class DebMaker {
/** The compression method used for the data file (none, gzip, bzip2 or xz) */
private String compression = "gzip";
+ /** Whether to sign the package that is created */
+ private boolean signPackage;
+
+ /** Defines which utility is used to verify the signed package */
+ private String signMethod;
+
+ /** Defines the role to sign with */
+ private String signRole;
+
private VariableResolver variableResolver;
+ private String openReplaceToken;
+ private String closeReplaceToken;
private final Collection<DataProducer> dataProducers = new ArrayList<DataProducer>();
+ private final Collection<DataProducer> conffilesProducers = new ArrayList<DataProducer>();
+
- public DebMaker(Console console, Collection<DataProducer> dataProducers) {
+ public DebMaker(Console console, Collection<DataProducer> dataProducers, Collection<DataProducer> conffileProducers) {
this.console = console;
- this.dataProducers.addAll(dataProducers);
+ if (dataProducers != null) {
+ this.dataProducers.addAll(dataProducers);
+ }
+ if (conffileProducers != null) {
+ this.conffilesProducers.addAll(conffileProducers);
+ }
+
+ Security.addProvider(new BouncyCastleProvider());
}
public void setDeb(File deb) {
@@ -142,6 +178,18 @@ public class DebMaker {
this.changesSave = changes;
}
+ public void setSignPackage(boolean signPackage) {
+ this.signPackage = signPackage;
+ }
+
+ public void setSignMethod(String signMethod) {
+ this.signMethod = signMethod;
+ }
+
+ public void setSignRole(String signRole) {
+ this.signRole = signRole;
+ }
+
public void setKeyring(File keyring) {
this.keyring = keyring;
}
@@ -179,7 +227,7 @@ public class DebMaker {
if (changesIn.exists() && (!changesIn.isFile() || !changesIn.canRead())) {
throw new PackagingException("The 'changesIn' setting needs to point to a readable file. " + changesIn + " was not found/readable.");
}
-
+
if (changesOut != null && !isWritableFile(changesOut)) {
throw new PackagingException("Cannot write the output for 'changesOut' to " + changesOut);
}
@@ -201,10 +249,6 @@ public class DebMaker {
if (deb == null) {
throw new PackagingException("You need to specify where the deb file is supposed to be created.");
}
-
- if (dataProducers.size() == 0) {
- throw new PackagingException("You need to provide at least one reference to a tgz or directory with data.");
- }
}
public void makeDeb() throws PackagingException {
@@ -212,12 +256,48 @@ public class DebMaker {
try {
console.info("Creating debian package: " + deb);
- packageControlFile = createDeb(Compression.toEnum(compression));
+ // If we should sign the package
+ boolean doSign = signPackage;
+
+ if (doSign) {
+
+ if (keyring == null || !keyring.exists()) {
+ doSign = false;
+ console.warn("Signing requested, but no keyring supplied");
+ }
+
+ if (key == null) {
+ doSign = false;
+ console.warn("Signing requested, but no key supplied");
+ }
+
+ if (passphrase == null) {
+ doSign = false;
+ console.warn("Signing requested, but no passphrase supplied");
+ }
+
+ FileInputStream keyRingInput = new FileInputStream(keyring);
+ PGPSigner signer = null;
+ try {
+ signer = new PGPSigner(new FileInputStream(keyring), key, passphrase);
+ } finally {
+ keyRingInput.close();
+ }
+
+ int digest = PGPUtil.SHA1;
+
+ PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(new BcPGPContentSignerBuilder(signer.getSecretKey().getPublicKey().getAlgorithm(), digest));
+ signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, signer.getPrivateKey());
+
+ packageControlFile = createSignedDeb(Compression.toEnum(compression), signatureGenerator, signer);
+ } else {
+ packageControlFile = createDeb(Compression.toEnum(compression));
+ }
} catch (Exception e) {
throw new PackagingException("Failed to create debian package " + deb, e);
}
-
+
makeChangesFiles(packageControlFile);
}
@@ -225,15 +305,15 @@ public class DebMaker {
if (changesOut == null) {
changesOut = new File(deb.getParentFile(), deb.getName().replace(".deb", ".changes"));
}
-
+
ChangesProvider changesProvider;
FileOutputStream out = null;
-
+
try {
console.info("Creating changes file: " + changesOut);
-
+
out = new FileOutputStream(changesOut);
-
+
if (changesIn != null && changesIn.exists()) {
// read the changes form a textfile provider
changesProvider = new TextfileChangesProvider(new FileInputStream(changesIn), packageControlFile);
@@ -243,16 +323,21 @@ public class DebMaker {
@Override
public ChangeSet[] getChangesSets() {
return new ChangeSet[] {
- new ChangeSet(packageControlFile.get("Package"), packageControlFile.get("Version"), new Date(),
- "stable", "low", packageControlFile.get("Maintainer"), new String[0])
+ new ChangeSet(packageControlFile.get("Package"),
+ packageControlFile.get("Version"),
+ new Date(),
+ packageControlFile.get("Distribution"),
+ packageControlFile.get("Urgency"),
+ packageControlFile.get("Maintainer"),
+ new String[0])
};
}
};
}
-
+
ChangesFileBuilder builder = new ChangesFileBuilder();
ChangesFile changesFile = builder.createChanges(packageControlFile, deb, changesProvider);
-
+
if (keyring != null && key != null && passphrase != null) {
console.info("Signing the changes file with the key " + key);
PGPSigner signer = new PGPSigner(new FileInputStream(keyring), key, passphrase);
@@ -267,11 +352,11 @@ public class DebMaker {
} finally {
IOUtils.closeQuietly(out);
}
-
+
if (changesSave == null || !(changesProvider instanceof TextfileChangesProvider)) {
return;
}
-
+
try {
console.info("Saving changes to file: " + changesSave);
@@ -281,7 +366,44 @@ public class DebMaker {
throw new PackagingException("Failed to save debian changes file " + changesSave, e);
}
}
-
+
+ private List<String> populateConffiles(Collection<DataProducer> producers) {
+ final List<String> result = new ArrayList<String>();
+
+ if (producers == null || producers.isEmpty()) {
+ return result;
+ }
+
+ final DataConsumer receiver = new DataConsumer() {
+ public void onEachDir( String dirname, String linkname, String user, int uid, String group, int gid, int mode, long size ) throws IOException {
+ //
+ }
+
+ public void onEachFile( InputStream inputStream, String filename, String linkname, String user, int uid, String group, int gid, int mode, long size ) throws IOException {
+ String tempConffileItem = filename;
+ if (tempConffileItem.startsWith(".")) {
+ tempConffileItem = tempConffileItem.substring(1);
+ }
+ console.info("Adding conffile: " + tempConffileItem);
+ result.add(tempConffileItem);
+ }
+
+ public void onEachLink(String path, String linkname, boolean symlink, String user, int uid, String group, int gid, int mode) throws IOException {
+ //
+ }
+ };
+
+ try {
+ for (DataProducer data : producers) {
+ data.produce(receiver);
+ }
+ } catch(Exception e) {
+ //
+ }
+
+ return result;
+ }
+
/**
* Create the debian archive with from the provided control files and data producers.
*
@@ -293,6 +415,18 @@ public class DebMaker {
* @throws PackagingException
*/
public BinaryPackageControlFile createDeb(Compression compression) throws PackagingException {
+ return createSignedDeb(compression, null, null);
+ }
+ /**
+ * Create the debian archive with from the provided control files and data producers.
+ *
+ * @param compression the compression method used for the data file (gzip, bzip2 or anything else for no compression)
+ * @param signatureGenerator the signature generator
+ *
+ * @return PackageDescriptor
+ * @throws PackagingException
+ */
+ public BinaryPackageControlFile createSignedDeb(Compression compression, final PGPSignatureGenerator signatureGenerator, PGPSigner signer ) throws PackagingException {
File tempData = null;
File tempControl = null;
@@ -300,13 +434,16 @@ public class DebMaker {
tempData = File.createTempFile("deb", "data");
tempControl = File.createTempFile("deb", "control");
- console.info("Building data");
+ console.debug("Building data");
DataBuilder dataBuilder = new DataBuilder(console);
StringBuilder md5s = new StringBuilder();
BigInteger size = dataBuilder.buildData(dataProducers, tempData, md5s, compression);
-
- console.info("Building control");
- ControlBuilder controlBuilder = new ControlBuilder(console, variableResolver);
+
+ console.info("Building conffiles");
+ List<String> tempConffiles = populateConffiles(conffilesProducers);
+
+ console.debug("Building control");
+ ControlBuilder controlBuilder = new ControlBuilder(console, variableResolver, openReplaceToken, closeReplaceToken);
BinaryPackageControlFile packageControlFile = controlBuilder.createPackageControlFile(new File(control, "control"), size);
if (packageControlFile.get("Package") == null) {
packageControlFile.set("Package", packageName);
@@ -323,26 +460,67 @@ public class DebMaker {
if (packageControlFile.get("Homepage") == null) {
packageControlFile.set("Homepage", homepage);
}
-
- controlBuilder.buildControl(packageControlFile, control.listFiles(), md5s, tempControl);
-
+
+ controlBuilder.buildControl(packageControlFile, control.listFiles(), tempConffiles , md5s, tempControl);
+
if (!packageControlFile.isValid()) {
throw new PackagingException("Control file fields are invalid " + packageControlFile.invalidFields() +
- ". The following fields are mandatory: " + packageControlFile.getMandatoryFields() +
- ". Please check your pom.xml/build.xml and your control file.");
+ ". The following fields are mandatory: " + packageControlFile.getMandatoryFields() +
+ ". Please check your pom.xml/build.xml and your control file.");
}
deb.getParentFile().mkdirs();
-
-
+
ArArchiveOutputStream ar = new ArArchiveOutputStream(new FileOutputStream(deb));
-
- addTo(ar, "debian-binary", "2.0\n");
- addTo(ar, "control.tar.gz", tempControl);
- addTo(ar, "data.tar" + compression.getExtension(), tempData);
+
+ String binaryName = "debian-binary";
+ String binaryContent = "2.0\n";
+ String controlName = "control.tar.gz";
+ String dataName = "data.tar" + compression.getExtension();
+
+ addTo(ar, binaryName, binaryContent);
+ addTo(ar, controlName, tempControl);
+ addTo(ar, dataName, tempData);
+
+ if (signatureGenerator != null) {
+ console.info("Signing package with key " + key);
+
+ if(signRole == null) {
+ signRole = "origin";
+ }
+
+ // Use debsig-verify as default
+ if(signMethod == null || !"dpkg-sig".equals(signMethod)) {
+ // Sign file to verify with debsig-verify
+ PGPSignatureOutputStream sigStream = new PGPSignatureOutputStream(signatureGenerator);
+
+ addTo(sigStream, binaryContent);
+ addTo(sigStream, tempControl);
+ addTo(sigStream, tempData);
+ addTo(ar, "_gpg" + signRole, sigStream.generateASCIISignature());
+
+ } else {
+
+ // Sign file to verify with dpkg-sig --verify
+ final String outputStr =
+ "Version: 4\n" +
+ "Signer: \n" +
+ "Date: " + new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", Locale.ENGLISH).format(new Date()) + "\n" +
+ "Role: " + signRole +"\n" +
+ "Files: \n" +
+ addFile(binaryName, binaryContent) +
+ addFile(controlName, tempControl) +
+ addFile(dataName, tempData);
+
+ ByteArrayOutputStream message = new ByteArrayOutputStream();
+ signer.clearSign(outputStr, message);
+
+ addTo(ar, "_gpg" + signRole, message.toString());
+ }
+ }
ar.close();
-
+
return packageControlFile;
} catch (Exception e) {
@@ -361,6 +539,81 @@ public class DebMaker {
}
}
+ private String addFile(String name, String input){
+ return addLine(md5Hash(input), sha1Hash(input), input.length(), name);
+ }
+
+ private String addFile(String name, File input){
+ return addLine(md5Hash(input), sha1Hash(input), input.length(), name);
+ }
+
+ private String addLine(String md5, String sha1, long size, String name){
+ return "\t" + md5 + " " + sha1 + " " + size + " " + name + "\n";
+ }
+
+ private String md5Hash(String input){
+ return md5Hash(input.getBytes());
+ }
+
+ private String md5Hash(File input){
+ try {
+ return md5Hash(FileUtils.readFileToByteArray(input));
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ private String md5Hash(byte input[]){
+ //update the input of MD5
+ MD5Digest md5 = new MD5Digest();
+ md5.update(input, 0, input.length);
+
+ //get the output/ digest size and hash it
+ byte[] digest = new byte[md5.getDigestSize()];
+ md5.doFinal(digest, 0);
+
+ return new String(Hex.encode(digest));
+ }
+
+ private String sha1Hash(String input){
+ return sha1Hash(input.getBytes());
+ }
+
+ private String sha1Hash(File input){
+ try {
+ return sha1Hash(FileUtils.readFileToByteArray(input));
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ private String sha1Hash(byte input[]){
+ try
+ {
+ //prepare the input
+ MessageDigest hash = MessageDigest.getInstance("SHA1");
+ hash.update(input);
+
+ //proceed ....
+ byte[] digest = hash.digest();
+
+ return new String(Hex.encode(digest));
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ System.err.println("No such algorithm");
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
private void addTo(ArArchiveOutputStream pOutput, String pName, String pContent) throws IOException {
final byte[] content = pContent.getBytes();
pOutput.putArchiveEntry(new ArArchiveEntry(pName, content.length));
@@ -380,4 +633,26 @@ public class DebMaker {
pOutput.closeArchiveEntry();
}
+
+ private void addTo(final PGPSignatureOutputStream pOutput, final String pContent) throws IOException {
+ final byte[] content = pContent.getBytes();
+ pOutput.write(content);
+ }
+
+ private void addTo(final PGPSignatureOutputStream pOutput, final File pContent) throws IOException {
+ final InputStream input = new FileInputStream(pContent);
+ try {
+ Utils.copy(input, pOutput);
+ } finally {
+ input.close();
+ }
+ }
+
+ public void setOpenReplaceToken(String openReplaceToken) {
+ this.openReplaceToken = openReplaceToken;
+ }
+
+ public void setCloseReplaceToken(String closeReplaceToken) {
+ this.closeReplaceToken = closeReplaceToken;
+ }
}
diff --git a/src/main/java/org/vafer/jdeb/PackagingException.java b/src/main/java/org/vafer/jdeb/PackagingException.java
index 5fddfd7..c2eca64 100644
--- a/src/main/java/org/vafer/jdeb/PackagingException.java
+++ b/src/main/java/org/vafer/jdeb/PackagingException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/main/java/org/vafer/jdeb/ant/Data.java b/src/main/java/org/vafer/jdeb/ant/Data.java
index b32872f..f8e5dd9 100644
--- a/src/main/java/org/vafer/jdeb/ant/Data.java
+++ b/src/main/java/org/vafer/jdeb/ant/Data.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,6 +44,8 @@ public final class Data extends PatternSet implements DataProducer {
private String type;
+ private Boolean conffile;
+
private String destinationName;
public void setSrc(File src) {
@@ -58,6 +60,14 @@ public final class Data extends PatternSet implements DataProducer {
this.type = type;
}
+ public void setConffile(Boolean conffile) {
+ this.conffile = conffile;
+ }
+
+ public Boolean getConffile() {
+ return this.conffile;
+ }
+
public void setDst(String destinationName) {
this.destinationName = destinationName;
}
diff --git a/src/main/java/org/vafer/jdeb/ant/DebAntTask.java b/src/main/java/org/vafer/jdeb/ant/DebAntTask.java
index bf8ea43..7b7a5eb 100644
--- a/src/main/java/org/vafer/jdeb/ant/DebAntTask.java
+++ b/src/main/java/org/vafer/jdeb/ant/DebAntTask.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -72,6 +72,7 @@ public class DebAntTask extends MatchingTask {
private Collection<Link> links = new ArrayList<Link>();
private Collection<DataProducer> dataProducers = new ArrayList<DataProducer>();
+ private Collection<DataProducer> conffilesProducers = new ArrayList<DataProducer>();
public void setDestfile( File deb ) {
@@ -145,12 +146,15 @@ public class DebAntTask extends MatchingTask {
} else if (!Arrays.asList("file", "directory", "archive").contains(data.getType().toLowerCase())) {
throw new BuildException("The type '" + data.getType() + "' of the data element is unknown (expected 'file', 'directory' or 'archive')");
}
+ if (data.getConffile() != null && data.getConffile()) {
+ conffilesProducers.add(dataProducer);
+ }
}
}
Console console = new TaskConsole(this, verbose);
- DebMaker debMaker = new DebMaker(console, dataProducers);
+ DebMaker debMaker = new DebMaker(console, dataProducers, conffilesProducers);
debMaker.setDeb(deb);
debMaker.setControl(control);
debMaker.setChangesIn(changesIn);
diff --git a/src/main/java/org/vafer/jdeb/ant/Link.java b/src/main/java/org/vafer/jdeb/ant/Link.java
index 7a7a928..3cad190 100644
--- a/src/main/java/org/vafer/jdeb/ant/Link.java
+++ b/src/main/java/org/vafer/jdeb/ant/Link.java
@@ -1,109 +1,109 @@
-/*
- * Copyright 2013 The jdeb developers.
- *
- * 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 org.vafer.jdeb.ant;
-
-import org.apache.commons.compress.archivers.zip.UnixStat;
-import org.vafer.jdeb.DataProducer;
-import org.vafer.jdeb.mapping.PermMapper;
-import org.vafer.jdeb.producers.DataProducerLink;
-
-/**
- * Defines a symbolic or hard link.
- *
- * @author Emmanuel Bourg
- * @version $Revision$, $Date$
- */
-public final class Link {
-
- private String name;
- private String target;
- private boolean symbolic = true;
- private String username = "root";
- private String group = "root";
- private int uid = 0;
- private int gid = 0;
- private int mode = UnixStat.LINK_FLAG | UnixStat.DEFAULT_LINK_PERM;
-
- DataProducer toDataProducer() {
- org.vafer.jdeb.mapping.Mapper mapper = new PermMapper(uid, gid, username, group, mode, mode, 0, null);
- return new DataProducerLink(name, target, symbolic, null, null, new org.vafer.jdeb.mapping.Mapper[]{mapper});
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getTarget() {
- return target;
- }
-
- public void setTarget(String target) {
- this.target = target;
- }
-
- public boolean isSymbolic() {
- return symbolic;
- }
-
- public void setSymbolic(boolean symbolic) {
- this.symbolic = symbolic;
- }
-
- public String getUsername() {
- return username;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
- public String getGroup() {
- return group;
- }
-
- public void setGroup(String group) {
- this.group = group;
- }
-
- public int getUid() {
- return uid;
- }
-
- public void setUid(int uid) {
- this.uid = uid;
- }
-
- public int getGid() {
- return gid;
- }
-
- public void setGid(int gid) {
- this.gid = gid;
- }
-
- public int getMode() {
- return mode;
- }
-
- public void setMode(String mode) {
- this.mode = UnixStat.LINK_FLAG | Integer.parseInt(mode, 8);
- }
-}
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb.ant;
+
+import org.apache.commons.compress.archivers.zip.UnixStat;
+import org.vafer.jdeb.DataProducer;
+import org.vafer.jdeb.mapping.PermMapper;
+import org.vafer.jdeb.producers.DataProducerLink;
+
+/**
+ * Defines a symbolic or hard link.
+ *
+ * @author Emmanuel Bourg
+ * @version $Revision$, $Date$
+ */
+public final class Link {
+
+ private String name;
+ private String target;
+ private boolean symbolic = true;
+ private String username = "root";
+ private String group = "root";
+ private int uid = 0;
+ private int gid = 0;
+ private int mode = UnixStat.LINK_FLAG | UnixStat.DEFAULT_LINK_PERM;
+
+ DataProducer toDataProducer() {
+ org.vafer.jdeb.mapping.Mapper mapper = new PermMapper(uid, gid, username, group, mode, mode, 0, null);
+ return new DataProducerLink(name, target, symbolic, null, null, new org.vafer.jdeb.mapping.Mapper[]{mapper});
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getTarget() {
+ return target;
+ }
+
+ public void setTarget(String target) {
+ this.target = target;
+ }
+
+ public boolean isSymbolic() {
+ return symbolic;
+ }
+
+ public void setSymbolic(boolean symbolic) {
+ this.symbolic = symbolic;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getGroup() {
+ return group;
+ }
+
+ public void setGroup(String group) {
+ this.group = group;
+ }
+
+ public int getUid() {
+ return uid;
+ }
+
+ public void setUid(int uid) {
+ this.uid = uid;
+ }
+
+ public int getGid() {
+ return gid;
+ }
+
+ public void setGid(int gid) {
+ this.gid = gid;
+ }
+
+ public int getMode() {
+ return mode;
+ }
+
+ public void setMode(String mode) {
+ this.mode = UnixStat.LINK_FLAG | Integer.parseInt(mode, 8);
+ }
+}
diff --git a/src/main/java/org/vafer/jdeb/ant/Mapper.java b/src/main/java/org/vafer/jdeb/ant/Mapper.java
index e99dd1b..7c562f5 100644
--- a/src/main/java/org/vafer/jdeb/ant/Mapper.java
+++ b/src/main/java/org/vafer/jdeb/ant/Mapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,8 +39,8 @@ public final class Mapper {
private int gid = -1;
private String user;
private String group;
- private int fileMode = -1;
- private int dirMode = -1;
+ private String fileMode;
+ private String dirMode;
public void setType( final String pType ) {
mapperType = pType;
@@ -76,11 +76,11 @@ public final class Mapper {
group = pGroup;
}
- public void setFileMode( final int pFileMode ) {
+ public void setFileMode( final String pFileMode ) {
fileMode = pFileMode;
}
- public void setDirMode( int pDirMode ) {
+ public void setDirMode( final String pDirMode ) {
dirMode = pDirMode;
}
diff --git a/src/main/java/org/vafer/jdeb/ant/TaskConsole.java b/src/main/java/org/vafer/jdeb/ant/TaskConsole.java
index 066455f..46b643d 100644
--- a/src/main/java/org/vafer/jdeb/ant/TaskConsole.java
+++ b/src/main/java/org/vafer/jdeb/ant/TaskConsole.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +16,13 @@
package org.vafer.jdeb.ant;
+import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.vafer.jdeb.Console;
/**
- * Console implementation for Ant tasks.
+ * Console implementation for Ant tasks. debug messages are only displayed
+ * when the <tt>verbose</tt> parameter is true.
*/
class TaskConsole implements Console {
@@ -32,14 +34,21 @@ class TaskConsole implements Console {
this.verbose = verbose;
}
- public void info(String message) {
+ @Override
+ public void debug(String message) {
if (verbose) {
task.log(message);
}
}
- public void warn(String message) {
+ @Override
+ public void info(String message) {
task.log(message);
}
+ @Override
+ public void warn(String message) {
+ task.log(message, Project.MSG_WARN);
+ }
+
}
diff --git a/src/main/java/org/vafer/jdeb/changes/ChangeSet.java b/src/main/java/org/vafer/jdeb/changes/ChangeSet.java
index 4ebc3c5..e6adb2b 100644
--- a/src/main/java/org/vafer/jdeb/changes/ChangeSet.java
+++ b/src/main/java/org/vafer/jdeb/changes/ChangeSet.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/main/java/org/vafer/jdeb/changes/ChangesProvider.java b/src/main/java/org/vafer/jdeb/changes/ChangesProvider.java
index 235ded8..9282747 100644
--- a/src/main/java/org/vafer/jdeb/changes/ChangesProvider.java
+++ b/src/main/java/org/vafer/jdeb/changes/ChangesProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/main/java/org/vafer/jdeb/changes/TextfileChangesProvider.java b/src/main/java/org/vafer/jdeb/changes/TextfileChangesProvider.java
index ed97531..900166e 100644
--- a/src/main/java/org/vafer/jdeb/changes/TextfileChangesProvider.java
+++ b/src/main/java/org/vafer/jdeb/changes/TextfileChangesProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/main/java/org/vafer/jdeb/debian/BinaryPackageControlFile.java b/src/main/java/org/vafer/jdeb/debian/BinaryPackageControlFile.java
index 274b53d..9931969 100644
--- a/src/main/java/org/vafer/jdeb/debian/BinaryPackageControlFile.java
+++ b/src/main/java/org/vafer/jdeb/debian/BinaryPackageControlFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,6 +65,11 @@ public final class BinaryPackageControlFile extends ControlFile {
}
@Override
+ public void set(final String field, final String value) {
+ super.set(field, value);
+ }
+
+ @Override
protected ControlField[] getFields() {
return FIELDS;
}
@@ -72,14 +77,19 @@ public final class BinaryPackageControlFile extends ControlFile {
/**
* Returns the short description of the package. The short description
* consists in the first line of the Description field.
- *
+ *
* @return
*/
public String getShortDescription() {
if (get("Description") == null) {
return null;
}
-
+
return get("Description").split("\n")[0];
}
+
+ @Override
+ protected char getUserDefinedFieldLetter() {
+ return 'B';
+ }
}
diff --git a/src/main/java/org/vafer/jdeb/debian/ChangesFile.java b/src/main/java/org/vafer/jdeb/debian/ChangesFile.java
index 49bc6b9..e3c46c7 100644
--- a/src/main/java/org/vafer/jdeb/debian/ChangesFile.java
+++ b/src/main/java/org/vafer/jdeb/debian/ChangesFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +16,13 @@
package org.vafer.jdeb.debian;
+import org.vafer.jdeb.changes.ChangeSet;
+
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.Date;
import java.util.Locale;
-
-import org.vafer.jdeb.changes.ChangeSet;
+import java.util.Map.Entry;
/**
* Reflecting a changes file
@@ -30,8 +32,6 @@ import org.vafer.jdeb.changes.ChangeSet;
*/
public final class ChangesFile extends ControlFile {
- public static final DateFormat DATE_FORMAT = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH); // RFC 2822 format
-
private static final ControlField[] FIELDS = {
new ControlField("Format", true),
new ControlField("Date", true),
@@ -53,13 +53,14 @@ public final class ChangesFile extends ControlFile {
public ChangesFile() {
set("Format", "1.8");
+ set("Urgency", "low");
set("Distribution", "stable");
}
/**
* Initializes the fields on the changes file with the values of the specified
* binary package control file.
- *
+ *
* @param packageControlFile
*/
public void initialize(BinaryPackageControlFile packageControlFile) {
@@ -69,7 +70,12 @@ public final class ChangesFile extends ControlFile {
set("Version", packageControlFile.get("Version"));
set("Maintainer", packageControlFile.get("Maintainer"));
set("Changed-By", packageControlFile.get("Maintainer"));
-
+ set("Distribution", packageControlFile.get("Distribution"));
+
+ for (Entry<String, String> entry : packageControlFile.getUserDefinedFields().entrySet()) {
+ set(entry.getKey(), entry.getValue());
+ }
+
StringBuilder description = new StringBuilder();
description.append(packageControlFile.get("Package"));
if (packageControlFile.get("Description") != null) {
@@ -86,7 +92,7 @@ public final class ChangesFile extends ControlFile {
final ChangeSet mostRecentChangeSet = changeSets[0];
set("Urgency", mostRecentChangeSet.getUrgency());
set("Changed-By", mostRecentChangeSet.getChangedBy());
-
+
for (ChangeSet changeSet : changeSets) {
sb.append(changeSet.toString());
}
@@ -99,4 +105,14 @@ public final class ChangesFile extends ControlFile {
protected ControlField[] getFields() {
return FIELDS;
}
+
+ @Override
+ protected char getUserDefinedFieldLetter() {
+ return 'C';
+ }
+
+ public static String formatDate(Date date) {
+ final DateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH); // RFC 2822 format
+ return format.format(date);
+ }
}
diff --git a/src/main/java/org/vafer/jdeb/debian/ControlField.java b/src/main/java/org/vafer/jdeb/debian/ControlField.java
index 73e37ba..c08e73b 100644
--- a/src/main/java/org/vafer/jdeb/debian/ControlField.java
+++ b/src/main/java/org/vafer/jdeb/debian/ControlField.java
@@ -1,130 +1,130 @@
-/*
- * Copyright 2013 The jdeb developers.
- *
- * 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 org.vafer.jdeb.debian;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.StringReader;
-
-/**
- * A field of a control file. This class is immutable.
- *
- * @author Emmanuel Bourg
- */
-public class ControlField {
-
- /**
- * The format of a field.
- */
- public enum Type {
- /** Value on a single line */
- SIMPLE,
- /** Value on multiple lines, space characters are ignored */
- FOLDED,
- /** Value on multiple lines, space characters are preserved */
- MULTILINE
- }
-
- /** The name of the field */
- private String name;
-
- /** Tells if the field is mandatory */
- private boolean mandatory;
-
- /** The type of the field */
- private Type type = Type.SIMPLE;
-
- /** Tells is the first line of the field must be empty (for MULTILINE values only) */
- private boolean firstLineEmpty;
-
-
- public ControlField(String name) {
- this(name, false);
- }
-
- public ControlField(String name, boolean mandatory) {
- this(name, mandatory, Type.SIMPLE);
- }
-
- public ControlField(String name, boolean mandatory, Type type) {
- this(name, mandatory, type, false);
- }
-
- public ControlField(String name, boolean mandatory, Type type, boolean firstLineEmpty) {
- this.name = name;
- this.mandatory = mandatory;
- this.type = type;
- this.firstLineEmpty = firstLineEmpty;
- }
-
- public String getName() {
- return name;
- }
-
- public boolean isMandatory() {
- return mandatory;
- }
-
- public Type getType() {
- return type;
- }
-
- public boolean isFirstLineEmpty() {
- return firstLineEmpty;
- }
-
- /**
- * Returns the field with the specified value properly formatted. Multiline
- * values are automatically indented, and dots are added on the empty lines.
- *
- * <pre>
- * Field-Name: value
- * </pre>
- */
- public String format(String value) {
- StringBuilder s = new StringBuilder();
-
- if (value != null && value.trim().length() > 0) {
- boolean continuationLine = false;
-
- s.append(getName()).append(":");
- if (isFirstLineEmpty()) {
- s.append("\n");
- continuationLine = true;
- }
-
- try {
- BufferedReader reader = new BufferedReader(new StringReader(value));
- String line;
- while ((line = reader.readLine()) != null) {
- if (continuationLine && line.trim().length() == 0) {
- // put a dot on the empty continuation lines
- s.append(" .\n");
- } else {
- s.append(" ").append(line).append("\n");
- }
-
- continuationLine = true;
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- return s.toString();
- }
-}
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb.debian;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+
+/**
+ * A field of a control file. This class is immutable.
+ *
+ * @author Emmanuel Bourg
+ */
+public class ControlField {
+
+ /**
+ * The format of a field.
+ */
+ public enum Type {
+ /** Value on a single line */
+ SIMPLE,
+ /** Value on multiple lines, space characters are ignored */
+ FOLDED,
+ /** Value on multiple lines, space characters are preserved */
+ MULTILINE
+ }
+
+ /** The name of the field */
+ private String name;
+
+ /** Tells if the field is mandatory */
+ private boolean mandatory;
+
+ /** The type of the field */
+ private Type type = Type.SIMPLE;
+
+ /** Tells is the first line of the field must be empty (for MULTILINE values only) */
+ private boolean firstLineEmpty;
+
+
+ public ControlField(String name) {
+ this(name, false);
+ }
+
+ public ControlField(String name, boolean mandatory) {
+ this(name, mandatory, Type.SIMPLE);
+ }
+
+ public ControlField(String name, boolean mandatory, Type type) {
+ this(name, mandatory, type, false);
+ }
+
+ public ControlField(String name, boolean mandatory, Type type, boolean firstLineEmpty) {
+ this.name = name;
+ this.mandatory = mandatory;
+ this.type = type;
+ this.firstLineEmpty = firstLineEmpty;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public boolean isMandatory() {
+ return mandatory;
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public boolean isFirstLineEmpty() {
+ return firstLineEmpty;
+ }
+
+ /**
+ * Returns the field with the specified value properly formatted. Multiline
+ * values are automatically indented, and dots are added on the empty lines.
+ *
+ * <pre>
+ * Field-Name: value
+ * </pre>
+ */
+ public String format(String value) {
+ StringBuilder s = new StringBuilder();
+
+ if (value != null && value.trim().length() > 0) {
+ boolean continuationLine = false;
+
+ s.append(getName()).append(":");
+ if (isFirstLineEmpty()) {
+ s.append("\n");
+ continuationLine = true;
+ }
+
+ try {
+ BufferedReader reader = new BufferedReader(new StringReader(value));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ if (continuationLine && line.trim().length() == 0) {
+ // put a dot on the empty continuation lines
+ s.append(" .\n");
+ } else {
+ s.append(" ").append(line).append("\n");
+ }
+
+ continuationLine = true;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ return s.toString();
+ }
+}
diff --git a/src/main/java/org/vafer/jdeb/debian/ControlFile.java b/src/main/java/org/vafer/jdeb/debian/ControlFile.java
index 00c8b10..e014683 100644
--- a/src/main/java/org/vafer/jdeb/debian/ControlFile.java
+++ b/src/main/java/org/vafer/jdeb/debian/ControlFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
@@ -37,6 +38,8 @@ import java.util.Set;
public abstract class ControlFile {
protected final Map<String, String> values = new LinkedHashMap<String, String>();
+ protected final Map<String, String> userDefinedFields = new LinkedHashMap<String, String>();
+ protected final Set<ControlField> userDefinedFieldNames = new HashSet<ControlField>();
public void parse(String input) throws IOException, ParseException {
parse(new ByteArrayInputStream(input.getBytes("UTF-8")));
@@ -51,10 +54,8 @@ public abstract class ControlFile {
final String line = reader.readLine();
if (line == null) {
- if (buffer.length() > 0) {
- // flush value of the previous field
- set(field, buffer.toString());
- }
+ // flush value of the previous field
+ set(field, buffer.toString());
break;
}
@@ -69,11 +70,9 @@ public abstract class ControlFile {
// new field
- if (buffer.length() > 0) {
- // flush value of the previous field
- set(field, buffer.toString());
- buffer = new StringBuilder();
- }
+ // flush value of the previous field
+ set(field, buffer.toString());
+ buffer = new StringBuilder();
final int i = line.indexOf(':');
@@ -98,8 +97,19 @@ public abstract class ControlFile {
}
- public void set(final String field, final String value) {
- if (!"".equals(value)) {
+ public void set(String field, final String value) {
+ if (field != null && isUserDefinedField(field)) {
+ userDefinedFields.put(field, value);
+ String fieldName = getUserDefinedFieldName(field);
+
+ if (fieldName != null) {
+ userDefinedFieldNames.add(new ControlField(fieldName));
+ }
+
+ field = fieldName;
+ }
+
+ if (field != null && !"".equals(field)) {
values.put(field, value);
}
}
@@ -110,6 +120,14 @@ public abstract class ControlFile {
protected abstract ControlField[] getFields();
+ protected Map<String, String> getUserDefinedFields() {
+ return userDefinedFields;
+ }
+
+ protected Set<ControlField> getUserDefinedFieldNames() {
+ return userDefinedFieldNames;
+ }
+
public List<String> getMandatoryFields() {
List<String> fields = new ArrayList<String>();
@@ -118,7 +136,7 @@ public abstract class ControlFile {
fields.add(field.getName());
}
}
-
+
return fields;
}
@@ -128,7 +146,7 @@ public abstract class ControlFile {
public Set<String> invalidFields() {
Set<String> invalid = new HashSet<String>();
-
+
for (ControlField field : getFields()) {
if (field.isMandatory() && get(field.getName()) == null) {
invalid.add(field.getName());
@@ -148,6 +166,60 @@ public abstract class ControlFile {
}
public String toString() {
- return toString(getFields());
+ List<ControlField> fields = new ArrayList<ControlField>();
+ fields.addAll(Arrays.asList(getFields()));
+ fields.addAll(getUserDefinedFieldNames());
+ return toString(fields.toArray(new ControlField[fields.size()]));
+ }
+
+ /**
+ * Returns the letter expected in the prefix of a user defined field
+ * in order to include the field in this control file.
+ *
+ * @return The letter returned is:
+ * <ul>
+ * <li>B: for a binary package</li>
+ * <li>S: for a source package</li>
+ * <li>C: for a changes file</li>
+ * </ul>
+ *
+ * @since 1.1
+ * @see <a href="http://www.debian.org/doc/debian-policy/ch-controlfields.html#s5.7">Debian Policy - User-defined fields</a>
+ */
+ protected abstract char getUserDefinedFieldLetter();
+
+ /**
+ * Tells if the specified field name is a user defined field.
+ * User-defined fields must begin with an 'X', followed by one or more
+ * letters that specify the output file and a hyphen.
+ *
+ * @param field the name of the field
+ *
+ * @since 1.1
+ * @see <a href="http://www.debian.org/doc/debian-policy/ch-controlfields.html#s5.7">Debian Policy - User-defined fields</a>
+ */
+ protected boolean isUserDefinedField(String field) {
+ return field.startsWith("X") && field.indexOf("-") > 0;
+ }
+
+ /**
+ * Returns the user defined field without its prefix.
+ *
+ * @param field the name of the user defined field
+ * @return the user defined field without the prefix, or null if the fields
+ * doesn't apply to this control file.
+ * @since 1.1
+ */
+ protected String getUserDefinedFieldName(String field) {
+ int index = field.indexOf('-');
+ char letter = getUserDefinedFieldLetter();
+
+ for (int i = 0; i < index; ++i) {
+ if (field.charAt(i) == letter) {
+ return field.substring(index + 1);
+ }
+ }
+
+ return null;
}
}
diff --git a/src/main/java/org/vafer/jdeb/mapping/LsMapper.java b/src/main/java/org/vafer/jdeb/mapping/LsMapper.java
index fdf19c5..1998c72 100644
--- a/src/main/java/org/vafer/jdeb/mapping/LsMapper.java
+++ b/src/main/java/org/vafer/jdeb/mapping/LsMapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/main/java/org/vafer/jdeb/mapping/Mapper.java b/src/main/java/org/vafer/jdeb/mapping/Mapper.java
index 1229fda..2f30727 100644
--- a/src/main/java/org/vafer/jdeb/mapping/Mapper.java
+++ b/src/main/java/org/vafer/jdeb/mapping/Mapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/main/java/org/vafer/jdeb/mapping/NullMapper.java b/src/main/java/org/vafer/jdeb/mapping/NullMapper.java
index de5b115..1c8a8d3 100644
--- a/src/main/java/org/vafer/jdeb/mapping/NullMapper.java
+++ b/src/main/java/org/vafer/jdeb/mapping/NullMapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/main/java/org/vafer/jdeb/mapping/PermMapper.java b/src/main/java/org/vafer/jdeb/mapping/PermMapper.java
index f3c6701..66b8583 100644
--- a/src/main/java/org/vafer/jdeb/mapping/PermMapper.java
+++ b/src/main/java/org/vafer/jdeb/mapping/PermMapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/main/java/org/vafer/jdeb/maven/AbstractPluginMojo.java b/src/main/java/org/vafer/jdeb/maven/AbstractPluginMojo.java
deleted file mode 100644
index de3cf65..0000000
--- a/src/main/java/org/vafer/jdeb/maven/AbstractPluginMojo.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2013 The jdeb developers.
- *
- * 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 org.vafer.jdeb.maven;
-
-import java.io.File;
-
-import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.project.MavenProject;
-
-public abstract class AbstractPluginMojo extends AbstractMojo {
-
- /**
- * @parameter expression="${project}"
- * @required
- * @readonly
- */
- private MavenProject project;
-
- /**
- * @parameter expression="${project.build.directory}"
- * @required
- * @readonly
- */
- protected File buildDirectory;
-
- protected MavenProject getProject() {
- if (project.getExecutionProject() != null) {
- return project.getExecutionProject();
- }
-
- return project;
- }
-
-}
diff --git a/src/main/java/org/vafer/jdeb/maven/Data.java b/src/main/java/org/vafer/jdeb/maven/Data.java
index 0f1dd41..e4309c4 100644
--- a/src/main/java/org/vafer/jdeb/maven/Data.java
+++ b/src/main/java/org/vafer/jdeb/maven/Data.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,10 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.vafer.jdeb.maven;
-import static org.vafer.jdeb.maven.MissingSourceBehavior.FAIL;
-import static org.vafer.jdeb.maven.MissingSourceBehavior.IGNORE;
+package org.vafer.jdeb.maven;
import java.io.File;
import java.io.FileNotFoundException;
@@ -25,14 +23,18 @@ import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
+import org.apache.maven.plugins.annotations.Parameter;
import org.vafer.jdeb.DataConsumer;
import org.vafer.jdeb.DataProducer;
import org.vafer.jdeb.producers.DataProducerArchive;
import org.vafer.jdeb.producers.DataProducerDirectory;
import org.vafer.jdeb.producers.DataProducerFile;
+import org.vafer.jdeb.producers.DataProducerFiles;
import org.vafer.jdeb.producers.DataProducerLink;
import org.vafer.jdeb.producers.DataProducerPathTemplate;
+import static org.vafer.jdeb.maven.MissingSourceBehavior.*;
+
/**
* Maven "data" element acting as a factory for DataProducers. So far Archive and
* Directory producers are supported. Both support the usual ant pattern set
@@ -42,38 +44,30 @@ import org.vafer.jdeb.producers.DataProducerPathTemplate;
*/
public final class Data implements DataProducer {
+ @Parameter
private File src;
- /**
- * @parameter expression="${src}"
- */
public void setSrc( File src ) {
this.src = src;
}
+ @Parameter
private String dst;
- /**
- * @parameter expression="${dst}"
- */
public void setDst( String dst ) {
this.dst = dst;
}
+ @Parameter
private String type;
- /**
- * @parameter expression="${type}"
- */
public void setType( String type ) {
this.type = type;
}
+ @Parameter
private MissingSourceBehavior missingSrc = FAIL;
- /**
- * @parameter expression="${missingSrc}"
- */
public void setMissingSrc( String missingSrc ) {
MissingSourceBehavior value = MissingSourceBehavior.valueOf(missingSrc.trim().toUpperCase());
if (value == null) {
@@ -82,59 +76,58 @@ public final class Data implements DataProducer {
this.missingSrc = value;
}
+ @Parameter
private String linkName;
- /**
- * @parameter expression="${linkName}"
- */
public void setLinkName(String linkName) {
this.linkName = linkName;
}
+ @Parameter
private String linkTarget;
- /**
- * @parameter expression="${linkTarget}"
- */
public void setLinkTarget(String linkTarget) {
this.linkTarget = linkTarget;
}
+ @Parameter
private boolean symlink = true;
- /**
- * @parameter expression="${symlink}"
- */
public void setSymlink(boolean symlink) {
this.symlink = symlink;
}
-
- private String[] includePatterns;
+
+ private boolean conffile = false;
/**
- * @parameter expression="${includes}" alias="includes"
+ * @parameter expression="${conffile}"
*/
+ public void setConffile(boolean conffile) {
+ this.conffile = conffile;
+ }
+
+ public boolean getConffile() {
+ return this.conffile;
+ }
+
+ @Parameter(alias = "includes")
+ private String[] includePatterns;
+
public void setIncludes( String includes ) {
includePatterns = splitPatterns(includes);
}
+ @Parameter(alias = "excludes")
private String[] excludePatterns;
- /**
- * @parameter expression="${excludes}" alias="excludes"
- */
public void setExcludes( String excludes ) {
excludePatterns = splitPatterns(excludes);
}
- /**
- * @parameter expression="${mapper}"
- */
+ @Parameter
private Mapper mapper;
- /**
- * @parameter expression="${paths}"
- */
+ @Parameter
private String[] paths;
/* For testing only */
@@ -163,7 +156,7 @@ public final class Data implements DataProducer {
// link type
- if ("link".equalsIgnoreCase(type)) {
+ if (typeIs("link")) {
if (linkName == null) {
throw new RuntimeException("linkName is not set");
}
@@ -177,15 +170,18 @@ public final class Data implements DataProducer {
// template type
- if ("template".equalsIgnoreCase(type)) {
- if (paths == null || paths.length == 0) {
- throw new RuntimeException("paths is not set");
- }
-
+ if (typeIs("template")) {
+ checkPaths();
new DataProducerPathTemplate(paths, includePatterns, excludePatterns, mappers).produce(pReceiver);
return;
}
+ if (typeIs("files")) {
+ checkPaths();
+ new DataProducerFiles(paths, dst, mappers).produce(pReceiver);
+ return;
+ }
+
// Types that require src to exist
if (src == null || !src.exists()) {
@@ -196,17 +192,17 @@ public final class Data implements DataProducer {
}
}
- if ("file".equalsIgnoreCase(type)) {
+ if (typeIs("file")) {
new DataProducerFile(src, dst, includePatterns, excludePatterns, mappers).produce(pReceiver);
return;
}
- if ("archive".equalsIgnoreCase(type)) {
+ if (typeIs("archive")) {
new DataProducerArchive(src, includePatterns, excludePatterns, mappers).produce(pReceiver);
return;
}
- if ("directory".equalsIgnoreCase(type)) {
+ if (typeIs("directory")) {
new DataProducerDirectory(src, includePatterns, excludePatterns, mappers).produce(pReceiver);
return;
}
@@ -214,4 +210,13 @@ public final class Data implements DataProducer {
throw new IOException("Unknown type '" + type + "' (file|directory|archive|template|link) for " + src);
}
+ private boolean typeIs( final String type ) {
+ return type.equalsIgnoreCase(this.type);
+ }
+
+ private void checkPaths() {
+ if (paths == null || paths.length == 0) {
+ throw new RuntimeException("paths parameter is not set");
+ }
+ }
}
diff --git a/src/main/java/org/vafer/jdeb/maven/DebMojo.java b/src/main/java/org/vafer/jdeb/maven/DebMojo.java
index 9d67332..d2b47d9 100644
--- a/src/main/java/org/vafer/jdeb/maven/DebMojo.java
+++ b/src/main/java/org/vafer/jdeb/maven/DebMojo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package org.vafer.jdeb.maven;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -29,92 +30,91 @@ import java.util.Set;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Component;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectHelper;
+import org.apache.maven.settings.Profile;
+import org.apache.maven.settings.Settings;
import org.apache.tools.tar.TarEntry;
+import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
+import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException;
import org.vafer.jdeb.Console;
import org.vafer.jdeb.DataConsumer;
import org.vafer.jdeb.DataProducer;
import org.vafer.jdeb.DebMaker;
import org.vafer.jdeb.PackagingException;
-import org.vafer.jdeb.utils.FilteredFile;
import org.vafer.jdeb.utils.MapVariableResolver;
import org.vafer.jdeb.utils.Utils;
import org.vafer.jdeb.utils.VariableResolver;
+import static org.vafer.jdeb.utils.Utils.lookupIfEmpty;
+
/**
- * Creates deb archive
- *
- * @goal jdeb
- * @phase package
+ * Creates Debian package
*/
-public class DebMojo extends AbstractPluginMojo {
+ at Mojo(name = "jdeb", defaultPhase = LifecyclePhase.PACKAGE)
+public class DebMojo extends AbstractMojo {
- /**
- * @component
- */
+ @Component
private MavenProjectHelper projectHelper;
-
+
+ @Component(hint = "jdeb-sec")
+ private SecDispatcher secDispatcher;
+
/**
* Defines the name of deb package.
- *
- * @parameter
*/
+ @Parameter
private String name;
/**
* Defines the pattern of the name of final artifacts. Possible
* substitutions are [[baseDir]] [[buildDir]] [[artifactId]] [[version]]
* [[extension]] and [[groupId]].
- *
- * @parameter default-value="[[buildDir]]/[[artifactId]]_[[version]]_all.[[extension]]"
*/
+ @Parameter(defaultValue = "[[buildDir]]/[[artifactId]]_[[version]]_all.[[extension]]")
private String deb;
/**
* Explicitly defines the path to the control directory. At least the
* control file is mandatory.
- *
- * @parameter default-value="[[baseDir]]/src/deb/control"
*/
+ @Parameter(defaultValue = "[[baseDir]]/src/deb/control")
private String controlDir;
/**
* Explicitly define the file to read the changes from.
- *
- * @parameter default-value="[[baseDir]]/CHANGES.txt"
*/
+ @Parameter(defaultValue = "[[baseDir]]/CHANGES.txt")
private String changesIn;
/**
* Explicitly define the file where to write the changes to.
- *
- * @parameter default-value="[[buildDir]]/[[artifactId]]_[[version]]_all.changes"
*/
+ @Parameter(defaultValue = "[[buildDir]]/[[artifactId]]_[[version]]_all.changes")
private String changesOut;
/**
- * Explicitly define the file where to write the changes of the changes
- * input to.
- *
- * @parameter default-value="[[baseDir]]/CHANGES.txt"
+ * Explicitly define the file where to write the changes of the changes input to.
*/
+ @Parameter(defaultValue = "[[baseDir]]/CHANGES.txt")
private String changesSave;
/**
* The compression method used for the data file (none, gzip, bzip2 or xz)
- *
- * @parameter default-value="gzip"
*/
+ @Parameter(defaultValue = "gzip")
private String compression;
-
/**
* Boolean option whether to attach the artifact to the project
- *
- * @parameter default-value="true"
*/
+ @Parameter(defaultValue = "true")
private String attach;
/**
@@ -122,51 +122,44 @@ public class DebMojo extends AbstractPluginMojo {
* packages are installed in /opt (see the FHS here:
* http://www.pathname.com/
* fhs/pub/fhs-2.3.html#OPTADDONAPPLICATIONSOFTWAREPACKAGES)
- *
- * @parameter default-value="/opt/[[artifactId]]"
*/
+ @Parameter(defaultValue = "/opt/[[artifactId]]")
private String installDir;
-
/**
* The type of attached artifact
- *
- * @parameter default-value="deb"
*/
+ @Parameter(defaultValue = "deb")
private String type;
/**
* The project base directory
- *
- * @parameter default-value="${basedir}"
- * @required
- * @readonly
*/
+ @Parameter(defaultValue = "${basedir}", required = true, readonly = true)
private File baseDir;
/**
- * Run the plugin on all sub-modules.
- * If set to false, the plugin will be run in the same folder where the
- * mvn command was invoked
- *
- * @parameter expression="${submodules}" default-value="true"
+ * The Maven Session Object
*/
- private boolean submodules;
+ @Parameter( defaultValue = "${session}", readonly = true )
+ private MavenSession session;
+
+ /**
+ * The Maven Project Object
+ */
+ @Parameter( defaultValue = "${project}", readonly = true )
+ private MavenProject project;
/**
- * The Maven Session Object
- *
- * @parameter expression="${session}"
- * @required
- * @readonly
+ * The build directory
*/
- private MavenSession session;
+ @Parameter(property = "project.build.directory", required = true, readonly = true)
+ private File buildDirectory;
/**
* The classifier of attached artifact
- *
- * @parameter
*/
+ @Parameter
private String classifier;
/**
@@ -174,7 +167,8 @@ public class DebMojo extends AbstractPluginMojo {
* The "data" entries may specify a tarball (tar.gz, tar.bz2, tgz), a
* directory, or a normal file. An entry would look something like this in
* your pom.xml:
- *
+ *
+ *
* <pre>
* <build>
* <plugins>
@@ -221,57 +215,151 @@ public class DebMojo extends AbstractPluginMojo {
* </plugins>
* </build>
* </pre>
- *
- * @parameter expression="${dataSet}"
+ *
*/
+ @Parameter
private Data[] dataSet;
/**
- * When SNAPSHOT version replace <code>SNAPSHOT</code> with current date
- * and time to make sure each build is unique.
- *
- * @parameter expression="${timestamped}" default-value="false"
- */
+ * @deprecated
+ @Parameter(defaultValue = "false")
private boolean timestamped;
+ */
/**
- * If verbose is true info messages also get logged.
- * Will be changed to "false" in future versions.
- * Left to "true" for the transition.
- *
- * @parameter expression="${verbose}" default-value="true"
+ * When enabled SNAPSHOT inside the version gets replaced with current timestamp or
+ * if set a value of a environment variable.
+ */
+ @Parameter(defaultValue = "false")
+ private boolean snapshotExpand;
+
+ /**
+ * Which environment variable to check for the SNAPSHOT value.
+ * If the variable is not set/empty it will default to use the timestamp.
*/
+ @Parameter(defaultValue = "SNAPSHOT")
+ private String snapshotEnv;
+
+ /**
+ * If verbose is true more build messages are logged.
+ */
+ @Parameter(defaultValue = "false")
private boolean verbose;
+ /**
+ * Indicates if the execution should be disabled. If <code>true</code>, nothing will occur during execution.
+ *
+ * @since 1.1
+ */
+ @Parameter(defaultValue = "false")
+ private boolean skip;
+
+ @Parameter(defaultValue = "true")
+ private boolean skipPOMs;
+
+ @Parameter(defaultValue = "false")
+ private boolean skipSubmodules;
+
+ /**
+ * @deprecated
+ */
+ @Parameter(defaultValue = "true")
+ private boolean submodules;
+
+
+ /**
+ * If signPackage is true then a origin signature will be placed
+ * in the generated package.
+ */
+ @Parameter(defaultValue = "false")
+ private boolean signPackage;
+
+ /**
+ * Defines which utility is used to verify the signed package
+ */
+ @Parameter(defaultValue = "debsig-verify")
+ private String signMethod;
+
+ /**
+ * Defines the role to sign with
+ */
+ @Parameter(defaultValue = "origin")
+ private String signRole;
+
+ /**
+ * The keyring to use for signing operations.
+ */
+ @Parameter
+ private String keyring;
+
+ /**
+ * The key to use for signing operations.
+ */
+ @Parameter
+ private String key;
+
+ /**
+ * The passphrase to use for signing operations.
+ */
+ @Parameter
+ private String passphrase;
+
+ /**
+ * The prefix to use when reading signing variables
+ * from settings.
+ */
+ @Parameter(defaultValue = "jdeb.")
+ private String signCfgPrefix;
+
+ /**
+ * The settings.
+ */
+ @Parameter(defaultValue = "${settings}")
+ private Settings settings;
+
/* end of parameters */
+
+ private static final String KEY = "key";
+ private static final String KEYRING = "keyring";
+ private static final String PASSPHRASE = "passphrase";
private String openReplaceToken = "[[";
private String closeReplaceToken = "]]";
+ private Console console;
private Collection<DataProducer> dataProducers = new ArrayList<DataProducer>();
+ private Collection<DataProducer> conffileProducers = new ArrayList<DataProducer>();
public void setOpenReplaceToken( String openReplaceToken ) {
this.openReplaceToken = openReplaceToken;
- // FIXME yuck!
- FilteredFile.setOpenToken(openReplaceToken);
}
public void setCloseReplaceToken( String closeReplaceToken ) {
this.closeReplaceToken = closeReplaceToken;
- // FIXME yuck!
- FilteredFile.setCloseToken(closeReplaceToken);
}
protected void setData( Data[] dataSet ) {
this.dataSet = dataSet;
dataProducers.clear();
+ conffileProducers.clear();
if (dataSet != null) {
Collections.addAll(dataProducers, dataSet);
+
+ for (Data item : dataSet) {
+ if (item.getConffile()) {
+ conffileProducers.add(item);
+ }
+ }
}
}
protected VariableResolver initializeVariableResolver( Map<String, String> variables ) {
- ((Map) variables).putAll(getProject().getProperties());
- ((Map) variables).putAll(System.getProperties());
+ @SuppressWarnings("unchecked")
+ final Map<String, String> projectProperties = Map.class.cast(getProject().getProperties());
+ @SuppressWarnings("unchecked")
+ final Map<String, String> systemProperties = Map.class.cast(System.getProperties());
+
+ variables.putAll(projectProperties);
+ variables.putAll(systemProperties);
variables.put("name", name != null ? name : getProject().getName());
variables.put("artifactId", getProject().getArtifactId());
variables.put("groupId", getProject().getGroupId());
@@ -296,7 +384,22 @@ public class DebMojo extends AbstractPluginMojo {
* @return the Maven project version
*/
private String getProjectVersion() {
- return Utils.convertToDebianVersion(getProject().getVersion(), this.timestamped ? session.getStartTime() : null);
+ return Utils.convertToDebianVersion(getProject().getVersion(), this.snapshotExpand, this.snapshotEnv, session.getStartTime());
+ }
+
+ /**
+ * @return whether the artifact is a POM or not
+ */
+ private boolean isPOM() {
+ String type = getProject().getArtifact().getType();
+ return "pom".equalsIgnoreCase(type);
+ }
+
+ /**
+ * @return whether the artifact is of configured type (i.e. the package to generate is the main artifact)
+ */
+ private boolean isType() {
+ return type.equals(getProject().getArtifact().getType());
}
/**
@@ -321,19 +424,31 @@ public class DebMojo extends AbstractPluginMojo {
*
* @throws MojoExecutionException on error
*/
- @Override
public void execute() throws MojoExecutionException {
final MavenProject project = getProject();
- if (isSubmodule() && !submodules) {
- getLog().info("skipping sub module: jdeb executing at top-level only");
+ if (skip) {
+ getLog().info("skipping as configured (skip)");
return;
}
+ if (skipPOMs && isPOM()) {
+ getLog().info("skipping because artifact is a pom (skipPOMs)");
+ return;
+ }
+
+ if (skipSubmodules && isSubmodule()) {
+ getLog().info("skipping submodule (skipSubmodules)");
+ return;
+ }
+
+
setData(dataSet);
- Console console = new MojoConsole(getLog(), verbose);
+ console = new MojoConsole(getLog(), verbose);
+
+ initializeSignProperties();
final VariableResolver resolver = initializeVariableResolver(new HashMap<String, String>());
@@ -343,32 +458,27 @@ public class DebMojo extends AbstractPluginMojo {
final File changesInFile = new File(Utils.replaceVariables(resolver, changesIn, openReplaceToken, closeReplaceToken));
final File changesOutFile = new File(Utils.replaceVariables(resolver, changesOut, openReplaceToken, closeReplaceToken));
final File changesSaveFile = new File(Utils.replaceVariables(resolver, changesSave, openReplaceToken, closeReplaceToken));
+ final File keyringFile = keyring == null ? null : new File(Utils.replaceVariables(resolver, keyring, openReplaceToken, closeReplaceToken));
// if there are no producers defined we try to use the artifacts
if (dataProducers.isEmpty()) {
- if (!hasMainArtifact()) {
-
- final String packaging = project.getPackaging();
- if ("pom".equalsIgnoreCase(packaging)) {
- getLog().warn("Creating empty debian package.");
- } else {
- throw new MojoExecutionException(
- "Nothing to include into the debian package. " +
- "Did you maybe forget to add a <data> tag or call the plugin directly?");
- }
-
- } else {
-
+ if (hasMainArtifact()) {
Set<Artifact> artifacts = new HashSet<Artifact>();
artifacts.add(project.getArtifact());
- for (Artifact artifact : (Set<Artifact>) project.getArtifacts()) {
+ @SuppressWarnings("unchecked")
+ final Set<Artifact> projectArtifacts = project.getArtifacts();
+
+ for (Artifact artifact : projectArtifacts) {
artifacts.add(artifact);
}
- for (Artifact artifact : (List<Artifact>) project.getAttachedArtifacts()) {
+ @SuppressWarnings("unchecked")
+ final List<Artifact> attachedArtifacts = project.getAttachedArtifacts();
+
+ for (Artifact artifact : attachedArtifacts) {
artifacts.add(artifact);
}
@@ -399,7 +509,7 @@ public class DebMojo extends AbstractPluginMojo {
}
try {
- DebMaker debMaker = new DebMaker(console, dataProducers);
+ DebMaker debMaker = new DebMaker(console, dataProducers, conffileProducers);
debMaker.setDeb(debFile);
debMaker.setControl(controlDirFile);
debMaker.setPackage(getProject().getArtifactId());
@@ -409,14 +519,26 @@ public class DebMojo extends AbstractPluginMojo {
debMaker.setChangesOut(changesOutFile);
debMaker.setChangesSave(changesSaveFile);
debMaker.setCompression(compression);
+ debMaker.setKeyring(keyringFile);
+ debMaker.setKey(key);
+ debMaker.setPassphrase(passphrase);
+ debMaker.setSignPackage(signPackage);
+ debMaker.setSignMethod(signMethod);
+ debMaker.setSignRole(signRole);
debMaker.setResolver(resolver);
+ debMaker.setOpenReplaceToken(openReplaceToken);
+ debMaker.setCloseReplaceToken(closeReplaceToken);
debMaker.validate();
debMaker.makeDeb();
// Always attach unless explicitly set to false
if ("true".equalsIgnoreCase(attach)) {
- getLog().info("Attaching created debian archive " + debFile);
- projectHelper.attachArtifact(project, type, classifier, debFile);
+ console.info("Attaching created debian package " + debFile);
+ if (!isType()) {
+ projectHelper.attachArtifact(project, type, classifier, debFile);
+ } else {
+ project.getArtifact().setFile(debFile);
+ }
}
} catch (PackagingException e) {
@@ -424,4 +546,126 @@ public class DebMojo extends AbstractPluginMojo {
throw new MojoExecutionException("Failed to create debian package " + debFile, e);
}
}
+
+ /**
+ * Initializes unspecified sign properties using available defaults
+ * and global settings.
+ */
+ private void initializeSignProperties() {
+ if (!signPackage) {
+ return;
+ }
+
+ if (key != null && keyring != null && passphrase != null) {
+ return;
+ }
+
+ Map<String, String> properties =
+ readPropertiesFromActiveProfiles(signCfgPrefix, KEY, KEYRING, PASSPHRASE);
+
+ key = lookupIfEmpty(key, properties, KEY);
+ keyring = lookupIfEmpty(keyring, properties, KEYRING);
+ passphrase = decrypt(lookupIfEmpty(passphrase, properties, PASSPHRASE));
+
+ if (keyring == null) {
+ try {
+ keyring = Utils.guessKeyRingFile().getAbsolutePath();
+ console.info("Located keyring at " + keyring);
+ } catch (FileNotFoundException e) {
+ console.warn(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Decrypts given passphrase if needed using maven security dispatcher.
+ * See http://maven.apache.org/guides/mini/guide-encryption.html for details.
+ *
+ * @param maybeEncryptedPassphrase possibly encrypted passphrase
+ * @return decrypted passphrase
+ */
+ private String decrypt( final String maybeEncryptedPassphrase ) {
+ if (maybeEncryptedPassphrase == null) {
+ return null;
+ }
+
+ try {
+ final String decrypted = secDispatcher.decrypt(maybeEncryptedPassphrase);
+ if (maybeEncryptedPassphrase.equals(decrypted)) {
+ console.info("Passphrase was not encrypted");
+ } else {
+ console.info("Passphrase was successfully decrypted");
+ }
+ return decrypted;
+ } catch (SecDispatcherException e) {
+ console.warn("Unable to decrypt passphrase: " + e.getMessage());
+ }
+
+ return maybeEncryptedPassphrase;
+ }
+
+ /**
+ *
+ * @return the maven project used by this mojo
+ */
+ private MavenProject getProject() {
+ if (project.getExecutionProject() != null) {
+ return project.getExecutionProject();
+ }
+
+ return project;
+ }
+
+
+
+ /**
+ * Read properties from the active profiles.
+ *
+ * Goes through all active profiles (in the order the
+ * profiles are defined in settings.xml) and extracts
+ * the desired properties (if present). The prefix is
+ * used when looking up properties in the profile but
+ * not in the returned map.
+ *
+ * @param prefix The prefix to use or null if no prefix should be used
+ * @param properties The properties to read
+ *
+ * @return A map containing the values for the properties that were found
+ */
+ public Map<String, String> readPropertiesFromActiveProfiles( final String prefix,
+ final String... properties ) {
+ if (settings == null) {
+ console.debug("No maven setting injected");
+ return Collections.emptyMap();
+ }
+
+ final List<String> activeProfilesList = settings.getActiveProfiles();
+ if (activeProfilesList.isEmpty()) {
+ console.debug("No active profiles found");
+ return Collections.emptyMap();
+ }
+
+ final Map<String, String> map = new HashMap<String, String>();
+ final Set<String> activeProfiles = new HashSet<String>(activeProfilesList);
+
+ // Iterate over all active profiles in order
+ for (final Profile profile : settings.getProfiles()) {
+ // Check if the profile is active
+ final String profileId = profile.getId();
+ if (activeProfiles.contains(profileId)) {
+ console.debug("Trying active profile " + profileId);
+ for (final String property : properties) {
+ final String propKey = prefix != null ? prefix + property : property;
+ final String value = profile.getProperties().getProperty(propKey);
+ if (value != null) {
+ console.debug("Found property " + property + " in profile " + profileId);
+ map.put(property, value);
+ }
+ }
+ }
+ }
+
+ return map;
+ }
+
}
diff --git a/src/main/java/org/vafer/jdeb/maven/Mapper.java b/src/main/java/org/vafer/jdeb/maven/Mapper.java
index d44a3d2..0e4cebe 100644
--- a/src/main/java/org/vafer/jdeb/maven/Mapper.java
+++ b/src/main/java/org/vafer/jdeb/maven/Mapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,12 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.vafer.jdeb.maven;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import org.apache.maven.plugins.annotations.Parameter;
import org.vafer.jdeb.mapping.LsMapper;
import org.vafer.jdeb.mapping.NullMapper;
import org.vafer.jdeb.mapping.PermMapper;
@@ -31,55 +33,34 @@ import org.vafer.jdeb.mapping.PermMapper;
*/
public final class Mapper {
- /**
- * @parameter
- * @required
- */
+ @Parameter(required = true)
private String type;
- /**
- * @parameter
- */
+ @Parameter
private int uid = -1;
- /**
- * @parameter
- */
+ @Parameter
private int gid = -1;
- /**
- * @parameter
- */
+ @Parameter
private String user;
- /**
- * @parameter
- */
+ @Parameter
private String group;
- /**
- * @parameter
- */
+ @Parameter
private String filemode;
- /**
- * @parameter
- */
+ @Parameter
private String dirmode;
- /**
- * @parameter
- */
+ @Parameter
private String prefix;
- /**
- * @parameter
- */
+ @Parameter
private int strip;
- /**
- * @parameter
- */
+ @Parameter
private File src;
diff --git a/src/main/java/org/vafer/jdeb/maven/MissingSourceBehavior.java b/src/main/java/org/vafer/jdeb/maven/MissingSourceBehavior.java
index 684e871..c988807 100644
--- a/src/main/java/org/vafer/jdeb/maven/MissingSourceBehavior.java
+++ b/src/main/java/org/vafer/jdeb/maven/MissingSourceBehavior.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.vafer.jdeb.maven;
public enum MissingSourceBehavior {
diff --git a/src/main/java/org/vafer/jdeb/maven/MojoConsole.java b/src/main/java/org/vafer/jdeb/maven/MojoConsole.java
index da78148..ca3b0f2 100644
--- a/src/main/java/org/vafer/jdeb/maven/MojoConsole.java
+++ b/src/main/java/org/vafer/jdeb/maven/MojoConsole.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,8 @@ import org.apache.maven.plugin.logging.Log;
import org.vafer.jdeb.Console;
/**
- * Console implementation for Maven plugins.
+ * Console implementation for Maven plugins. debug messages are only displayed
+ * when the <tt>verbose</tt> parameter is true.
*/
class MojoConsole implements Console {
@@ -32,13 +33,17 @@ class MojoConsole implements Console {
this.verbose = verbose;
}
- public void info(String s) {
+ public void debug(String message) {
if (verbose) {
- log.info(s);
+ log.info(message);
}
}
- public void warn(String s) {
- log.warn(s);
+ public void info(String message) {
+ log.info(message);
+ }
+
+ public void warn(String message) {
+ log.warn(message);
}
}
diff --git a/src/main/java/org/vafer/jdeb/producers/AbstractDataProducer.java b/src/main/java/org/vafer/jdeb/producers/AbstractDataProducer.java
index 47d8764..5396ec6 100644
--- a/src/main/java/org/vafer/jdeb/producers/AbstractDataProducer.java
+++ b/src/main/java/org/vafer/jdeb/producers/AbstractDataProducer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,9 +17,14 @@ package org.vafer.jdeb.producers;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.tools.ant.types.selectors.SelectorUtils;
+import org.vafer.jdeb.DataConsumer;
import org.vafer.jdeb.DataProducer;
import org.vafer.jdeb.mapping.Mapper;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
/**
* Base Producer class providing including/excluding.
*
@@ -67,6 +72,23 @@ public abstract class AbstractDataProducer implements DataProducer {
return false;
}
+ public void produceDir( final DataConsumer consumer,
+ final String dirname ) throws IOException {
+ TarArchiveEntry entry = Producers.defaultDirEntryWithName(dirname);
+ entry = map(entry);
+ entry.setSize(0);
+ Producers.produceDirEntry(consumer, entry);
+ }
+
+ public void produceFile( final DataConsumer consumer,
+ final File file,
+ final String entryName ) throws IOException {
+ TarArchiveEntry entry = Producers.defaultFileEntryWithName(entryName);
+ entry.setSize(file.length());
+ entry = map(entry);
+ Producers.produceInputStreamWithEntry(consumer, new FileInputStream(file), entry);
+ }
+
public TarArchiveEntry map( final TarArchiveEntry pEntry ) {
TarArchiveEntry entry = pEntry;
diff --git a/src/main/java/org/vafer/jdeb/producers/DataProducerArchive.java b/src/main/java/org/vafer/jdeb/producers/DataProducerArchive.java
index 8160759..ed3d8cb 100644
--- a/src/main/java/org/vafer/jdeb/producers/DataProducerArchive.java
+++ b/src/main/java/org/vafer/jdeb/producers/DataProducerArchive.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/main/java/org/vafer/jdeb/producers/DataProducerDirectory.java b/src/main/java/org/vafer/jdeb/producers/DataProducerDirectory.java
index 70eff71..8bece12 100644
--- a/src/main/java/org/vafer/jdeb/producers/DataProducerDirectory.java
+++ b/src/main/java/org/vafer/jdeb/producers/DataProducerDirectory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,30 +60,19 @@ public final class DataProducerDirectory extends AbstractDataProducer implements
continue;
}
- if (!isIncluded(dirname)) {
- continue;
- }
-
if ('/' != File.separatorChar) {
dirname = dirname.replace(File.separatorChar, '/');
}
+ if (!isIncluded(dirname)) {
+ continue;
+ }
+
if (!dirname.endsWith("/")) {
dirname += "/";
}
- TarArchiveEntry entry = new TarArchiveEntry(dirname, true);
- entry.setUserId(0);
- entry.setUserName("root");
- entry.setGroupId(0);
- entry.setGroupName("root");
- entry.setMode(TarArchiveEntry.DEFAULT_DIR_MODE);
-
- entry = map(entry);
-
- entry.setSize(0);
-
- pReceiver.onEachDir(entry.getName(), entry.getLinkName(), entry.getUserName(), entry.getUserId(), entry.getGroupName(), entry.getGroupId(), entry.getMode(), entry.getSize());
+ produceDir(pReceiver, dirname);
}
@@ -91,31 +80,15 @@ public final class DataProducerDirectory extends AbstractDataProducer implements
final File file = new File(baseDir, f);
String filename = getFilename(baseDir, file);
- if (!isIncluded(filename)) {
- continue;
- }
-
if ('/' != File.separatorChar) {
filename = filename.replace(File.separatorChar, '/');
}
- TarArchiveEntry entry = new TarArchiveEntry(filename, true);
- entry.setUserId(0);
- entry.setUserName("root");
- entry.setGroupId(0);
- entry.setGroupName("root");
- entry.setMode(TarArchiveEntry.DEFAULT_FILE_MODE);
-
- entry = map(entry);
-
- entry.setSize(file.length());
-
- final InputStream inputStream = new FileInputStream(file);
- try {
- pReceiver.onEachFile(inputStream, entry.getName(), entry.getLinkName(), entry.getUserName(), entry.getUserId(), entry.getGroupName(), entry.getGroupId(), entry.getMode(), entry.getSize());
- } finally {
- inputStream.close();
+ if (!isIncluded(filename)) {
+ continue;
}
+
+ produceFile(pReceiver, file, filename);
}
}
diff --git a/src/main/java/org/vafer/jdeb/producers/DataProducerFile.java b/src/main/java/org/vafer/jdeb/producers/DataProducerFile.java
index 17fb3bd..7bea326 100644
--- a/src/main/java/org/vafer/jdeb/producers/DataProducerFile.java
+++ b/src/main/java/org/vafer/jdeb/producers/DataProducerFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,24 +51,13 @@ public final class DataProducerFile extends AbstractDataProducer implements Data
fileName = file.getName();
}
- TarArchiveEntry entry = new TarArchiveEntry(fileName, true);
- entry.setUserId(0);
- entry.setUserName("root");
- entry.setGroupId(0);
- entry.setGroupName("root");
- entry.setMode(TarArchiveEntry.DEFAULT_FILE_MODE);
+ TarArchiveEntry entry = Producers.defaultFileEntryWithName(fileName);
entry = map(entry);
entry.setSize(file.length());
- final InputStream inputStream = new FileInputStream(file);
- try {
- pReceiver.onEachFile(inputStream, entry.getName(), entry.getLinkName(), entry.getUserName(), entry.getUserId(), entry.getGroupName(), entry.getGroupId(), entry.getMode(), entry.getSize());
- } finally {
- inputStream.close();
- }
-
+ Producers.produceInputStreamWithEntry(pReceiver, new FileInputStream(file), entry);
}
}
diff --git a/src/main/java/org/vafer/jdeb/producers/DataProducerFileSet.java b/src/main/java/org/vafer/jdeb/producers/DataProducerFileSet.java
index b4eaf4d..cb921c9 100644
--- a/src/main/java/org/vafer/jdeb/producers/DataProducerFileSet.java
+++ b/src/main/java/org/vafer/jdeb/producers/DataProducerFileSet.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,10 +42,10 @@ public final class DataProducerFileSet implements DataProducer {
}
public void produce( final DataConsumer pReceiver ) throws IOException {
- String user = "root";
- int uid = 0;
- String group = "root";
- int gid = 0;
+ String user = Producers.ROOT_NAME;
+ int uid = Producers.ROOT_UID;
+ String group = Producers.ROOT_NAME;
+ int gid = Producers.ROOT_UID;
int filemode = TarEntry.DEFAULT_FILE_MODE;
int dirmode = TarEntry.DEFAULT_DIR_MODE;
String prefix = "";
diff --git a/src/main/java/org/vafer/jdeb/producers/DataProducerFiles.java b/src/main/java/org/vafer/jdeb/producers/DataProducerFiles.java
new file mode 100644
index 0000000..cd89c7b
--- /dev/null
+++ b/src/main/java/org/vafer/jdeb/producers/DataProducerFiles.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb.producers;
+
+import org.vafer.jdeb.DataConsumer;
+import org.vafer.jdeb.mapping.Mapper;
+import org.vafer.jdeb.utils.Utils;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Data producer that places multiple files into a single
+ * destination directory.
+ *
+ * @author Roman Kashitsyn
+ */
+public class DataProducerFiles extends AbstractDataProducer {
+
+ private final String[] files;
+ private final String destDir;
+
+ public DataProducerFiles( final String[] files,
+ final String destDir,
+ final Mapper[] mappers ) {
+ super(null, null, mappers);
+ this.files = files;
+ this.destDir = destDir;
+ }
+
+ @Override
+ public void produce( DataConsumer receiver ) throws IOException {
+ boolean hasDestDir = !Utils.isNullOrEmpty(destDir);
+
+ for (String fileName : files) {
+ File f = new File(fileName);
+
+ if (hasDestDir) {
+ fileName = Utils.movePath(fileName, destDir);
+ }
+
+ produceFile(receiver, f, fileName);
+ }
+ }
+}
diff --git a/src/main/java/org/vafer/jdeb/producers/DataProducerLink.java b/src/main/java/org/vafer/jdeb/producers/DataProducerLink.java
index 69c851f..c5f5180 100644
--- a/src/main/java/org/vafer/jdeb/producers/DataProducerLink.java
+++ b/src/main/java/org/vafer/jdeb/producers/DataProducerLink.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,15 +41,14 @@ public final class DataProducerLink extends AbstractDataProducer implements Data
this.linkName = linkName;
}
- @Override
public void produce( final DataConsumer pReceiver ) throws IOException {
TarArchiveEntry entry = new TarArchiveEntry(path, symlink ? TarArchiveEntry.LF_SYMLINK : TarArchiveEntry.LF_LINK);
entry.setLinkName(linkName);
- entry.setUserId(0);
- entry.setUserName("root");
- entry.setGroupId(0);
- entry.setGroupName("root");
+ entry.setUserId(Producers.ROOT_UID);
+ entry.setUserName(Producers.ROOT_NAME);
+ entry.setGroupId(Producers.ROOT_UID);
+ entry.setGroupName(Producers.ROOT_NAME);
entry.setMode(TarArchiveEntry.DEFAULT_FILE_MODE);
entry = map(entry);
diff --git a/src/main/java/org/vafer/jdeb/producers/DataProducerPathTemplate.java b/src/main/java/org/vafer/jdeb/producers/DataProducerPathTemplate.java
index bd6cfd0..b38343b 100644
--- a/src/main/java/org/vafer/jdeb/producers/DataProducerPathTemplate.java
+++ b/src/main/java/org/vafer/jdeb/producers/DataProducerPathTemplate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,18 +33,7 @@ public class DataProducerPathTemplate extends AbstractDataProducer implements Da
public void produce( DataConsumer pReceiver ) throws IOException {
for (String literalPath : literalPaths) {
- TarArchiveEntry entry = new TarArchiveEntry(literalPath, true);
- entry.setUserId(0);
- entry.setUserName("root");
- entry.setGroupId(0);
- entry.setGroupName("root");
- entry.setMode(TarArchiveEntry.DEFAULT_DIR_MODE);
-
- entry = map(entry);
-
- entry.setSize(0);
-
- pReceiver.onEachDir(entry.getName(), entry.getLinkName(), entry.getUserName(), entry.getUserId(), entry.getGroupName(), entry.getGroupId(), entry.getMode(), entry.getSize());
+ produceDir(pReceiver, literalPath);
}
}
diff --git a/src/main/java/org/vafer/jdeb/producers/Producers.java b/src/main/java/org/vafer/jdeb/producers/Producers.java
new file mode 100644
index 0000000..bc1d4f0
--- /dev/null
+++ b/src/main/java/org/vafer/jdeb/producers/Producers.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb.producers;
+
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+
+import org.apache.commons.io.IOUtils;
+import org.vafer.jdeb.DataConsumer;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Package-private utility class with common producers functionality.
+ *
+ * @author Roman Kashitsyn <roman.kashitsyn at gmail.com>
+ */
+class Producers {
+
+ final static int ROOT_UID = 0;
+ final static String ROOT_NAME = "root";
+
+ private Producers() {}
+
+
+ /**
+ * Creates a tar file entry with defaults parameters.
+ * @param entryName the entry name
+ * @return file entry with reasonable defaults
+ */
+ static TarArchiveEntry defaultFileEntryWithName( final String entryName ) {
+ TarArchiveEntry entry = new TarArchiveEntry(entryName, true);
+ entry.setUserId(ROOT_UID);
+ entry.setUserName(ROOT_NAME);
+ entry.setGroupId(ROOT_UID);
+ entry.setGroupName(ROOT_NAME);
+ entry.setMode(TarArchiveEntry.DEFAULT_FILE_MODE);
+ return entry;
+ }
+
+ /**
+ * Creates a tar directory entry with defaults parameters.
+ * @param dirName the directory name
+ * @return dir entry with reasonable defaults
+ */
+ static TarArchiveEntry defaultDirEntryWithName( final String dirName ) {
+ TarArchiveEntry entry = new TarArchiveEntry(dirName, true);
+ entry.setUserId(ROOT_UID);
+ entry.setUserName(ROOT_NAME);
+ entry.setGroupId(ROOT_UID);
+ entry.setGroupName(ROOT_NAME);
+ entry.setMode(TarArchiveEntry.DEFAULT_DIR_MODE);
+ return entry;
+ }
+
+ /**
+ * Forwards tar archive entry entry to a consumer.
+ * @param consumer the consumer
+ * @param entry the entry to pass
+ * @throws IOException
+ */
+ static void produceDirEntry( final DataConsumer consumer,
+ final TarArchiveEntry entry ) throws IOException {
+ consumer.onEachDir(
+ entry.getName(),
+ entry.getLinkName(),
+ entry.getUserName(),
+ entry.getUserId(),
+ entry.getGroupName(),
+ entry.getGroupId(),
+ entry.getMode(),
+ entry.getSize()
+ );
+ }
+
+
+ /**
+ * Feeds input stream to data consumer using metadata from tar entry.
+ * @param consumer the consumer
+ * @param inputStream the stream to feed
+ * @param entry the entry to use for metadata
+ * @throws IOException on consume error
+ */
+ static void produceInputStreamWithEntry( final DataConsumer consumer,
+ final InputStream inputStream,
+ final TarArchiveEntry entry ) throws IOException {
+ try {
+ consumer.onEachFile(inputStream,
+ entry.getName(),
+ entry.getLinkName(),
+ entry.getUserName(),
+ entry.getUserId(),
+ entry.getGroupName(),
+ entry.getGroupId(),
+ entry.getMode(),
+ entry.getSize()
+ );
+ } finally {
+ IOUtils.closeQuietly(inputStream);
+ }
+ }
+
+}
diff --git a/src/main/java/org/vafer/jdeb/signing/PGPSigner.java b/src/main/java/org/vafer/jdeb/signing/PGPSigner.java
index b2af9e5..83a6aed 100644
--- a/src/main/java/org/vafer/jdeb/signing/PGPSigner.java
+++ b/src/main/java/org/vafer/jdeb/signing/PGPSigner.java
@@ -1,152 +1,176 @@
-/*
- * Copyright 2013 The jdeb developers.
- *
- * 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 org.vafer.jdeb.signing;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.nio.charset.Charset;
-import java.security.GeneralSecurityException;
-import java.util.Iterator;
-
-import org.bouncycastle.bcpg.ArmoredOutputStream;
-import org.bouncycastle.bcpg.BCPGOutputStream;
-import org.bouncycastle.openpgp.PGPException;
-import org.bouncycastle.openpgp.PGPPrivateKey;
-import org.bouncycastle.openpgp.PGPSecretKey;
-import org.bouncycastle.openpgp.PGPSecretKeyRing;
-import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
-import org.bouncycastle.openpgp.PGPSignature;
-import org.bouncycastle.openpgp.PGPSignatureGenerator;
-import org.bouncycastle.openpgp.PGPUtil;
-import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder;
-import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder;
-import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
-
-/**
- * Signing with OpenPGP.
- *
- * @author Torsten Curdt
- * @author Emmanuel Bourg
- */
-public class PGPSigner {
-
- private static final byte[] EOL = "\r\n".getBytes(Charset.forName("UTF-8"));
-
- private PGPPrivateKey privateKey;
-
- public PGPSigner(InputStream keyring, String keyId, String passphrase) throws IOException, PGPException {
- PGPSecretKey secretKey = getSecretKey(keyring, keyId);
- privateKey = secretKey.extractPrivateKey(new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(passphrase.toCharArray()));
- }
-
- /**
- * Creates a clear sign signature over the input data. (Not detached)
- *
- * @param input the content to be signed
- * @param output the output destination of the signature
- */
- public void clearSign(String input, OutputStream output) throws IOException, PGPException, GeneralSecurityException {
- clearSign(new ByteArrayInputStream(input.getBytes("UTF-8")), output);
- }
-
- /**
- * Creates a clear sign signature over the input data. (Not detached)
- *
- * @param input the content to be signed
- * @param output the output destination of the signature
- */
- public void clearSign(InputStream input, OutputStream output) throws IOException, PGPException, GeneralSecurityException {
- int digest = PGPUtil.SHA1;
-
- PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(new BcPGPContentSignerBuilder(privateKey.getPublicKeyPacket().getAlgorithm(), digest));
- signatureGenerator.init(PGPSignature.CANONICAL_TEXT_DOCUMENT, privateKey);
-
- ArmoredOutputStream armoredOutput = new ArmoredOutputStream(output);
- armoredOutput.beginClearText(digest);
-
- BufferedReader reader = new BufferedReader(new InputStreamReader(input));
-
- String line;
- while ((line = reader.readLine()) != null) {
- // trailing spaces must be removed for signature calculation (see http://tools.ietf.org/html/rfc4880#section-7.1)
- byte[] data = trim(line).getBytes("UTF-8");
-
- armoredOutput.write(data);
- armoredOutput.write(EOL);
-
- signatureGenerator.update(data);
- signatureGenerator.update(EOL);
- }
-
- armoredOutput.endClearText();
-
- PGPSignature signature = signatureGenerator.generate();
- signature.encode(new BCPGOutputStream(armoredOutput));
-
- armoredOutput.close();
- }
-
- /**
- * Returns the secret key matching the specified identifier.
- *
- * @param input the input stream containing the keyring collection
- * @param keyId the 4 bytes identifier of the key
- */
- private PGPSecretKey getSecretKey(InputStream input, String keyId) throws IOException, PGPException {
- PGPSecretKeyRingCollection keyrings = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(input));
-
- Iterator rIt = keyrings.getKeyRings();
-
- while (rIt.hasNext()) {
- PGPSecretKeyRing kRing = (PGPSecretKeyRing) rIt.next();
- Iterator kIt = kRing.getSecretKeys();
-
- while (kIt.hasNext()) {
- PGPSecretKey key = (PGPSecretKey) kIt.next();
-
- if (key.isSigningKey() && Long.toHexString(key.getKeyID() & 0xFFFFFFFFL).equals(keyId.toLowerCase())) {
- return key;
- }
- }
- }
-
- return null;
- }
-
- /**
- * Trim the trailing spaces.
- *
- * @param line
- */
- private String trim(String line) {
- char[] chars = line.toCharArray();
- int len = chars.length;
-
- while (len > 0) {
- if (!Character.isWhitespace(chars[len - 1])) {
- break;
- }
- len--;
- }
-
- return line.substring(0, len);
- }
-}
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb.signing;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.security.GeneralSecurityException;
+import java.util.Iterator;
+
+import org.apache.commons.io.LineIterator;
+import org.bouncycastle.bcpg.ArmoredOutputStream;
+import org.bouncycastle.bcpg.BCPGOutputStream;
+import org.bouncycastle.openpgp.PGPException;
+import org.bouncycastle.openpgp.PGPPrivateKey;
+import org.bouncycastle.openpgp.PGPSecretKey;
+import org.bouncycastle.openpgp.PGPSecretKeyRing;
+import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
+import org.bouncycastle.openpgp.PGPSignature;
+import org.bouncycastle.openpgp.PGPSignatureGenerator;
+import org.bouncycastle.openpgp.PGPUtil;
+import org.bouncycastle.openpgp.operator.bc.BcPBESecretKeyDecryptorBuilder;
+import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder;
+import org.bouncycastle.openpgp.operator.bc.BcPGPDigestCalculatorProvider;
+
+/**
+ * Signing with OpenPGP.
+ *
+ * @author Torsten Curdt
+ * @author Emmanuel Bourg
+ */
+public class PGPSigner {
+
+ private static final byte[] EOL = "\n".getBytes(Charset.forName("UTF-8"));
+
+ private PGPSecretKey secretKey;
+ private PGPPrivateKey privateKey;
+
+ public PGPSigner(InputStream keyring, String keyId, String passphrase) throws IOException, PGPException {
+ secretKey = getSecretKey(keyring, keyId);
+ if(secretKey == null)
+ {
+ throw new PGPException(String.format("Specified key %s does not exist in key ring %s", keyId, keyring));
+ }
+ privateKey = secretKey.extractPrivateKey(new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(passphrase.toCharArray()));
+ }
+
+ /**
+ * Creates a clear sign signature over the input data. (Not detached)
+ *
+ * @param input the content to be signed
+ * @param output the output destination of the signature
+ */
+ public void clearSign(String input, OutputStream output) throws IOException, PGPException, GeneralSecurityException {
+ clearSign(new ByteArrayInputStream(input.getBytes("UTF-8")), output);
+ }
+
+ /**
+ * Creates a clear sign signature over the input data. (Not detached)
+ *
+ * @param input the content to be signed
+ * @param output the output destination of the signature
+ */
+ public void clearSign(InputStream input, OutputStream output) throws IOException, PGPException, GeneralSecurityException {
+ int digest = PGPUtil.SHA1;
+
+ PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(new BcPGPContentSignerBuilder(privateKey.getPublicKeyPacket().getAlgorithm(), digest));
+ signatureGenerator.init(PGPSignature.CANONICAL_TEXT_DOCUMENT, privateKey);
+
+ ArmoredOutputStream armoredOutput = new ArmoredOutputStream(output);
+ armoredOutput.beginClearText(digest);
+
+ LineIterator iterator = new LineIterator(new InputStreamReader(input));
+
+ while (iterator.hasNext()) {
+ String line = iterator.nextLine();
+
+ // trailing spaces must be removed for signature calculation (see http://tools.ietf.org/html/rfc4880#section-7.1)
+ byte[] data = trim(line).getBytes("UTF-8");
+
+ armoredOutput.write(data);
+ armoredOutput.write(EOL);
+
+ signatureGenerator.update(data);
+ if (iterator.hasNext()) {
+ signatureGenerator.update(EOL);
+ }
+ }
+
+ armoredOutput.endClearText();
+
+ PGPSignature signature = signatureGenerator.generate();
+ signature.encode(new BCPGOutputStream(armoredOutput));
+
+ armoredOutput.close();
+ }
+
+ /**
+ * Returns the secret key.
+ */
+ public PGPSecretKey getSecretKey()
+ {
+ return secretKey;
+ }
+
+ /**
+ * Returns the private key.
+ */
+ public PGPPrivateKey getPrivateKey()
+ {
+ return privateKey;
+ }
+
+ /**
+ * Returns the secret key matching the specified identifier.
+ *
+ * @param input the input stream containing the keyring collection
+ * @param keyId the 4 bytes identifier of the key
+ */
+ private PGPSecretKey getSecretKey(InputStream input, String keyId) throws IOException, PGPException {
+ PGPSecretKeyRingCollection keyrings = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(input));
+
+ Iterator rIt = keyrings.getKeyRings();
+
+ while (rIt.hasNext()) {
+ PGPSecretKeyRing kRing = (PGPSecretKeyRing) rIt.next();
+ Iterator kIt = kRing.getSecretKeys();
+
+ while (kIt.hasNext()) {
+ PGPSecretKey key = (PGPSecretKey) kIt.next();
+
+ if (key.isSigningKey() && Long.toHexString(key.getKeyID() & 0xFFFFFFFFL).equals(keyId.toLowerCase())) {
+ return key;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Trim the trailing spaces.
+ *
+ * @param line
+ */
+ private String trim(String line) {
+ char[] chars = line.toCharArray();
+ int len = chars.length;
+
+ while (len > 0) {
+ if (!Character.isWhitespace(chars[len - 1])) {
+ break;
+ }
+ len--;
+ }
+
+ return line.substring(0, len);
+ }
+}
diff --git a/src/main/java/org/vafer/jdeb/utils/FilteredFile.java b/src/main/java/org/vafer/jdeb/utils/FilteredFile.java
index c6f2beb..665e546 100644
--- a/src/main/java/org/vafer/jdeb/utils/FilteredFile.java
+++ b/src/main/java/org/vafer/jdeb/utils/FilteredFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,19 +25,19 @@ import java.util.List;
public class FilteredFile {
- private static String openToken = "[[";
- private static String closeToken = "]]";
+ private String openToken = "[[";
+ private String closeToken = "]]";
private List<String> lines = new ArrayList<String>();
public FilteredFile(InputStream in, VariableResolver resolver) throws IOException {
parse(in, resolver);
}
- public static void setOpenToken(String token) {
+ public void setOpenToken(String token) {
openToken = token;
}
- public static void setCloseToken(String token) {
+ public void setCloseToken(String token) {
closeToken = token;
}
diff --git a/src/main/java/org/vafer/jdeb/utils/InformationInputStream.java b/src/main/java/org/vafer/jdeb/utils/InformationInputStream.java
index 7907176..ac653ac 100644
--- a/src/main/java/org/vafer/jdeb/utils/InformationInputStream.java
+++ b/src/main/java/org/vafer/jdeb/utils/InformationInputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/main/java/org/vafer/jdeb/utils/InformationOutputStream.java b/src/main/java/org/vafer/jdeb/utils/InformationOutputStream.java
index 63f11c4..1db72ee 100644
--- a/src/main/java/org/vafer/jdeb/utils/InformationOutputStream.java
+++ b/src/main/java/org/vafer/jdeb/utils/InformationOutputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/main/java/org/vafer/jdeb/utils/MapVariableResolver.java b/src/main/java/org/vafer/jdeb/utils/MapVariableResolver.java
index de50343..deb6d72 100644
--- a/src/main/java/org/vafer/jdeb/utils/MapVariableResolver.java
+++ b/src/main/java/org/vafer/jdeb/utils/MapVariableResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/main/java/org/vafer/jdeb/utils/PGPSignatureOutputStream.java b/src/main/java/org/vafer/jdeb/utils/PGPSignatureOutputStream.java
new file mode 100644
index 0000000..854408d
--- /dev/null
+++ b/src/main/java/org/vafer/jdeb/utils/PGPSignatureOutputStream.java
@@ -0,0 +1,57 @@
+package org.vafer.jdeb.utils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.bouncycastle.bcpg.ArmoredOutputStream;
+import org.bouncycastle.openpgp.PGPException;
+import org.bouncycastle.openpgp.PGPSignature;
+import org.bouncycastle.openpgp.PGPSignatureGenerator;
+
+/**
+ * An output stream that calculates the signature of the input data as it
+ * is written
+ *
+ * @author mpoindexter
+ *
+ */
+public class PGPSignatureOutputStream extends OutputStream {
+ private final PGPSignatureGenerator signatureGenerator;
+
+ public PGPSignatureOutputStream( PGPSignatureGenerator signatureGenerator ) {
+ super();
+ this.signatureGenerator = signatureGenerator;
+ }
+
+ public void write( int b ) throws IOException {
+ signatureGenerator.update(new byte[] { (byte)b });
+ }
+
+ public void write( byte[] b ) throws IOException {
+ signatureGenerator.update(b);
+ }
+
+ public void write( byte[] b, int off, int len ) throws IOException {
+ signatureGenerator.update(b, off, len);
+ }
+
+ public PGPSignature generateSignature() throws PGPException {
+ return signatureGenerator.generate();
+ }
+
+ public String generateASCIISignature() throws PGPException {
+ try {
+ PGPSignature signature = generateSignature();
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ ArmoredOutputStream armorStream = new ArmoredOutputStream(buffer);
+ signature.encode(armorStream);
+ armorStream.close();
+ return new String(buffer.toByteArray());
+ } catch(IOException e) {
+ //Should never happen since we are just using a memory buffer
+ throw new RuntimeException(e);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/org/vafer/jdeb/utils/Utils.java b/src/main/java/org/vafer/jdeb/utils/Utils.java
index b078f22..987d5fa 100644
--- a/src/main/java/org/vafer/jdeb/utils/Utils.java
+++ b/src/main/java/org/vafer/jdeb/utils/Utils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,12 +16,20 @@
package org.vafer.jdeb.utils;
import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
-import java.util.Date;
import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.apache.tools.ant.filters.FixCrLfFilter;
import org.apache.tools.ant.util.ReaderInputStream;
@@ -34,6 +42,9 @@ import org.apache.tools.ant.util.ReaderInputStream;
* @author Torsten Curdt <tcurdt at vafer.org>
*/
public final class Utils {
+ private static final Pattern BETA_PATTERN = Pattern.compile("(.*?)([\\.\\-_]?)(alpha|a|beta|b|milestone|m|cr|rc)(.*)", Pattern.CASE_INSENSITIVE);
+
+ private static final Pattern SNAPSHOT_PATTERN = Pattern.compile("(.*)[\\-\\+]SNAPSHOT");
public static int copy( final InputStream pInput, final OutputStream pOutput ) throws IOException {
final byte[] buffer = new byte[2048];
@@ -87,7 +98,6 @@ public final class Utils {
return s;
}
-
/**
* Substitute the variables in the given expression with the
* values from the resolver
@@ -101,49 +111,71 @@ public final class Utils {
final StringBuilder out = new StringBuilder();
StringBuilder sb = new StringBuilder();
- char[] watch = open;
- int w = 0;
+ char[] last = null;
+ int wo = 0;
+ int wc = 0;
+ int level = 0;
for (char c : pExpression.toCharArray()) {
- if (c == watch[w]) {
- w++;
- if (watch.length == w) {
- // found the full token to watch for
-
- if (watch == open) {
- // found open
- out.append(sb);
- sb = new StringBuilder();
- // search for close
- watch = close;
- } else {
- // found close
+ if (c == open[wo]) {
+ wo++;
+ if (open.length == wo) {
+ // found open
+ if (last == open) {
+ out.append(open);
+ }
+ level++;
+ out.append(sb);
+ sb = new StringBuilder();
+ wo = 0;
+ last = open;
+ }
+ } else if (c == close[wc]) {
+ wc++;
+ if (close.length == wc) {
+ // found close
+ if (last == open) {
final String variable = pResolver.get(sb.toString());
if (variable != null) {
out.append(variable);
} else {
- out.append(pOpen);
+ out.append(open);
out.append(sb);
- out.append(pClose);
+ out.append(close);
}
- sb = new StringBuilder();
- // search for open
- watch = open;
+ } else {
+ out.append(sb);
+ out.append(close);
}
- w = 0;
+ sb = new StringBuilder();
+ level--;
+ wc = 0;
+ last = close;
}
} else {
- if (w > 0) {
- sb.append(watch, 0, w);
+ if (wo > 0) {
+ sb.append(open, 0, wo);
+ }
+
+ if (wc > 0) {
+ sb.append(close, 0, wc);
}
sb.append(c);
- w = 0;
+ wo = wc = 0;
}
}
- if (watch == close) {
+ if (wo > 0) {
+ sb.append(open, 0, wo);
+ }
+
+ if (wc > 0) {
+ sb.append(close, 0, wc);
+ }
+
+ if (level > 0) {
out.append(open);
}
out.append(sb);
@@ -168,20 +200,179 @@ public final class Utils {
}
/**
- * convert to debian version format
+ * Convert the project version to a version suitable for a Debian package.
+ * -SNAPSHOT suffixes are replaced with a timestamp (~yyyyMMddHHmmss).
+ * The separator before a rc, alpha or beta version is replaced with '~'
+ * such that the version is always ordered before the final or GA release.
+ *
+ * @param version the project version to convert to a Debian package version
+ * @param timestamp the date used as the timestamp to replace the SNAPSHOT suffix
*/
- public static String convertToDebianVersion( String version, Date timestamp ) {
- version = version.replace('-', '+');
- if (version.endsWith("+SNAPSHOT")) {
- version = version.substring(0, version.length() - "+SNAPSHOT".length());
- version += "~";
+ public static String convertToDebianVersion( String version, boolean apply, String envName, Date timestamp ) {
+ Matcher matcher = SNAPSHOT_PATTERN.matcher(version);
+ if (matcher.matches()) {
+ version = matcher.group(1) + "~";
- if (timestamp != null) {
- version += new SimpleDateFormat("yyyyMMddHHmmss").format(timestamp);
+ if (apply) {
+ final String envValue = System.getenv(envName);
+ final String snapshot = (envValue != null && envValue.length() > 0)
+ ? envValue
+ : new SimpleDateFormat("yyyyMMddHHmmss").format(timestamp);
+ version += snapshot;
} else {
version += "SNAPSHOT";
}
+ } else {
+ matcher = BETA_PATTERN.matcher(version);
+ if (matcher.matches()) {
+ version = matcher.group(1) + "~" + matcher.group(3) + matcher.group(4);
+ }
}
+
+ version = version.replace('-', '+');
+
return version;
}
+
+ /**
+ * Construct new path by replacing file directory part. No
+ * files are actually modified.
+ * @param file path to move
+ * @param target new path directory
+ */
+ public static String movePath( final String file,
+ final String target ) {
+ final String name = new File(file).getName();
+ return target.endsWith("/") ? target + name : target + '/' + name;
+ }
+
+ /**
+ * Extracts value from map if given value is null.
+ * @param value current value
+ * @param props properties to extract value from
+ * @param key property name to extract
+ * @return initial value or value extracted from map
+ */
+ public static String lookupIfEmpty( final String value,
+ final Map<String, String> props,
+ final String key ) {
+ return value != null ? value : props.get(key);
+ }
+
+ /**
+ * Get the known locations where the secure keyring can be located.
+ * Looks through known locations of the GNU PG secure keyring.
+ *
+ * @return The location of the PGP secure keyring if it was found,
+ * null otherwise
+ */
+ public static Collection<String> getKnownPGPSecureRingLocations() {
+ final LinkedHashSet<String> locations = new LinkedHashSet<String>();
+
+ final String os = System.getProperty("os.name");
+ final boolean runOnWindows = os == null || os.toLowerCase().contains("win");
+
+ if (runOnWindows) {
+ // The user's roaming profile on Windows, via environment
+ final String windowsRoaming = System.getenv("APPDATA");
+ if (windowsRoaming != null) {
+ locations.add(joinPaths(windowsRoaming, "gnupg", "secring.gpg"));
+ }
+
+ // The user's local profile on Windows, via environment
+ final String windowsLocal = System.getenv("LOCALAPPDATA");
+ if (windowsLocal != null) {
+ locations.add(joinPaths(windowsLocal, "gnupg", "secring.gpg"));
+ }
+
+ // The Windows installation directory
+ final String windir = System.getProperty("WINDIR");
+ if (windir != null) {
+ // Local Profile on Windows 98 and ME
+ locations.add(joinPaths(windir, "Application Data", "gnupg", "secring.gpg"));
+ }
+ }
+
+ final String home = System.getProperty("user.home");
+
+ if (home != null && runOnWindows) {
+ // These are for various flavours of Windows
+ // if the environment variables above have failed
+
+ // Roaming profile on Vista and later
+ locations.add(joinPaths(home, "AppData", "Roaming", "gnupg", "secring.gpg"));
+ // Local profile on Vista and later
+ locations.add(joinPaths(home, "AppData", "Local", "gnupg", "secring.gpg"));
+ // Roaming profile on 2000 and XP
+ locations.add(joinPaths(home, "Application Data", "gnupg", "secring.gpg"));
+ // Local profile on 2000 and XP
+ locations.add(joinPaths(home, "Local Settings", "Application Data", "gnupg", "secring.gpg"));
+ }
+
+ // *nix, including OS X
+ if (home != null) {
+ locations.add(joinPaths(home, ".gnupg", "secring.gpg"));
+ }
+
+ return locations;
+ }
+
+ /**
+ * Tries to guess location of the user secure keyring using various
+ * heuristics.
+ *
+ * @return path to the keyring file
+ * @throws FileNotFoundException if no keyring file found
+ */
+ public static File guessKeyRingFile() throws FileNotFoundException {
+ final Collection<String> possibleLocations = getKnownPGPSecureRingLocations();
+ for (final String location : possibleLocations) {
+ final File candidate = new File(location);
+ if (candidate.exists()) {
+ return candidate;
+ }
+ }
+ final StringBuilder message = new StringBuilder("Could not locate secure keyring, locations tried: ");
+ final Iterator<String> it = possibleLocations.iterator();
+ while (it.hasNext()) {
+ message.append(it.next());
+ if (it.hasNext()) {
+ message.append(", ");
+ }
+ }
+ throw new FileNotFoundException(message.toString());
+ }
+
+ /**
+ * Join together path elements with File.separator. Filters out null
+ * elements.
+ *
+ * @param elements The path elements to join
+ * @return elements concatenated together with File.separator
+ */
+ public static String joinPaths(String... elements) {
+ StringBuilder builder = new StringBuilder();
+ boolean first = true;
+ for (String element : elements) {
+ // Skip null elements
+ if (element == null) {
+ // This won't change the value of first if we skip elements
+ // in the beginning of the array
+ continue;
+ }
+ if (!first) {
+ builder.append(File.separatorChar);
+ }
+ builder.append(element);
+ first = false;
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Returns true if string is null or empty.
+ */
+ public static boolean isNullOrEmpty(final String str) {
+ return str == null || str.length() == 0;
+ }
}
diff --git a/src/main/java/org/vafer/jdeb/utils/VariableResolver.java b/src/main/java/org/vafer/jdeb/utils/VariableResolver.java
index 9e71ce8..4c05e66 100644
--- a/src/main/java/org/vafer/jdeb/utils/VariableResolver.java
+++ b/src/main/java/org/vafer/jdeb/utils/VariableResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/main/resources/META-INF/plexus/components.xml b/src/main/resources/META-INF/plexus/components.xml
new file mode 100644
index 0000000..7222b9c
--- /dev/null
+++ b/src/main/resources/META-INF/plexus/components.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+
+<component-set>
+ <components>
+ <component>
+ <role>org.sonatype.plexus.components.sec.dispatcher.SecDispatcher</role>
+ <role-hint>jdeb-sec</role-hint>
+ <implementation>org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher</implementation>
+ <requirements>
+ <requirement>
+ <role>org.sonatype.plexus.components.cipher.PlexusCipher</role>
+ <field-name>_cipher</field-name>
+ </requirement>
+ </requirements>
+ <configuration>
+ <_configuration-file>~/.m2/settings-security.xml</_configuration-file>
+ </configuration>
+ </component>
+ <component>
+ <role>org.sonatype.plexus.components.cipher.PlexusCipher</role>
+ <role-hint>jdeb-sec</role-hint>
+ <implementation>org.sonatype.plexus.components.cipher.DefaultPlexusCipher</implementation>
+ </component>
+
+ <!-- deb packaging extension -->
+ <component>
+ <role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
+ <role-hint>deb</role-hint>
+ <implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
+ <configuration>
+ <phases>
+ <process-resources>org.apache.maven.plugins:maven-resources-plugin:resources</process-resources>
+ <package>org.vafer:jdeb:jdeb</package>
+ <install>org.apache.maven.plugins:maven-install-plugin:install</install>
+ <deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
+ </phases>
+ </configuration>
+ </component>
+ <component>
+ <role>org.apache.maven.artifact.handler.ArtifactHandler</role>
+ <role-hint>deb</role-hint>
+ <implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation>
+ <configuration>
+ <type>deb</type>
+ <extension>deb</extension>
+ <packaging>deb</packaging>
+ </configuration>
+ </component>
+ </components>
+</component-set>
\ No newline at end of file
diff --git a/src/test/java/org/vafer/jdeb/ArchiveVisitor.java b/src/test/java/org/vafer/jdeb/ArchiveVisitor.java
index 5c3ebc1..3eb7414 100644
--- a/src/test/java/org/vafer/jdeb/ArchiveVisitor.java
+++ b/src/test/java/org/vafer/jdeb/ArchiveVisitor.java
@@ -1,31 +1,31 @@
-/*
- * Copyright 2013 Emmanuel Bourg
- *
- * 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 org.vafer.jdeb;
-
-import java.io.IOException;
-
-import org.apache.commons.compress.archivers.ArchiveEntry;
-
-/**
- * Callback used for inspecting an archive.
- *
- * @author Emmanuel Bourg
- */
-public interface ArchiveVisitor<E extends ArchiveEntry> {
-
- void visit(E entry, byte[] content) throws IOException;
-}
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb;
+
+import java.io.IOException;
+
+import org.apache.commons.compress.archivers.ArchiveEntry;
+
+/**
+ * Callback used for inspecting an archive.
+ *
+ * @author Emmanuel Bourg
+ */
+public interface ArchiveVisitor<E extends ArchiveEntry> {
+
+ void visit(E entry, byte[] content) throws IOException;
+}
diff --git a/src/test/java/org/vafer/jdeb/ArchiveWalker.java b/src/test/java/org/vafer/jdeb/ArchiveWalker.java
index 4fa02ee..2feb423 100644
--- a/src/test/java/org/vafer/jdeb/ArchiveWalker.java
+++ b/src/test/java/org/vafer/jdeb/ArchiveWalker.java
@@ -1,96 +1,113 @@
-/*
- * Copyright 2013 Emmanuel Bourg
- *
- * 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 org.vafer.jdeb;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.zip.GZIPInputStream;
-
-import org.apache.commons.compress.archivers.ArchiveEntry;
-import org.apache.commons.compress.archivers.ArchiveInputStream;
-import org.apache.commons.compress.archivers.ar.ArArchiveEntry;
-import org.apache.commons.compress.archivers.ar.ArArchiveInputStream;
-import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
-import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
-import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
-import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
-
-/**
- * Support class for inspecting the content of an archive.
- *
- * @author Emmanuel Bourg
- */
-public class ArchiveWalker {
-
- public static void walk(ArchiveInputStream in, ArchiveVisitor visitor) throws IOException {
- try {
- ArchiveEntry entry;
- while ((entry = in.getNextEntry()) != null) {
- byte[] content = new byte[(int) entry.getSize()];
- if (entry.getSize() > 0) {
- int length = in.read(content);
- if (length != entry.getSize()) {
- throw new IOException("Couldn't read entry " + entry.getName() + " : read " + length + ", expected " + entry.getSize());
- }
- }
-
- visitor.visit(entry, content);
- }
- } finally {
- in.close();
- }
- }
-
- public static boolean walkControl(File deb, final ArchiveVisitor<TarArchiveEntry> visitor) throws IOException {
- return walkEmbedded(deb, "control.tar", visitor, Compression.GZIP);
- }
-
- public static boolean walkData(File deb, final ArchiveVisitor<TarArchiveEntry> visitor, final Compression compression) throws IOException {
- return walkEmbedded(deb, "data.tar", visitor, compression);
- }
-
- public static boolean walkEmbedded(File deb, final String name, final ArchiveVisitor<TarArchiveEntry> visitor, final Compression compression) throws IOException {
- final AtomicBoolean found = new AtomicBoolean(false);
- ArArchiveInputStream in = new ArArchiveInputStream(new FileInputStream(deb));
- ArchiveWalker.walk(in, new ArchiveVisitor<ArArchiveEntry>() {
- public void visit(ArArchiveEntry entry, byte[] content) throws IOException {
- if (entry.getName().equals(name + compression.getExtension())) {
- InputStream in = new ByteArrayInputStream(content);
- if (compression == Compression.GZIP) {
- in = new GZIPInputStream(in);
- } else if (compression == Compression.XZ) {
- in = new XZCompressorInputStream(in);
- } else if (compression == Compression.BZIP2) {
- in = new BZip2CompressorInputStream(in);
- }
-
- ArchiveWalker.walk(new TarArchiveInputStream(in), new ArchiveVisitor<TarArchiveEntry>() {
- public void visit(TarArchiveEntry entry, byte[] content) throws IOException {
- found.set(true);
- visitor.visit(entry, content);
- }
- });
- }
- }
- });
- return found.get();
- }
-}
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.zip.GZIPInputStream;
+
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.ArchiveInputStream;
+import org.apache.commons.compress.archivers.ar.ArArchiveEntry;
+import org.apache.commons.compress.archivers.ar.ArArchiveInputStream;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
+import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
+import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
+
+/**
+ * Support class for inspecting the content of an archive.
+ *
+ * @author Emmanuel Bourg
+ */
+public class ArchiveWalker {
+
+ public static void walk(ArchiveInputStream in, ArchiveVisitor visitor) throws IOException {
+ try {
+ ArchiveEntry entry;
+ while ((entry = in.getNextEntry()) != null) {
+ byte[] content = new byte[(int) entry.getSize()];
+ if (entry.getSize() > 0) {
+ int length = in.read(content);
+ if (length != entry.getSize()) {
+ throw new IOException("Couldn't read entry " + entry.getName() + " : read " + length + ", expected " + entry.getSize());
+ }
+ }
+
+ visitor.visit(entry, content);
+ }
+ } finally {
+ in.close();
+ }
+ }
+
+ public static boolean walkControl(File deb, final ArchiveVisitor<TarArchiveEntry> visitor) throws IOException {
+ return walkEmbedded(deb, "control.tar", visitor, Compression.GZIP);
+ }
+
+ public static boolean walkData(File deb, final ArchiveVisitor<TarArchiveEntry> visitor, final Compression compression) throws IOException {
+ return walkEmbedded(deb, "data.tar", visitor, compression);
+ }
+
+ public static boolean walkEmbedded(File deb, final String name, final ArchiveVisitor<TarArchiveEntry> visitor, final Compression compression) throws IOException {
+ final AtomicBoolean found = new AtomicBoolean(false);
+ ArArchiveInputStream in = new ArArchiveInputStream(new FileInputStream(deb));
+ ArchiveWalker.walk(in, new ArchiveVisitor<ArArchiveEntry>() {
+ public void visit(ArArchiveEntry entry, byte[] content) throws IOException {
+ if (entry.getName().equals(name + compression.getExtension())) {
+ InputStream in = new ByteArrayInputStream(content);
+ if (compression == Compression.GZIP) {
+ in = new GZIPInputStream(in);
+ } else if (compression == Compression.XZ) {
+ in = new XZCompressorInputStream(in);
+ } else if (compression == Compression.BZIP2) {
+ in = new BZip2CompressorInputStream(in);
+ }
+
+ ArchiveWalker.walk(new TarArchiveInputStream(in), new ArchiveVisitor<TarArchiveEntry>() {
+ public void visit(TarArchiveEntry entry, byte[] content) throws IOException {
+ found.set(true);
+ visitor.visit(entry, content);
+ }
+ });
+ }
+ }
+ });
+ return found.get();
+ }
+
+ public static boolean arArchiveContains(File archive, String filename) throws IOException {
+ ArchiveEntry entry;
+ ArArchiveInputStream tin;
+
+ tin = new ArArchiveInputStream(new FileInputStream (archive));
+
+ while ((entry = tin.getNextEntry()) != null) {
+ if(entry.getName().equals(filename)){
+ tin.close();
+ return true;
+ }
+ }
+
+ tin.close();
+ return false;
+ }
+}
diff --git a/src/test/java/org/vafer/jdeb/DataBuilderTestCase.java b/src/test/java/org/vafer/jdeb/DataBuilderTestCase.java
index 5a0bc17..e3ac66a 100644
--- a/src/test/java/org/vafer/jdeb/DataBuilderTestCase.java
+++ b/src/test/java/org/vafer/jdeb/DataBuilderTestCase.java
@@ -1,82 +1,83 @@
-/*
- * Copyright 2013 The jdeb developers.
- *
- * 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 org.vafer.jdeb;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.util.Arrays;
-
-import junit.framework.TestCase;
-import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.types.FileSet;
-import org.vafer.jdeb.producers.DataProducerFile;
-import org.vafer.jdeb.producers.DataProducerFileSet;
-
-public class DataBuilderTestCase extends TestCase {
-
- /**
- * Checks if the file paths in the md5sums file use only unix file separators
- * (this test can only fail on Windows)
- */
- public void testBuildDataWithFileSet() throws Exception {
- DataBuilder builder = new DataBuilder(new NullConsole());
-
- Project project = new Project();
- project.setCoreLoader(getClass().getClassLoader());
- project.init();
-
- FileSet fileset = new FileSet();
- fileset.setDir(new File(getClass().getResource("deb/data").toURI()));
- fileset.setIncludes("**/*");
- fileset.setProject(project);
-
- StringBuilder md5s = new StringBuilder();
- builder.buildData(Arrays.asList((DataProducer) new DataProducerFileSet(fileset)), new File("target/data.tar"), md5s, Compression.GZIP);
-
- assertTrue("empty md5 file", md5s.length() > 0);
- assertFalse("windows path separator found", md5s.indexOf("\\") != -1);
- }
-
- public void testCreateParentDirectories() throws Exception {
- File archive = new File("target/data.tar");
- if (archive.exists()) {
- archive.delete();
- }
-
- DataBuilder builder = new DataBuilder(new NullConsole());
-
- DataProducer producer = new DataProducerFile(new File("pom.xml"), "/usr/share/myapp/pom.xml", null, null, null);
-
- builder.buildData(Arrays.asList(producer), archive, new StringBuilder(), Compression.NONE);
-
- int count = 0;
- TarArchiveInputStream in = null;
- try {
- in = new TarArchiveInputStream(new FileInputStream(archive));
- while (in.getNextTarEntry() != null) {
- count++;
- }
- } finally {
- if (in != null) {
- in.close();
- }
- }
-
- assertEquals("entries", 4, count);
- }
-}
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.FileSet;
+import org.vafer.jdeb.producers.DataProducerFile;
+import org.vafer.jdeb.producers.DataProducerFileSet;
+
+public class DataBuilderTestCase extends TestCase {
+
+ /**
+ * Checks if the file paths in the md5sums file use only unix file separators
+ * (this test can only fail on Windows)
+ */
+ public void testBuildDataWithFileSet() throws Exception {
+ DataBuilder builder = new DataBuilder(new NullConsole());
+
+ Project project = new Project();
+ project.setCoreLoader(getClass().getClassLoader());
+ project.init();
+
+ FileSet fileset = new FileSet();
+ fileset.setDir(new File(getClass().getResource("deb/data").toURI()));
+ fileset.setIncludes("**/*");
+ fileset.setProject(project);
+
+ StringBuilder md5s = new StringBuilder();
+ builder.buildData(Arrays.asList((DataProducer) new DataProducerFileSet(fileset)), new File("target/data.tar"), md5s, Compression.GZIP);
+
+ assertTrue("empty md5 file", md5s.length() > 0);
+ assertFalse("windows path separator found", md5s.indexOf("\\") != -1);
+ assertTrue("two spaces between md5 and file", md5s.toString().equals("8bc944dbd052ef51652e70a5104492e3 ./test/testfile\n"));
+ }
+
+ public void testCreateParentDirectories() throws Exception {
+ File archive = new File("target/data.tar");
+ if (archive.exists()) {
+ archive.delete();
+ }
+
+ DataBuilder builder = new DataBuilder(new NullConsole());
+
+ DataProducer producer = new DataProducerFile(new File("pom.xml"), "/usr/share/myapp/pom.xml", null, null, null);
+
+ builder.buildData(Arrays.asList(producer), archive, new StringBuilder(), Compression.NONE);
+
+ int count = 0;
+ TarArchiveInputStream in = null;
+ try {
+ in = new TarArchiveInputStream(new FileInputStream(archive));
+ while (in.getNextTarEntry() != null) {
+ count++;
+ }
+ } finally {
+ if (in != null) {
+ in.close();
+ }
+ }
+
+ assertEquals("entries", 4, count);
+ }
+}
diff --git a/src/test/java/org/vafer/jdeb/DebMakerTestCase.java b/src/test/java/org/vafer/jdeb/DebMakerTestCase.java
index 7eaf17c..021c9e6 100644
--- a/src/test/java/org/vafer/jdeb/DebMakerTestCase.java
+++ b/src/test/java/org/vafer/jdeb/DebMakerTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -55,7 +55,7 @@ public class DebMakerTestCase extends TestCase {
File deb = File.createTempFile("jdeb", ".deb");
- DebMaker maker = new DebMaker(new NullConsole(), Arrays.asList(data));
+ DebMaker maker = new DebMaker(new NullConsole(), Arrays.asList(data), null);
maker.setControl(new File(getClass().getResource("deb/control").toURI()));
maker.setDeb(deb);
@@ -88,7 +88,8 @@ public class DebMakerTestCase extends TestCase {
}
Collection<DataProducer> producers = Arrays.asList(new DataProducer[] {new EmptyDataProducer()});
- DebMaker maker = new DebMaker(new NullConsole(), producers);
+ Collection<DataProducer> conffileProducers = Arrays.asList(new DataProducer[] {new EmptyDataProducer()});
+ DebMaker maker = new DebMaker(new NullConsole(), producers, conffileProducers);
maker.setDeb(deb);
maker.setControl(new File("target/test-classes/org/vafer/jdeb/deb/control"));
@@ -132,7 +133,8 @@ public class DebMakerTestCase extends TestCase {
variables.put("version", "1.0");
Collection<DataProducer> producers = Arrays.asList(new DataProducer[] {new EmptyDataProducer()});
- DebMaker maker = new DebMaker(new NullConsole(), producers);
+ Collection<DataProducer> conffileProducers = Arrays.asList(new DataProducer[] {new EmptyDataProducer()});
+ DebMaker maker = new DebMaker(new NullConsole(), producers, conffileProducers);
maker.setDeb(deb);
maker.setControl(new File("target/test-classes/org/vafer/jdeb/deb/control"));
maker.setResolver(new MapVariableResolver(variables));
diff --git a/src/test/java/org/vafer/jdeb/EmptyDataProducer.java b/src/test/java/org/vafer/jdeb/EmptyDataProducer.java
index 9b38ca6..c699572 100644
--- a/src/test/java/org/vafer/jdeb/EmptyDataProducer.java
+++ b/src/test/java/org/vafer/jdeb/EmptyDataProducer.java
@@ -1,28 +1,28 @@
-/*
- * Copyright 2013 The jdeb developers.
- *
- * 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 org.vafer.jdeb;
-
-import java.io.IOException;
-
-/**
- * @author Emmanuel Bourg
- */
-public class EmptyDataProducer implements DataProducer {
-
- public void produce(DataConsumer receiver) throws IOException {
- }
-}
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb;
+
+import java.io.IOException;
+
+/**
+ * @author Emmanuel Bourg
+ */
+public class EmptyDataProducer implements DataProducer {
+
+ public void produce(DataConsumer receiver) throws IOException {
+ }
+}
diff --git a/src/test/java/org/vafer/jdeb/NullConsole.java b/src/test/java/org/vafer/jdeb/NullConsole.java
index 97a8f85..22a1a77 100644
--- a/src/test/java/org/vafer/jdeb/NullConsole.java
+++ b/src/test/java/org/vafer/jdeb/NullConsole.java
@@ -1,28 +1,32 @@
-/*
- * Copyright 2013 The jdeb developers.
- *
- * 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 org.vafer.jdeb;
-
-public class NullConsole implements Console {
-
- @Override
- public void info(String s) {
- }
-
- @Override
- public void warn(String s) {
- }
-}
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb;
+
+public class NullConsole implements Console {
+
+ @Override
+ public void debug(String message) {
+ }
+
+ @Override
+ public void info(String message) {
+ }
+
+ @Override
+ public void warn(String message) {
+ }
+}
diff --git a/src/test/java/org/vafer/jdeb/ant/AntSelectorTestCase.java b/src/test/java/org/vafer/jdeb/ant/AntSelectorTestCase.java
index 05beec9..6a34f58 100644
--- a/src/test/java/org/vafer/jdeb/ant/AntSelectorTestCase.java
+++ b/src/test/java/org/vafer/jdeb/ant/AntSelectorTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/test/java/org/vafer/jdeb/ant/DebAntTaskTestCase.java b/src/test/java/org/vafer/jdeb/ant/DebAntTaskTestCase.java
index ee553ca..df6289e 100644
--- a/src/test/java/org/vafer/jdeb/ant/DebAntTaskTestCase.java
+++ b/src/test/java/org/vafer/jdeb/ant/DebAntTaskTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -93,12 +93,9 @@ public final class DebAntTaskTestCase extends TestCase {
}
public void testEmptyPackage() {
- try {
- project.executeTarget("empty-package");
- fail("No exception thrown");
- } catch (BuildException e) {
- // expected
- }
+ project.executeTarget("empty-package");
+
+ assertTrue("package not build", new File("target/test-classes/test.deb").exists());
}
public void testPackageWithArchive() {
@@ -225,6 +222,21 @@ public final class DebAntTaskTestCase extends TestCase {
assertTrue("Link not found", linkFound.get());
}
+ public void testMapper() throws Exception {
+ project.executeTarget("perm-mapper");
+
+ File deb = new File("target/test-classes/test.deb");
+ assertTrue("package not build", deb.exists());
+
+ ArchiveWalker.walkData(deb, new ArchiveVisitor<TarArchiveEntry>() {
+ public void visit(TarArchiveEntry entry, byte[] content) throws IOException {
+ if (entry.isFile()) {
+ assertEquals("file mode (" + entry.getName() + ")", 0700, entry.getMode());
+ }
+ }
+ }, Compression.GZIP);
+ }
+
public void testUnkownCompression() throws Exception {
try {
project.executeTarget("unknown-compression");
@@ -305,4 +317,10 @@ public final class DebAntTaskTestCase extends TestCase {
assertTrue("tar file not found", found);
}
+
+ public void testPackageConffiles() {
+ project.executeTarget("conffiles");
+
+ assertTrue("package not build", new File("target/test-classes/test.deb").exists());
+ }
}
diff --git a/src/test/java/org/vafer/jdeb/changes/TextfileChangesProviderTestCase.java b/src/test/java/org/vafer/jdeb/changes/TextfileChangesProviderTestCase.java
index e36a3d9..f5a7a17 100644
--- a/src/test/java/org/vafer/jdeb/changes/TextfileChangesProviderTestCase.java
+++ b/src/test/java/org/vafer/jdeb/changes/TextfileChangesProviderTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/test/java/org/vafer/jdeb/debian/ChangesFileTestCase.java b/src/test/java/org/vafer/jdeb/debian/ChangesFileTestCase.java
index c8e68aa..60a7131 100644
--- a/src/test/java/org/vafer/jdeb/debian/ChangesFileTestCase.java
+++ b/src/test/java/org/vafer/jdeb/debian/ChangesFileTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,11 +26,13 @@ public final class ChangesFileTestCase extends TestCase {
packageControlFile.set("Package", "test-package");
packageControlFile.set("Description", "This is\na description\non several lines");
packageControlFile.set("Version", "1.0");
+ packageControlFile.set("XC-UserDefinedField", "This is a user defined field.");
ChangesFile changes = new ChangesFile();
changes.setChanges(new ChangeSet[0]);
changes.initialize(packageControlFile);
assertEquals("1.0", changes.get("Version"));
+ assertEquals("This is a user defined field.", changes.get("UserDefinedField"));
}
}
diff --git a/src/test/java/org/vafer/jdeb/debian/ControlFieldTestCase.java b/src/test/java/org/vafer/jdeb/debian/ControlFieldTestCase.java
index 35ce579..45291b5 100644
--- a/src/test/java/org/vafer/jdeb/debian/ControlFieldTestCase.java
+++ b/src/test/java/org/vafer/jdeb/debian/ControlFieldTestCase.java
@@ -1,44 +1,44 @@
-/*
- * Copyright 2013 The jdeb developers.
- *
- * 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 org.vafer.jdeb.debian;
-
-import junit.framework.TestCase;
-
-/**
- * @author Emmanuel Bourg
- * @version $Revision$, $Date$
- */
-public class ControlFieldTestCase extends TestCase {
-
- public void testFormatSimpleValue() {
- ControlField field = new ControlField("Field-Name");
-
- assertEquals("Field-Name: value\n", field.format("value"));
- }
-
- public void testFormatMultilineValue1() {
- ControlField field = new ControlField("Field-Name", false, ControlField.Type.MULTILINE);
-
- assertEquals("Field-Name: value1\n value2\n .\n value3\n", field.format("value1\nvalue2\n\nvalue3"));
- }
-
- public void testFormatMultilineValue2() {
- ControlField field = new ControlField("Field-Name", false, ControlField.Type.MULTILINE, true);
-
- assertEquals("Field-Name:\n value1\n value2\n .\n value3\n", field.format("value1\nvalue2\n\nvalue3"));
- }
-}
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb.debian;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Emmanuel Bourg
+ * @version $Revision$, $Date$
+ */
+public class ControlFieldTestCase extends TestCase {
+
+ public void testFormatSimpleValue() {
+ ControlField field = new ControlField("Field-Name");
+
+ assertEquals("Field-Name: value\n", field.format("value"));
+ }
+
+ public void testFormatMultilineValue1() {
+ ControlField field = new ControlField("Field-Name", false, ControlField.Type.MULTILINE);
+
+ assertEquals("Field-Name: value1\n value2\n .\n value3\n", field.format("value1\nvalue2\n\nvalue3"));
+ }
+
+ public void testFormatMultilineValue2() {
+ ControlField field = new ControlField("Field-Name", false, ControlField.Type.MULTILINE, true);
+
+ assertEquals("Field-Name:\n value1\n value2\n .\n value3\n", field.format("value1\nvalue2\n\nvalue3"));
+ }
+}
diff --git a/src/test/java/org/vafer/jdeb/debian/PackageControlFileTestCase.java b/src/test/java/org/vafer/jdeb/debian/PackageControlFileTestCase.java
index 7c18587..77be912 100644
--- a/src/test/java/org/vafer/jdeb/debian/PackageControlFileTestCase.java
+++ b/src/test/java/org/vafer/jdeb/debian/PackageControlFileTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@ public final class PackageControlFileTestCase extends TestCase {
" Value2.1\n" +
" Value2.2\n" +
"Key3: Value3\n";
-
+
BinaryPackageControlFile d = new BinaryPackageControlFile(input);
assertFalse(d.isValid());
@@ -44,9 +44,9 @@ public final class PackageControlFileTestCase extends TestCase {
packageControlFile.set("Package", "test-package");
packageControlFile.set("Description", "This is\na description\non several lines");
packageControlFile.set("Version", "1.0");
-
+
String s = packageControlFile.toString();
-
+
BinaryPackageControlFile packageControlFile2 = new BinaryPackageControlFile(s);
assertEquals("Package", packageControlFile.get("Package"), packageControlFile2.get("Package"));
assertEquals("Description", packageControlFile.get("Description"), packageControlFile2.get("Description"));
@@ -64,28 +64,34 @@ public final class PackageControlFileTestCase extends TestCase {
} catch (ParseException e) {
}
}
-
+
public void testGetShortDescription() {
BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile();
-
+
assertNull(packageControlFile.getShortDescription());
-
+
packageControlFile.set("Description", "This is the short description\nThis is the loooooong description");
-
+
assertEquals("short description", "This is the short description", packageControlFile.getShortDescription());
-
+
packageControlFile.set("Description", "\nThere is no short description");
-
+
assertEquals("short description", "", packageControlFile.getShortDescription());
}
public void testGetDescription() throws Exception {
BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile();
packageControlFile.parse(new FileInputStream("target/test-classes/org/vafer/jdeb/deb/control/control"));
-
+
assertEquals("Description", "revision @REVISION@, test package\n" +
"This is a sample package control file.\n\n" +
"Use for testing purposes only.",
packageControlFile.get("Description"));
}
+
+ public void testGetUserDefinedFields() throws Exception {
+ BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile();
+ packageControlFile.parse(new FileInputStream("target/test-classes/org/vafer/jdeb/deb/control/control"));
+ assertEquals("UserDefinedField", "This is a user defined field.", packageControlFile.get("UserDefinedField"));
+ }
}
diff --git a/src/test/java/org/vafer/jdeb/mapping/LsMapperTestCase.java b/src/test/java/org/vafer/jdeb/mapping/LsMapperTestCase.java
index 309759b..e08ea9d 100644
--- a/src/test/java/org/vafer/jdeb/mapping/LsMapperTestCase.java
+++ b/src/test/java/org/vafer/jdeb/mapping/LsMapperTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/test/java/org/vafer/jdeb/maven/DataTestCase.java b/src/test/java/org/vafer/jdeb/maven/DataTestCase.java
index fb89491..497144e 100644
--- a/src/test/java/org/vafer/jdeb/maven/DataTestCase.java
+++ b/src/test/java/org/vafer/jdeb/maven/DataTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/test/java/org/vafer/jdeb/producers/DataProducerFilesTestCase.java b/src/test/java/org/vafer/jdeb/producers/DataProducerFilesTestCase.java
new file mode 100644
index 0000000..b55b007
--- /dev/null
+++ b/src/test/java/org/vafer/jdeb/producers/DataProducerFilesTestCase.java
@@ -0,0 +1,89 @@
+package org.vafer.jdeb.producers;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.vafer.jdeb.DataConsumer;
+
+/**
+ * Tests for {@link org.vafer.jdeb.producers.DataProducerFiles}.
+ *
+ * @author Roman Kashitsyn
+ */
+public class DataProducerFilesTestCase extends TestCase {
+ File file1;
+ File file2;
+
+ public void setUp() throws Exception {
+ file1 = File.createTempFile(getClass().getSimpleName() + ".1", "txt");
+ file2 = File.createTempFile(getClass().getSimpleName() + ".2", "txt");
+ }
+
+ public void tearDown() throws Exception {
+ file1.delete();
+ file2.delete();
+ }
+
+ public void testProducesMultiplePaths() throws IOException {
+ DataConsumer consumer = mock(DataConsumer.class);
+ new DataProducerFiles(
+ new String[]{
+ file1.getAbsolutePath(),
+ file2.getAbsolutePath()
+ },
+ "/usr/include",
+ null
+ ).produce(consumer);
+
+ for (File f : Arrays.asList(file1, file2)) {
+ verify(consumer).onEachFile(
+ any(FileInputStream.class),
+ eq("/usr/include/" + f.getName()),
+ any(String.class),
+ eq("root"),
+ eq(0),
+ eq("root"),
+ eq(0),
+ anyInt(),
+ eq(f.length())
+ );
+ }
+ }
+
+ public void testProducesMultiplePathsNoDestination() throws IOException {
+ DataConsumer consumer = mock(DataConsumer.class);
+ new DataProducerFiles(
+ new String[]{
+ file1.getAbsolutePath(),
+ file2.getAbsolutePath()
+ },
+ null,
+ null
+ ).produce(consumer);
+
+ for (File f : Arrays.asList(file1, file2)) {
+ verify(consumer).onEachFile(
+ any(FileInputStream.class),
+ eq(new TarArchiveEntry(f.getAbsolutePath(), true).getName()),
+ any(String.class),
+ eq("root"),
+ eq(0),
+ eq("root"),
+ eq(0),
+ anyInt(),
+ eq(f.length())
+ );
+ }
+ }
+}
diff --git a/src/test/java/org/vafer/jdeb/producers/DataProducerPathTemplateTestCase.java b/src/test/java/org/vafer/jdeb/producers/DataProducerPathTemplateTestCase.java
index 60ac425..05f96d3 100644
--- a/src/test/java/org/vafer/jdeb/producers/DataProducerPathTemplateTestCase.java
+++ b/src/test/java/org/vafer/jdeb/producers/DataProducerPathTemplateTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/test/java/org/vafer/jdeb/signing/DebMakerTestCase.java b/src/test/java/org/vafer/jdeb/signing/DebMakerTestCase.java
new file mode 100644
index 0000000..330447d
--- /dev/null
+++ b/src/test/java/org/vafer/jdeb/signing/DebMakerTestCase.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2014 The jdeb developers.
+ *
+ * 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 org.vafer.jdeb.signing;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.io.FileUtils;
+import org.bouncycastle.openpgp.PGPSignature;
+import org.bouncycastle.openpgp.PGPSignatureGenerator;
+import org.bouncycastle.openpgp.PGPUtil;
+import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder;
+import org.vafer.jdeb.ArchiveVisitor;
+import org.vafer.jdeb.ArchiveWalker;
+import org.vafer.jdeb.Compression;
+import org.vafer.jdeb.DataProducer;
+import org.vafer.jdeb.DebMaker;
+import org.vafer.jdeb.NullConsole;
+import org.vafer.jdeb.debian.BinaryPackageControlFile;
+import org.vafer.jdeb.producers.DataProducerArchive;
+import org.vafer.jdeb.producers.DataProducerDirectory;
+import org.vafer.jdeb.producers.DataProducerLink;
+
+public class DebMakerTestCase extends TestCase {
+
+ public void testCreation() throws Exception {
+
+ File control = new File(getClass().getResource("../deb/control/control").toURI());
+ File archive1 = new File(getClass().getResource("../deb/data.tgz").toURI());
+ File archive2 = new File(getClass().getResource("../deb/data.tar.bz2").toURI());
+ File archive3 = new File(getClass().getResource("../deb/data.zip").toURI());
+ File directory = new File(getClass().getResource("../deb/data").toURI());
+
+ final InputStream ring = getClass().getClassLoader().getResourceAsStream("org/vafer/gpg/secring.gpg");
+
+ DataProducer[] data = new DataProducer[] {
+ new DataProducerArchive(archive1, null, null, null),
+ new DataProducerArchive(archive2, null, null, null),
+ new DataProducerArchive(archive3, null, null, null),
+ new DataProducerDirectory(directory, null, new String[] { "**/.svn/**" }, null),
+ new DataProducerLink("/link/path-element.ext", "/link/target-element.ext", true, null, null, null)
+ };
+
+ int digest = PGPUtil.SHA1;
+ PGPSigner signer = new PGPSigner(ring, "2E074D8F", "test");
+ PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(new BcPGPContentSignerBuilder(signer.getSecretKey().getPublicKey().getAlgorithm(), digest));
+ signatureGenerator.init(PGPSignature.BINARY_DOCUMENT, signer.getPrivateKey());
+
+ for(int i = 0; i <=1; i++){
+ File deb = File.createTempFile("jdeb", ".deb");
+
+ DebMaker maker = new DebMaker(new NullConsole(), Arrays.asList(data), null);
+ maker.setControl(new File(getClass().getResource("../deb/control").toURI()));
+ maker.setDeb(deb);
+
+ if(i==0)
+ maker.setSignMethod("debsig-verify");
+ else
+ maker.setSignMethod("dpkg-sig");
+
+ BinaryPackageControlFile packageControlFile = maker.createSignedDeb(Compression.GZIP, signatureGenerator, signer);
+
+ assertTrue(packageControlFile.isValid());
+
+ final Map<String, TarArchiveEntry> filesInDeb = new HashMap<String, TarArchiveEntry>();
+
+ ArchiveWalker.walkData(deb, new ArchiveVisitor<TarArchiveEntry>() {
+ public void visit(TarArchiveEntry entry, byte[] content) throws IOException {
+ filesInDeb.put(entry.getName(), entry);
+ }
+ }, Compression.GZIP);
+
+ assertTrue("_gpgorigin wasn't found in the package", ArchiveWalker.arArchiveContains(deb, "_gpgorigin"));
+ assertTrue("debian-binary wasn't found in the package", ArchiveWalker.arArchiveContains(deb, "debian-binary"));
+ assertTrue("control.tar.gz wasn't found in the package", ArchiveWalker.arArchiveContains(deb, "control.tar.gz"));
+ assertTrue("testfile wasn't found in the package", filesInDeb.containsKey("./test/testfile"));
+ assertTrue("testfile2 wasn't found in the package", filesInDeb.containsKey("./test/testfile2"));
+ assertTrue("testfile3 wasn't found in the package", filesInDeb.containsKey("./test/testfile3"));
+ assertTrue("testfile4 wasn't found in the package", filesInDeb.containsKey("./test/testfile4"));
+ assertTrue("/link/path-element.ext wasn't found in the package", filesInDeb.containsKey("./link/path-element.ext"));
+ assertEquals("/link/path-element.ext has wrong link target", "/link/target-element.ext", filesInDeb.get("./link/path-element.ext").getLinkName());
+
+ if(i==0){
+ FileUtils.copyFile(deb, new File("./target/test_debsig-verify.deb"));
+ }else{
+ FileUtils.copyFile(deb, new File("./target/test_dpkg-sig.deb"));
+ }
+
+ assertTrue("Cannot delete the file " + deb, deb.delete());
+ }
+ }
+}
diff --git a/src/test/java/org/vafer/jdeb/signing/PGPSignerTestCase.java b/src/test/java/org/vafer/jdeb/signing/PGPSignerTestCase.java
index 0e1c087..0494104 100644
--- a/src/test/java/org/vafer/jdeb/signing/PGPSignerTestCase.java
+++ b/src/test/java/org/vafer/jdeb/signing/PGPSignerTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
package org.vafer.jdeb.signing;
-import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Arrays;
@@ -31,7 +30,7 @@ public final class PGPSignerTestCase extends TestCase {
assertNotNull(ring);
- String input = "TEST1 \n-TEST2 \n \nTEST3 \n";
+ String input = "TEST1\n-TEST2 \n \nTEST3\n";
final String expectedOutputStr =
"-----BEGIN PGP SIGNED MESSAGE-----\n" +
@@ -42,7 +41,7 @@ public final class PGPSignerTestCase extends TestCase {
"\n" +
"TEST3\n" +
"-----BEGIN PGP SIGNATURE-----\n" +
- "Version: BCPG v1.48\n" +
+ "Version: BCPG v1.51\n" +
"\n" +
"iEYEARECABAFAkax1rgJEHM9pIAuB02PAABIJgCghFmoCJCZ0CGiqgVLGGPd/Yh5\n" +
"FQQAnRVqvI2ij45JQSHYJBblZ0Vv2meN\n" +
@@ -52,17 +51,16 @@ public final class PGPSignerTestCase extends TestCase {
final byte[] expectedOutput = expectedOutputStr.getBytes("UTF-8");
final ByteArrayOutputStream os = new ByteArrayOutputStream();
-
+
PGPSigner signer = new PGPSigner(ring, "2E074D8F", "test");
signer.clearSign(input, os);
-
- final byte[] output = fixCRLF(os.toByteArray());
+ final byte[] output = fixCRLF(os.toByteArray());
final int from = expectedOutputStr.indexOf("iEYEAREC");
final int until = expectedOutputStr.indexOf("=aAAT") + 5;
Arrays.fill(output, from, until, (byte) '?');
Arrays.fill(expectedOutput, from, until, (byte) '?');
-
+
assertEquals(new String(expectedOutput), new String(output));
}
diff --git a/src/test/java/org/vafer/jdeb/utils/FilteredFileTestCase.java b/src/test/java/org/vafer/jdeb/utils/FilteredFileTestCase.java
index e2d6eb8..b2be1b0 100644
--- a/src/test/java/org/vafer/jdeb/utils/FilteredFileTestCase.java
+++ b/src/test/java/org/vafer/jdeb/utils/FilteredFileTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,6 +46,15 @@ public class FilteredFileTestCase extends TestCase {
assertEquals("#!/bin/sh\ncat jdebcustom1 \necho 'custom2'\n", actual);
}
+ public void testTokenSubstitutionWithinOpenCloseTokens() throws Exception {
+ InputStream in = new ReaderInputStream(new StringReader("#!/bin/bash\nif [[ -z \"$(grep [[artifactId]] /etc/passwd )\" ]] ; then\n"));
+
+ FilteredFile placeHolder = new FilteredFile(in, variableResolver);
+
+ String actual = placeHolder.toString();
+ assertEquals("", "#!/bin/bash\nif [[ -z \"$(grep jdeb /etc/passwd )\" ]] ; then\n", actual);
+ }
+
public void testVariableSubstitution() throws Exception {
Map<String, String> map = new HashMap<String, String>();
map.put("VERSION", "1.2");
diff --git a/src/test/java/org/vafer/jdeb/utils/InformationInputStreamTestCase.java b/src/test/java/org/vafer/jdeb/utils/InformationInputStreamTestCase.java
index 478e5a6..c830df3 100644
--- a/src/test/java/org/vafer/jdeb/utils/InformationInputStreamTestCase.java
+++ b/src/test/java/org/vafer/jdeb/utils/InformationInputStreamTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/test/java/org/vafer/jdeb/utils/UtilsTestCase.java b/src/test/java/org/vafer/jdeb/utils/UtilsTestCase.java
index e7b4777..ca0b374 100644
--- a/src/test/java/org/vafer/jdeb/utils/UtilsTestCase.java
+++ b/src/test/java/org/vafer/jdeb/utils/UtilsTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013 The jdeb developers.
+ * Copyright 2014 The jdeb developers.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -83,15 +83,60 @@ public class UtilsTestCase extends TestCase {
result = Utils.replaceVariables(resolver, "if [[ \"${HOST_TYPE}\" -eq \"admin\" ]] ; then", "[[", "]]");
assertEquals("if [[ \"${HOST_TYPE}\" -eq \"admin\" ]] ; then", result);
+ // end of line https://github.com/tcurdt/jdeb/issues/154
+ String input = "if [ -e some_file ]";
+ result = Utils.replaceVariables(resolver, input, "[[", "]]");
+ assertEquals(input, result);
+
// mixed valid and unknown variables
result = Utils.replaceVariables(resolver, "[[name]] [[test]]", "[[", "]]");
assertEquals("jdeb [[test]]", result);
+
+ // nested vars
+ result = Utils.replaceVariables(new VariableResolver() {
+ public String get(String pKey) {
+ return "VAR";
+ }
+ }, "[[var]] [[ [[var]] [[ [[var]] ]] [[var]] ]]", "[[", "]]");
+
+ assertEquals("VAR [[ VAR [[ VAR ]] VAR ]]", result);
+ }
+
+ public void testReplaceVariablesWithinOpenCloseTokens() throws Exception {
+ Map<String, String> variables = new HashMap<String, String>();
+ variables.put("artifactId", "jdeb");
+
+ VariableResolver resolver = new MapVariableResolver(variables);
+
+ String result = Utils.replaceVariables(resolver, "if [[ -z \"$(grep [[artifactId]] /etc/passwd )\" ]] ; then", "[[", "]]");
+
+ assertEquals("", "if [[ -z \"$(grep jdeb /etc/passwd )\" ]] ; then", result);
+
}
public void testVersionConversion() {
- Calendar cal = new GregorianCalendar(2013, 02-1, 17);
- assertEquals("should match", "1.0", Utils.convertToDebianVersion("1.0", null));
- assertEquals("should match", "1.0~SNAPSHOT", Utils.convertToDebianVersion("1.0+SNAPSHOT", null));
- assertEquals("should match", "1.0~20130217000000", Utils.convertToDebianVersion("1.0+SNAPSHOT", cal.getTime()));
+ Calendar cal = new GregorianCalendar(2013, Calendar.FEBRUARY, 17);
+ assertEquals("should match", "1.0", Utils.convertToDebianVersion("1.0", false, "SNAPSHOT", cal.getTime()));
+ assertEquals("should match", "1.0~SNAPSHOT", Utils.convertToDebianVersion("1.0+SNAPSHOT", false, "SNAPSHOT", cal.getTime()));
+ assertEquals("should match", "1.0~SNAPSHOT", Utils.convertToDebianVersion("1.0-SNAPSHOT", false, "SNAPSHOT", cal.getTime()));
+ assertEquals("should match", "1.0~20130217000000", Utils.convertToDebianVersion("1.0+SNAPSHOT", true, "SNAPSHOT", cal.getTime()));
+ assertEquals("should match", "1.0~RC2", Utils.convertToDebianVersion("1.0-RC2", true, "SNAPSHOT", cal.getTime()));
+ assertEquals("should match", "1.0~alpha3", Utils.convertToDebianVersion("1.0-alpha3", true, "SNAPSHOT", cal.getTime()));
+ assertEquals("should match", "1.0~Beta+4", Utils.convertToDebianVersion("1.0.Beta-4", true, "SNAPSHOT", cal.getTime()));
+ assertEquals("should match", "1.0~milestone+4", Utils.convertToDebianVersion("1.0-milestone-4", true, "SNAPSHOT", cal.getTime()));
+ assertEquals("should match", "1.0~a+4", Utils.convertToDebianVersion("1.0-a-4", true, "SNAPSHOT", cal.getTime()));
+ assertEquals("should match", "1.0~b+4", Utils.convertToDebianVersion("1.0-b-4", true, "SNAPSHOT", cal.getTime()));
+ assertEquals("should match", "1.0~rc7", Utils.convertToDebianVersion("1.0rc7", true, "SNAPSHOT", cal.getTime()));
+ assertEquals("should match", "1.0~M1", Utils.convertToDebianVersion("1.0.M1", true, "SNAPSHOT", cal.getTime()));
+ assertEquals("should match", "1.0~M2", Utils.convertToDebianVersion("1.0-M2", true, "SNAPSHOT", cal.getTime()));
+ assertEquals("should match", "1.0~M3", Utils.convertToDebianVersion("1.0M3", true, "SNAPSHOT", cal.getTime()));
+ }
+
+ public void testMovePath() {
+ assertEquals("/usr/share/file.txt", Utils.movePath("file.txt", "/usr/share"));
+ assertEquals("/usr/share/file.txt", Utils.movePath("file.txt", "/usr/share/"));
+ assertEquals("/usr/share/noext", Utils.movePath("noext", "/usr/share/"));
+ assertEquals("/usr/share/file.txt", Utils.movePath("/home/user/file.txt", "/usr/share"));
+ assertEquals("/usr/share/file.txt", Utils.movePath("../relative/file.txt", "/usr/share/"));
}
}
diff --git a/src/test/resources/org/vafer/jdeb/deb/control/control b/src/test/resources/org/vafer/jdeb/deb/control/control
index 226eca2..673ecbe 100644
--- a/src/test/resources/org/vafer/jdeb/deb/control/control
+++ b/src/test/resources/org/vafer/jdeb/deb/control/control
@@ -10,3 +10,4 @@ Description: revision @REVISION@, test package
This is a sample package control file.
.
Use for testing purposes only.
+XB-UserDefinedField: This is a user defined field.
diff --git a/src/test/resources/testbuild.xml b/src/test/resources/testbuild.xml
index 56acc50..2252814 100644
--- a/src/test/resources/testbuild.xml
+++ b/src/test/resources/testbuild.xml
@@ -87,6 +87,14 @@
</deb>
</target>
+ <target name="perm-mapper">
+ <deb destfile="test.deb" control="org/vafer/jdeb/deb/control">
+ <data src="org/vafer/jdeb/deb/data" type="directory">
+ <mapper type="perm" filemode="700" prefix="/usr/share/foo"/>
+ </data>
+ </deb>
+ </target>
+
<target name="unknown-compression">
<deb destfile="test.deb" control="org/vafer/jdeb/deb/control" compression="rar">
<fileset dir="org/vafer/jdeb/deb/data"/>
@@ -111,4 +119,10 @@
</deb>
</target>
+ <target name="conffiles">
+ <deb destfile="test123.deb" control="org/vafer/jdeb/deb/control">
+ <data src="org/vafer/jdeb/deb/data" type="directory" conffile="true" />
+ </deb>
+ </target>
+
</project>
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/jdeb.git
More information about the pkg-java-commits
mailing list