jdeb/0000755000175000017500000000000012210355254011641 5ustar moellermoellerjdeb/.gitignore0000644000175000017500000000016312207644255013641 0ustar moellermoeller.DS_Store .classpath .project .settings target eclipse dependency-reduced-pom.xml *.iml *.iws *.ipr /.idea .releasejdeb/.travis.yml0000644000175000017500000000011412207644255013756 0ustar moellermoellerlanguage: java jdk: - oraclejdk7 - oraclejdk6 - openjdk7 - openjdk6 jdeb/HISTORY.md0000644000175000017500000001132312207644255013334 0ustar moellermoeller## Version 1.1, released ? * [ADD] xz compression support * [ADD] Added link support to the Ant task * [ADD] Support permission in (hard) link setup * [FIX] On Windows, parent directories are now created automatically when adding files to the data archive * [CHG] Links are now symbolic by default ## Version 1.0.1, released 28.02.2013 * [ADD] Override version via environment variable DEBVERSION * [FIX] Use the joint copyright * [FIX] Fixed the maven to debian version mapping ## Version 1.0, released 10.01.2013 * [ADD] Support for symbolic links (Maven only) * [FIX] Unresolved variables in package maintainer scripts no longer break the build * [CHG] Use "_all" as architecture postfix by default ## Version 0.11, released 14.07.2012 * [ADD] Added "timestamped" maven config to turn "SNAPSHOT" into a timestamp * [ADD] Added "verbose" maven config option to show/hide INFO logs * [ADD] Expand variables in configuration files "conffiles", "preinst", "postinst", "prerm", "postrm" * [ADD] Added a "template" data type to create dirs * [ADD] Added "missingSrc" maven config to control behavior on missing files/folders * [CHG] Use "~" instead of "+" when converting from a SNAPSHOT version * [REM] Deprecated PrefixMapper was removed (use PermMapper instead) ## Version 0.10, released 18.02.2012 Polishing and regression fixes * [FIX] Don't throw exception when detecting zip archives * [FIX] Make sure to close the tar output stream * [CHG] Have warn/info level on messages * [CHG] Fix line endings for control files * [ADD] Access to all Maven variables ## Version 0.9, released 17.12.2011 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] Warn if control files have non-unix line endings * [CHG] Throw an exception for unknown mappers * [REM] InvalidDescriptorException, wasn't really used anyway * [ADD] Added an "attach" attribute to specify whether maven artifact should be attached to project. * [ADD] Provide SHA1, SHA256 and not just MD5 for descriptors * [ADD] Provide "project.version" when using maven ## Version 0.8, released 27.06.2010 Lot of refactoring and support for configuration on the maven plugin. Easier permission mapping. * [CHG] Default maven artifact type is now "deb" instead of "deb-archive". * [CHG] Switched to commons compress for archive building. * [CHG] Renamed the maven goal from "deb" to "jdeb" to be more consistent. * [CHG] Maven goal no longer attached to execution phase by default. (see examples) * [CHG] Deprecated "FileSetDataProducer" in favor of "DataProducerFileSet" * [ADD] Added a "type" attribute to the "data" elements. * [ADD] New options to the maven plugin to configure the attached artifact. * [ADD] Added Examples for ant and maven. * [ADD] New "file" data source. ## Version 0.7, released 18.08.2008 Proper closing of streams! 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. * [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). * [ADD] More package descriptor keys (Pre-Depends, Recommends, Suggests, Breaks, Enhances, Homepage>). * [ADD] Verbose attribute for the Ant task. * [ADD] The Ant task now accepts tarfileset elements. ## Version 0.6, released 11.01.2008 * [FIX] Fixed the trailing linefeed in the 'changes' section of the changes file. ## Version 0.5, released 26.11.2007 * [FIX] Fixed the 'ls' parsing. * [CHG] Switched to ArInputStream/ArOutputStream. * [REM] Removed deprecated ant task delegate. * [ADD] Added "changesSave" attribute to save release information to. No longer saving those information to "changesIn". ## Version 0.4, released 20.09.2007 * [FIX] Fixed mapper support. * [CHG] Changed lookup from environment (DEBEMAIL, DEBFULLNAME) to overrule the descriptor. * [REM] Removed deprecated prefix/strip syntax. * [ADD] Added support for multiple mappers. * [ADD] Added more fields to the package descriptor. ## Version 0.3, released 15.09.2007 * [ADD] Added maintainer lookup from environment (DEBEMAIL, DEBFULLNAME). * [ADD] Added plugin implementation for maven. * [ADD] Added stricter descriptor validation. ## Version 0.2, released 21.08.2007 * [FIX] Fixed the delete of the temporary files. * [ADD] Added support for signed changes files. * [ADD] Added support for mapping ownerships and rights. ## Version 0.1, released 19.02.2007 Initial release. jdeb/LICENSE.txt0000644000175000017500000002613512207644255013503 0ustar moellermoeller Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. jdeb/NOTICE.md0000644000175000017500000000024512207644255013155 0ustar moellermoellerThe jdeb project is under a joint copyright of the developers listed in the pom.xml file. Thanks to all the contributors listed for their patches and contributions. jdeb/README.md0000644000175000017500000000314612207644255013134 0ustar moellermoeller[![Build Status](https://secure.travis-ci.org/tcurdt/jdeb.png)](http://travis-ci.org/tcurdt/jdeb) # Debian packages in Java 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. 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. ## 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). git clone git://github.com/tcurdt/jdeb.git ## Related projects Some links to other cross platform tools to package Linux applications: * [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) jdeb/TODO.md0000644000175000017500000000006012207644255012734 0ustar moellermoellerplease see https://github.com/tcurdt/jdeb/issuesjdeb/contrib/0000755000175000017500000000000012207644255013311 5ustar moellermoellerjdeb/contrib/eclipse-formatting-profile.xml0000644000175000017500000007251112207644255021273 0ustar moellermoeller jdeb/contrib/maven_scanpackages.sh0000644000175000017500000000656512207644255017472 0ustar moellermoeller#!/bin/bash ############################################################################### # # Update debian repository indexes. # # It actually makes maven repositories expose a debian index. # # It also create a "virtual" stable debian repository in which is selected only # stable releases (filter milestonnes and release candidates). # # Requirements: # * This script is based on dpkg-scanpackages. It is provided by dpkg-dev package. # * The script expect to find (configurable) # ** a "releases" folder containing a maven repository with the deployed # releases # ** a "snapshots" folder containing a maven repository with the deployed # snaphots # ** make sure the "stable" folder exists if you want a filtered stable debian # repository # # Setup: # You need to set the $ROOT_REP variable to where your maven repositories are # located. # ############################################################################### ROOT_REP=/home/maven/public_html SNAPSHOTS_REP="snapshots" RELEASES_REP="releases" STABLE_REP="stable" cd "$ROOT_REP" ## snapshots if [ -d $SNAPSHOTS_REP ]; then echo "Generates snapshots index" dpkg-scanpackages -m $SNAPSHOTS_REP /dev/null > $SNAPSHOTS_REP/Packages.tmp && mv -f $SNAPSHOTS_REP/Packages.tmp $SNAPSHOTS_REP/Packages gzip -9c $SNAPSHOTS_REP/Packages > $SNAPSHOTS_REP/Packages.gz.tmp && mv -f $SNAPSHOTS_REP/Packages.gz.tmp $SNAPSHOTS_REP/Packages.gz rm -rf $SNAPSHOTS_REP/Release $SNAPSHOTS_REP/Release.gpg apt-ftparchive -c=$SNAPSHOTS_REP/Release.conf release $SNAPSHOTS_REP > $SNAPSHOTS_REP/Release gpg -abs --default-key 0398E391 -o $SNAPSHOTS_REP/Release.gpg $SNAPSHOTS_REP/Release fi ## releases if [ -d $RELEASES_REP ]; then echo "Generates releases index" dpkg-scanpackages -m $RELEASES_REP /dev/null > $RELEASES_REP/Packages.tmp && mv -f $RELEASES_REP/Packages.tmp $RELEASES_REP/Packages gzip -9c $RELEASES_REP/Packages > $RELEASES_REP/Packages.gz.tmp && mv -f $RELEASES_REP/Packages.gz.tmp $RELEASES_REP/Packages.gz rm -rf $RELEASES_REP/Release $RELEASES_REP/Release.gpg apt-ftparchive -c=$RELEASES_REP/Release.conf release $RELEASES_REP > $RELEASES_REP/Release gpg -abs --default-key 0398E391 -o $RELEASES_REP/Release.gpg $RELEASES_REP/Release fi ## stable if [ -d stable ]; then echo "Generates stable index" rm -rf /tmp/stable_scanpackages mkdir -p /tmp/stable_scanpackages/$RELEASES_REP function link_package () { basepath=`dirname $1` basepath=${basepath##$ROOT_REP/} basepath=${basepath%*/} mkdir -p $basepath fullpath=`readlink -f $1` ln -sf $fullpath "/tmp/stable_scanpackages/$basepath" } cd /tmp/stable_scanpackages/ for i in $(find "$ROOT_REP/$RELEASES_REP" -name "*.[0-9][0-9].deb" ) ; do link_package $i done for i in $(find "$ROOT_REP/$RELEASES_REP" -name "*.[0-9].deb" ) ; do link_package $i done dpkg-scanpackages -m $RELEASES_REP /dev/null > "$ROOT_REP/$STABLE_REP/Packages.tmp" && mv -f "$ROOT_REP/$STABLE_REP/Packages.tmp" "$ROOT_REP/$STABLE_REP/Packages" gzip -9c "$ROOT_REP/$STABLE_REP/Packages" > "$ROOT_REP/$STABLE_REP/Packages.gz.tmp" && mv -f "$ROOT_REP/$STABLE_REP/Packages.gz.tmp" "$ROOT_REP/$STABLE_REP/Packages.gz" cd "$ROOT_REP" rm -rf $STABLE_REP/Release $STABLE_REP/Release.gpg apt-ftparchive -c=$STABLE_REP/Release.conf release $STABLE_REP > $STABLE_REP/Release gpg -abs --default-key 0398E391 -o $STABLE_REP/Release.gpg $STABLE_REP/Release fi jdeb/docs/0000755000175000017500000000000012207644255012601 5ustar moellermoellerjdeb/docs/ant.md0000644000175000017500000001577712207644255013726 0ustar moellermoeller# How to use jdeb with Ant Attribute | Description | Required ------------- | ---------------------------------------------------------------------------- | -------------------------- destfile | The debian package to be generated | Yes control | The directory containing the control files | Yes compression | Compression method for the data file (`gzip`, `bzip2`, `xz` or `none`) | No; defaults to `gzip` verbose | Print detailed info during the package generation | No; defaults to `false` 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 changesIn | The changes to add | No changesOut | The changes file generated | No changesSave | The merged changes file | No The jdeb Ant task can package up a directory as Debian package. You have to provide the control files defining meta information about the package (except the `md5sums` which gets created automatically). It creates the archive and if you want even a signed changes file. ```xml ``` For cross platform builds it might be important to retain permissions, ownerships and links. When you provide the original tar as input the meta data will be kept intact gets included directly into the deb. You can apply simple modifications like prefixing or stripping of paths though. ```xml ``` For more complex permission and ownership adjustments you can use a "ls" mapper. It allows you to define permissions and ownerships in a text file and even under Windows you will be able to build your debian package. ```xml ``` The mapper will apply the output of an "ls -laR > mapping.txt" command that should look like this ./trunk/target/test-classes/org/vafer/dependency: total 176 drwxr-xr-x 23 tcurdt tcurdt 782 Jun 25 03:48 . drwxr-xr-x 3 tcurdt tcurdt 102 Jun 25 03:48 .. -rw-r--r-- 1 tcurdt tcurdt 2934 Jun 25 03:48 DependenciesTestCase.class -rw-r--r-- 1 tcurdt tcurdt 2176 Jun 25 03:48 WarTestCase.class drwxr-xr-x 4 tcurdt tcurdt 136 Jun 25 03:48 classes It's also possible to use a `fileset` or even a `tarfileset` to specify the set of files to include with their permissions : ```xml ``` Links can be added by specifying a `link` element: ```xml ``` Here are the supported attributes on the `link` element: Attribute | Description | Required ------------- | ------------------------------------------------------ | ----------------------- name | The path of the link | Yes target | The target of the link | Yes symbolic | The type of the link (`true`: symbolic, `false`: hard) | No; defaults to `true` uid | Numerical uid | No; defaults to 0 gid | Numerical gid | No; defaults to 0 user | User name | No; defaults to "root" group | User group | No; defaults to "root" mode | Permissions as octet | No; deftauls to 777 ## Changes file In order to also create a changes file you will need to provide the input and output of the changes. The input file is a much simpler file where you should list your changes. Every change should be starting with the " * " and one line only. * changes for the next release release distribution=staging, date=20:13 17.08.2007,version=1.4+r89114,urgency=low,by=Torsten Curdt * debian changes support When you do a release jdeb will add (or complete!) the release line and create a debian format standard changes file for you. (Don't forget to commit changes jdeb did to the file.) From Ant you have to call jdeb like this ```xml ``` If you also provide a `changesSave` attribute the jdeb will add release information to the original input and write out the new file. ```xml ``` ## Signing changes To have the changes be signed, make sure you have the [BouncyCastle OpenPGP/BCPG jar](http://www.bouncycastle.org/latest_releases.html) in your classpath (just copy it into the `$ANT_HOME/lib` folder - next to jdeb). Then you can sign your changes file with: ```xml ``` Security Note: Hard coding the passphrase in the `` task can be a serious security hole. Consider using variable substitution and asking the passphrase to the user with the `` task, or retrieving it from a secured `.properties` file. jdeb/docs/maven.md0000644000175000017500000002467312207644255014245 0ustar moellermoeller# How to use jdeb with Maven Generating a default Debian package with maven is particular easy. Just add the plugin to your POM like this ```xml jdeb org.vafer 1.0 package jdeb ${project.build.directory}/${project.build.finalName}.jar file perm /usr/share/jdeb/lib ``` 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 Package: [[name]] Version: [[version]] Section: misc Priority: optional Architecture: all Depends: jdk (>= 1.5) Maintainer: Torsten Curdt Description: jetty java servlet container Distribution: development If the environment variables `DEBEMAIL` and `DEBFULLNAME` are both set this will overrule the `Maintainer` field set in there. The `Installed-Size` will also be injected. If a changes file is used, the `Distribution` usually comes from that file. The default changes file is called `CHANGES.txt`. See below for the syntax of the content of the changes file. Property replacement will also occur in any of the standard debian control files: conffiles, preinst, postinst, prerm, postrm. This allows dynamic configuration of the form: /etc/[[artifactId]]/[[artifactId]].properties /etc/[[artifactId]]/log4j.xml If you now do a `mvn clean install`, the `deb` goal will be called and artifacts consisting of the deb and potentially the changes file will automatically be attached to the project. The jdeb maven plugin also supports a variety of configuration options. These configuration options provide the same features available in the jdeb ant task. To configure the jdeb maven plugin, populate the jdeb configuration section with any of the following options: Element | Description | Required ------------- | ---------------------------------------------------------------------------- | ----------------------------------------------------------------- deb | The debian package to be generated | No; defaults to `${buildDirectory}/${artifactId}_${version}.deb` type | Artifact type | No; defaults to `deb` classifier | Artifact classifier | No; defaults to '' controlDir | The directory containing the control files | No; defaults to `src/deb/control` installDir | The default directory for the project artifact if no data section is present | No; defaults to `/opt/${artifactId}` dataSet | A list of directories, tarballs, or files to include in the deb package | No; defaults to include your maven artifact changesIn | The changes to add | No 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 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` verbose | Verbose logging | No; defaults to `true`, will be `false` in the future 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 tarball archive, or a file. You can add as many data elements to your dataSet as you'd like. The `data` element has the following options: Element | Description | Required ---------------- | ---------------------------------------------------------------------------- | ------------------------------------ src | The directory, tarball, file to include in the package | Yes 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 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 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` There are different kinds of mappers that can be selected via the `type` argument. The most common one is the 'perm' mapper. Element | Description | Required ------------- | ----------------------------------------------------- | ----------------------- type | 'perm' | Yes prefix | Add this prefix to the files | No; defaults to "" uid | Numerical uid | No; defaults to 0 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 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: ```xml jdeb org.vafer 1.0 package jdeb ${project.basedir}/target/my_archive.tar.gz archive ... ... perm 1 /somewhere/else tcurdt tcurdt 600 ${project.build.directory}/data directory **/.svn ls mapping.txt ${project.basedir}/README.txt README file ignore template /etc/${artifactId} /var/lib/${artifactId} /var/log/${artifactId} /var/run/${artifactId} link /a/path/on/the/target/fs /a/link/to/the/scr/file false link /a/path/on/the/target/fs /a/sym/link/to/the/scr/file true ``` jdeb/src/0000755000175000017500000000000012207644255012440 5ustar moellermoellerjdeb/src/examples/0000755000175000017500000000000012207644255014256 5ustar moellermoellerjdeb/src/examples/ant/0000755000175000017500000000000012207644255015040 5ustar moellermoellerjdeb/src/examples/ant/build.xml0000644000175000017500000000305512207644255016664 0ustar moellermoeller jdeb/src/examples/ant/src/0000755000175000017500000000000012207644255015627 5ustar moellermoellerjdeb/src/examples/ant/src/deb/0000755000175000017500000000000012207644255016361 5ustar moellermoellerjdeb/src/examples/ant/src/deb/control/0000755000175000017500000000000012207644255020041 5ustar moellermoellerjdeb/src/examples/ant/src/deb/control/control0000644000175000017500000000021712207644255021444 0ustar moellermoellerPackage: [[name]] Version: [[version]] Section: misc Priority: low Architecture: all Description: [[description]] Maintainer: tcurdt@vafer.org jdeb/src/examples/ant/src/main/0000755000175000017500000000000012207644255016553 5ustar moellermoellerjdeb/src/examples/ant/src/main/java/0000755000175000017500000000000012207644255017474 5ustar moellermoellerjdeb/src/examples/ant/src/main/java/org/0000755000175000017500000000000012207644255020263 5ustar moellermoellerjdeb/src/examples/ant/src/main/java/org/vafer/0000755000175000017500000000000012207644255021366 5ustar moellermoellerjdeb/src/examples/ant/src/main/java/org/vafer/jdeb/0000755000175000017500000000000012207644255022272 5ustar moellermoellerjdeb/src/examples/ant/src/main/java/org/vafer/jdeb/examples/0000755000175000017500000000000012207644255024110 5ustar moellermoellerjdeb/src/examples/ant/src/main/java/org/vafer/jdeb/examples/Main.java0000644000175000017500000000023412207644255025636 0ustar moellermoellerpackage org.vafer.jdeb.examples; public class Main { public static void main(String[] args) { System.out.println("jdeb example!"); } } jdeb/src/examples/maven/0000755000175000017500000000000012207644255015364 5ustar moellermoellerjdeb/src/examples/maven/CHANGES.txt0000644000175000017500000000021512207644255017173 0ustar moellermoellerrelease date=20:13 15.12.2011,version=0.9,urgency=low,by=Torsten Curdt ,distribution=unknown * lots of fixes here jdeb/src/examples/maven/pom.xml0000644000175000017500000000717112207644255016707 0ustar moellermoeller 4.0.0 org.vafer jdeb-example 1.0 description from pom UTF-8 UTF-8 jdeb org.vafer 1.0 package jdeb true ${basedir}/src/deb/control ${project.build.directory}/${project.build.finalName}.jar file perm /usr/share/jdeb/lib loader loader link true /usr/share/java/jdeb.jar /usr/share/jdeb/lib/${project.build.finalName}.jar ${basedir}/src/deb/init.d directory perm /etc/init.d loader loader template etc/${project.artifactId} var/lib/${project.artifactId} var/log/${project.artifactId} var/run/${project.artifactId} perm loader loader jdeb/src/examples/maven/src/0000755000175000017500000000000012207644255016153 5ustar moellermoellerjdeb/src/examples/maven/src/deb/0000755000175000017500000000000012207644255016705 5ustar moellermoellerjdeb/src/examples/maven/src/deb/control/0000755000175000017500000000000012207644255020365 5ustar moellermoellerjdeb/src/examples/maven/src/deb/control/control0000644000175000017500000000021712207644255021770 0ustar moellermoellerPackage: [[name]] Version: [[version]] Section: misc Priority: low Architecture: all Description: [[description]] Maintainer: tcurdt@vafer.org jdeb/src/examples/maven/src/deb/control/postinst0000644000175000017500000000001212207644255022164 0ustar moellermoeller#!/bin/sh jdeb/src/examples/maven/src/deb/control/postrm0000644000175000017500000000001212207644255021625 0ustar moellermoeller#!/bin/sh jdeb/src/examples/maven/src/deb/control/preinst0000644000175000017500000000001212207644255021765 0ustar moellermoeller#!/bin/sh jdeb/src/examples/maven/src/deb/control/prerm0000644000175000017500000000001212207644255021426 0ustar moellermoeller#!/bin/sh jdeb/src/examples/maven/src/deb/init.d/0000755000175000017500000000000012207644255020072 5ustar moellermoellerjdeb/src/examples/maven/src/deb/init.d/myservice0000644000175000017500000000000012207644255022011 0ustar moellermoellerjdeb/src/examples/maven/src/main/0000755000175000017500000000000012207644255017077 5ustar moellermoellerjdeb/src/examples/maven/src/main/java/0000755000175000017500000000000012207644255020020 5ustar moellermoellerjdeb/src/examples/maven/src/main/java/org/0000755000175000017500000000000012207644255020607 5ustar moellermoellerjdeb/src/examples/maven/src/main/java/org/vafer/0000755000175000017500000000000012207644255021712 5ustar moellermoellerjdeb/src/examples/maven/src/main/java/org/vafer/jdeb/0000755000175000017500000000000012207644255022616 5ustar moellermoellerjdeb/src/examples/maven/src/main/java/org/vafer/jdeb/examples/0000755000175000017500000000000012207644255024434 5ustar moellermoellerjdeb/src/examples/maven/src/main/java/org/vafer/jdeb/examples/Main.java0000644000175000017500000000023012207644255026156 0ustar moellermoellerpackage org.vafer.jdeb.examples; public class Main { public static void main(String[] args) { System.out.println("jdeb example!"); } } jdeb/src/it/0000755000175000017500000000000012207644255013054 5ustar moellermoellerjdeb/src/it/no-datasets/0000755000175000017500000000000012207644255015276 5ustar moellermoellerjdeb/src/it/no-datasets/pom.xml0000644000175000017500000000254112207644255016615 0ustar moellermoeller 4.0.0 org.vafer jdeb-it 1.0 description from pom UTF-8 UTF-8 org.vafer jdeb @project.version@ package jdeb true ${basedir}/src/deb/control jdeb/src/it/no-datasets/src/0000755000175000017500000000000012207644255016065 5ustar moellermoellerjdeb/src/it/no-datasets/src/deb/0000755000175000017500000000000012207644255016617 5ustar moellermoellerjdeb/src/it/no-datasets/src/deb/control/0000755000175000017500000000000012207644255020277 5ustar moellermoellerjdeb/src/it/no-datasets/src/deb/control/control0000644000175000017500000000021712207644255021702 0ustar moellermoellerPackage: [[name]] Version: [[version]] Section: misc Priority: low Architecture: all Description: [[description]] Maintainer: tcurdt@vafer.org jdeb/src/it/no-datasets/src/main/0000755000175000017500000000000012207644255017011 5ustar moellermoellerjdeb/src/it/no-datasets/src/main/java/0000755000175000017500000000000012207644255017732 5ustar moellermoellerjdeb/src/it/no-datasets/src/main/java/org/0000755000175000017500000000000012207644255020521 5ustar moellermoellerjdeb/src/it/no-datasets/src/main/java/org/vafer/0000755000175000017500000000000012207644255021624 5ustar moellermoellerjdeb/src/it/no-datasets/src/main/java/org/vafer/jdeb/0000755000175000017500000000000012207644255022530 5ustar moellermoellerjdeb/src/it/no-datasets/src/main/java/org/vafer/jdeb/examples/0000755000175000017500000000000012207644255024346 5ustar moellermoellerjdeb/src/it/no-datasets/src/main/java/org/vafer/jdeb/examples/Main.java0000644000175000017500000000023412207644255026074 0ustar moellermoellerpackage org.vafer.jdeb.examples; public class Main { public static void main(String[] args) { System.out.println("jdeb example!"); } } jdeb/src/it/no-datasets/verify.groovy0000644000175000017500000000010312207644255020043 0ustar moellermoellerassert new File( basedir, 'target/jdeb-it_1.0_all.deb' ).exists(); jdeb/src/it/pom-only/0000755000175000017500000000000012207644255014626 5ustar moellermoellerjdeb/src/it/pom-only/pom.xml0000644000175000017500000000260012207644255016141 0ustar moellermoeller 4.0.0 org.vafer jdeb-it 1.0 pom description from pom UTF-8 UTF-8 org.vafer jdeb @project.version@ package jdeb true ${basedir}/src/deb/control jdeb/src/it/pom-only/src/0000755000175000017500000000000012207644255015415 5ustar moellermoellerjdeb/src/it/pom-only/src/deb/0000755000175000017500000000000012207644255016147 5ustar moellermoellerjdeb/src/it/pom-only/src/deb/control/0000755000175000017500000000000012207644255017627 5ustar moellermoellerjdeb/src/it/pom-only/src/deb/control/control0000644000175000017500000000021712207644255021232 0ustar moellermoellerPackage: [[name]] Version: [[version]] Section: misc Priority: low Architecture: all Description: [[description]] Maintainer: tcurdt@vafer.org jdeb/src/it/pom-only/verify.groovy0000644000175000017500000000010312207644255017373 0ustar moellermoellerassert new File( basedir, 'target/jdeb-it_1.0_all.deb' ).exists(); jdeb/src/it/settings.xml0000644000175000017500000000220412207644255015434 0ustar moellermoeller it-repo true local.central @localRepositoryUrl@ true true local.central @localRepositoryUrl@ true true jdeb/src/main/0000755000175000017500000000000012207644255013364 5ustar moellermoellerjdeb/src/main/java/0000755000175000017500000000000012207644255014305 5ustar moellermoellerjdeb/src/main/java/org/0000755000175000017500000000000012207644255015074 5ustar moellermoellerjdeb/src/main/java/org/vafer/0000755000175000017500000000000012207644255016177 5ustar moellermoellerjdeb/src/main/java/org/vafer/jdeb/0000755000175000017500000000000012207644255017103 5ustar moellermoellerjdeb/src/main/java/org/vafer/jdeb/ChangesFileBuilder.java0000644000175000017500000000721412207644255023431 0ustar moellermoeller/* * 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; } } jdeb/src/main/java/org/vafer/jdeb/Compression.java0000644000175000017500000000503612207644255022253 0ustar moellermoeller/* * 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; } } } jdeb/src/main/java/org/vafer/jdeb/Console.java0000644000175000017500000000143512207644255021353 0ustar moellermoeller/* * 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; /** * Plug in your favorite log implementation. * * @author Torsten Curdt */ public interface Console { void info( String s ); void warn( String s ); } jdeb/src/main/java/org/vafer/jdeb/ControlBuilder.java0000644000175000017500000002141412207644255022677 0ustar moellermoeller/* * 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 MAINTAINER_SCRIPTS = new HashSet(Arrays.asList("preinst", "postinst", "prerm", "postrm", "config")); /** The name of the other control files subject to token substitution */ private static final Set CONFIGURATION_FILENAMES = new HashSet(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 * Date, Distribution and Urgency fields if missing. * The Installed-Size field is also initialized to the actual size of * the package. The Maintainer field is overridden by the DEBEMAIL * and DEBFULLNAME 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; } } jdeb/src/main/java/org/vafer/jdeb/DataBuilder.java0000644000175000017500000003176412207644255022141 0ustar moellermoeller/* * 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 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 addedDirectories = new ArrayList(); 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; } } jdeb/src/main/java/org/vafer/jdeb/DataConsumer.java0000644000175000017500000000235712207644255022342 0ustar moellermoeller/* * 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; import java.io.InputStream; /** * A DataConsumer consumes Data produced from a producer. * * @author Torsten Curdt */ 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; } jdeb/src/main/java/org/vafer/jdeb/DataProducer.java0000644000175000017500000000147512207644255022332 0ustar moellermoeller/* * 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; /** * Provides Data to a DataConsumer. * * @author Torsten Curdt */ public interface DataProducer { void produce( DataConsumer receiver ) throws IOException; } jdeb/src/main/java/org/vafer/jdeb/DebMaker.java0000644000175000017500000003271512207644255021430 0ustar moellermoeller/* * 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.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import org.apache.commons.compress.archivers.ar.ArArchiveEntry; import org.apache.commons.compress.archivers.ar.ArArchiveOutputStream; import org.apache.commons.io.IOUtils; 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.Utils; import org.vafer.jdeb.utils.VariableResolver; /** * A generic class for creating Debian archives. Even supports signed changes * files. * * @author Torsten Curdt * @author Bryan Sant */ public class DebMaker { /** A console to output log message with */ private Console console; /** The Debian package produced */ private File deb; /** The directory containing the control files to build the package */ private File control; /** The name of the package. Default value if not specified in the control file */ private String packageName; /** The section of the package. Default value if not specified in the control file */ private String section = "java"; /** The dependencies of the package. Default value if not specified in the control file */ private String depends = "default-jre | java6-runtime"; /** The description of the package. Default value if not specified in the control file */ private String description; /** The homepage of the application. Default value if not specified in the control file */ private String homepage; /** The file containing the PGP keys */ private File keyring; /** The key to use in the keyring */ private String key; /** The passphrase for the key to sign the changes file */ private String passphrase; /** The file to read the changes from */ private File changesIn; /** The file where to write the changes to */ private File changesOut; /** The file where to write the changes of the changes input to */ private File changesSave; /** The compression method used for the data file (none, gzip, bzip2 or xz) */ private String compression = "gzip"; private VariableResolver variableResolver; private final Collection dataProducers = new ArrayList(); public DebMaker(Console console, Collection dataProducers) { this.console = console; this.dataProducers.addAll(dataProducers); } public void setDeb(File deb) { this.deb = deb; } public void setControl(File control) { this.control = control; } public void setPackage(String packageName) { this.packageName = packageName; } public void setSection(String section) { this.section = section; } public void setDepends(String depends) { this.depends = depends; } public void setDescription(String description) { this.description = description; } public void setHomepage(String homepage) { this.homepage = homepage; } public void setChangesIn(File changes) { this.changesIn = changes; } public void setChangesOut(File changes) { this.changesOut = changes; } public void setChangesSave(File changes) { this.changesSave = changes; } public void setKeyring(File keyring) { this.keyring = keyring; } public void setKey(String key) { this.key = key; } public void setPassphrase(String passphrase) { this.passphrase = passphrase; } public void setCompression(String compression) { this.compression = compression; } public void setResolver(VariableResolver variableResolver) { this.variableResolver = variableResolver; } private boolean isWritableFile(File file) { return !file.exists() || file.isFile() && file.canWrite(); } /** * Validates the input parameters. */ public void validate() throws PackagingException { if (control == null || !control.isDirectory()) { throw new PackagingException("The 'control' attribute doesn't point to a directory."); } if (changesIn != null) { 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); } if (changesSave != null && !isWritableFile(changesSave)) { throw new PackagingException("Cannot write the output for 'changesSave' to " + changesSave); } } else { if (changesOut != null || changesSave != null) { throw new PackagingException("The 'changesOut' or 'changesSave' settings may only be used when there is a 'changesIn' specified."); } } if (Compression.toEnum(compression) == null) { throw new PackagingException("The compression method '" + compression + "' is not supported (expected 'none', 'gzip', 'bzip2' or 'xz')"); } 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 { BinaryPackageControlFile packageControlFile; try { console.info("Creating debian package: " + deb); packageControlFile = createDeb(Compression.toEnum(compression)); } catch (Exception e) { throw new PackagingException("Failed to create debian package " + deb, e); } makeChangesFiles(packageControlFile); } private void makeChangesFiles(final BinaryPackageControlFile packageControlFile) throws PackagingException { 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); } else { // create an empty changelog changesProvider = new ChangesProvider() { @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]) }; } }; } 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); signer.clearSign(changesFile.toString(), out); } else { out.write(changesFile.toString().getBytes("UTF-8")); } out.flush(); } catch (Exception e) { throw new PackagingException("Failed to create the Debian changes file " + changesOut, e); } finally { IOUtils.closeQuietly(out); } if (changesSave == null || !(changesProvider instanceof TextfileChangesProvider)) { return; } try { console.info("Saving changes to file: " + changesSave); ((TextfileChangesProvider) changesProvider).save(new FileOutputStream(changesSave)); } catch (Exception e) { throw new PackagingException("Failed to save debian changes file " + changesSave, e); } } /** * Create the debian archive with from the provided control files and data producers. * * @param pControlFiles * @param pData * @param deb * @param compression the compression method used for the data file * @return BinaryPackageControlFile * @throws PackagingException */ public BinaryPackageControlFile createDeb(Compression compression) throws PackagingException { File tempData = null; File tempControl = null; try { tempData = File.createTempFile("deb", "data"); tempControl = File.createTempFile("deb", "control"); console.info("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); BinaryPackageControlFile packageControlFile = controlBuilder.createPackageControlFile(new File(control, "control"), size); if (packageControlFile.get("Package") == null) { packageControlFile.set("Package", packageName); } if (packageControlFile.get("Depends") == null) { packageControlFile.set("Depends", depends); } if (packageControlFile.get("Section") == null) { packageControlFile.set("Section", section); } if (packageControlFile.get("Description") == null) { packageControlFile.set("Description", description); } if (packageControlFile.get("Homepage") == null) { packageControlFile.set("Homepage", homepage); } controlBuilder.buildControl(packageControlFile, control.listFiles(), 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."); } 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); ar.close(); return packageControlFile; } catch (Exception e) { throw new PackagingException("Could not create deb package", e); } finally { if (tempData != null) { if (!tempData.delete()) { console.warn("Could not delete the temporary file " + tempData); } } if (tempControl != null) { if (!tempControl.delete()) { console.warn("Could not delete the temporary file " + tempControl); } } } } private void addTo(ArArchiveOutputStream pOutput, String pName, String pContent) throws IOException { final byte[] content = pContent.getBytes(); pOutput.putArchiveEntry(new ArArchiveEntry(pName, content.length)); pOutput.write(content); pOutput.closeArchiveEntry(); } private void addTo(ArArchiveOutputStream pOutput, String pName, File pContent) throws IOException { pOutput.putArchiveEntry(new ArArchiveEntry(pName, pContent.length())); final InputStream input = new FileInputStream(pContent); try { Utils.copy(input, pOutput); } finally { input.close(); } pOutput.closeArchiveEntry(); } } jdeb/src/main/java/org/vafer/jdeb/PackagingException.java0000644000175000017500000000220412207644255023507 0ustar moellermoeller/* * 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; /** * Something went wrong while building the package * * @author Torsten Curdt */ public final class PackagingException extends Exception { private static final long serialVersionUID = 1L; public PackagingException() { super(); } public PackagingException( String message, Throwable cause ) { super(message, cause); } public PackagingException( String message ) { super(message); } public PackagingException( Throwable cause ) { super(cause); } } jdeb/src/main/java/org/vafer/jdeb/ant/0000755000175000017500000000000012207644255017665 5ustar moellermoellerjdeb/src/main/java/org/vafer/jdeb/ant/Data.java0000644000175000017500000000627412207644255021412 0ustar moellermoeller/* * 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 java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import org.apache.tools.ant.types.PatternSet; 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; /** * Ant "data" element acting as a factory for DataProducers. * So far Archive and Directory producers are supported. * Both support the usual ant pattern set matching. * * @author Torsten Curdt */ public final class Data extends PatternSet implements DataProducer { private final Collection mapperWrapper = new ArrayList(); private File src; private String type; private String destinationName; public void setSrc(File src) { this.src = src; } public String getType() { return type; } public void setType(String type) { this.type = type; } public void setDst(String destinationName) { this.destinationName = destinationName; } public void addMapper(Mapper mapper) { mapperWrapper.add(mapper); } public void produce( final DataConsumer pReceiver ) throws IOException { if (src == null || !src.exists()) { throw new FileNotFoundException("Data source not found : " + src); } org.vafer.jdeb.mapping.Mapper[] mappers = new org.vafer.jdeb.mapping.Mapper[mapperWrapper.size()]; final Iterator it = mapperWrapper.iterator(); for (int i = 0; i < mappers.length; i++) { mappers[i] = it.next().createMapper(); } if ("file".equalsIgnoreCase(type)) { new DataProducerFile( src, destinationName, getIncludePatterns(getProject()), getExcludePatterns(getProject()), mappers ).produce(pReceiver); } else if ("archive".equalsIgnoreCase(type)) { new DataProducerArchive( src, getIncludePatterns(getProject()), getExcludePatterns(getProject()), mappers ).produce(pReceiver); } else if ("directory".equalsIgnoreCase(type)) { new DataProducerDirectory( src, getIncludePatterns(getProject()), getExcludePatterns(getProject()), mappers ).produce(pReceiver); } } } jdeb/src/main/java/org/vafer/jdeb/ant/DebAntTask.java0000644000175000017500000001223012207644255022506 0ustar moellermoeller/* * 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 java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.taskdefs.MatchingTask; import org.apache.tools.ant.taskdefs.Tar; import org.apache.tools.ant.types.FileSet; import org.vafer.jdeb.Console; import org.vafer.jdeb.DataProducer; import org.vafer.jdeb.DebMaker; import org.vafer.jdeb.PackagingException; import org.vafer.jdeb.producers.DataProducerFileSet; /** * AntTask for creating debian archives. * * @author Torsten Curdt */ public class DebAntTask extends MatchingTask { /** The Debian package produced */ private File deb; /** The directory containing the control files to build the package */ private File control; /** The file containing the PGP keys */ private File keyring; /** The key to use in the keyring */ private String key; /** The passphrase for the key to sign the changes file */ private String passphrase; /** The file to read the changes from */ private File changesIn; /** The file where to write the changes to */ private File changesOut; /** The file where to write the changes of the changes input to */ private File changesSave; /** The compression method used for the data file (none, gzip, bzip2 or xz) */ private String compression = "gzip"; /** Trigger the verbose mode detailing all operations */ private boolean verbose; private Collection links = new ArrayList(); private Collection dataProducers = new ArrayList(); public void setDestfile( File deb ) { this.deb = deb; } public void setControl( File control ) { this.control = control; } public void setChangesIn( File changes ) { this.changesIn = changes; } public void setChangesOut( File changes ) { this.changesOut = changes; } public void setChangesSave( File changes ) { this.changesSave = changes; } public void setKeyring( File keyring ) { this.keyring = keyring; } public void setKey( String key ) { this.key = key; } public void setPassphrase( String passphrase ) { this.passphrase = passphrase; } public void setCompression( String compression ) { this.compression = compression; } public void setVerbose( boolean verbose ) { this.verbose = verbose; } public void addFileSet( FileSet fileset ) { dataProducers.add(new DataProducerFileSet(fileset)); } public void addTarFileSet( Tar.TarFileSet fileset ) { dataProducers.add(new DataProducerFileSet(fileset)); } public void addData( Data data ) { dataProducers.add(data); } public void addLink( Link link ) { links.add(link); } public void execute() { // add the data producers for the links for (Link link : links) { dataProducers.add(link.toDataProducer()); } // validate the type of the elements for (DataProducer dataProducer : dataProducers) { if (dataProducer instanceof Data) { Data data = (Data) dataProducer; if (data.getType() == null) { throw new BuildException("The type of the data element wasn't specified (expected 'file', 'directory' or 'archive')"); } 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')"); } } } Console console = new TaskConsole(this, verbose); DebMaker debMaker = new DebMaker(console, dataProducers); debMaker.setDeb(deb); debMaker.setControl(control); debMaker.setChangesIn(changesIn); debMaker.setChangesOut(changesOut); debMaker.setChangesSave(changesSave); debMaker.setKeyring(keyring); debMaker.setKey(key); debMaker.setPassphrase(passphrase); debMaker.setCompression(compression); try { debMaker.validate(); debMaker.makeDeb(); } catch (PackagingException e) { log("Failed to create the Debian package " + deb, e, Project.MSG_ERR); throw new BuildException("Failed to create the Debian package " + deb, e); } } } jdeb/src/main/java/org/vafer/jdeb/ant/Link.java0000644000175000017500000000527012207644255021431 0ustar moellermoeller/* * 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); } } jdeb/src/main/java/org/vafer/jdeb/ant/Mapper.java0000644000175000017500000000500612207644255021755 0ustar moellermoeller/* * 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 java.io.File; import java.io.FileInputStream; import java.io.IOException; import org.vafer.jdeb.mapping.LsMapper; import org.vafer.jdeb.mapping.PermMapper; /** * Ant "mapper" element acting as factory for the entry mapper. * Supported types: ls, perm * * @author Torsten Curdt */ public final class Mapper { private String mapperType = "perm"; private File src; private String prefix; private int strip; private int uid = -1; private int gid = -1; private String user; private String group; private int fileMode = -1; private int dirMode = -1; public void setType( final String pType ) { mapperType = pType; } public void setSrc( final File pSrc ) { src = pSrc; } public void setPrefix( final String pPrefix ) { prefix = pPrefix; } public void setStrip( final int pStrip ) { strip = pStrip; } public void setUid( final int pUid ) { uid = pUid; } public void setGid( final int pGid ) { gid = pGid; } public void setUser( final String pUser ) { user = pUser; } public void setGroup( final String pGroup ) { group = pGroup; } public void setFileMode( final int pFileMode ) { fileMode = pFileMode; } public void setDirMode( int pDirMode ) { dirMode = pDirMode; } public org.vafer.jdeb.mapping.Mapper createMapper() throws IOException { if ("perm".equalsIgnoreCase(mapperType)) { return new PermMapper(uid, gid, user, group, fileMode, dirMode, strip, prefix); } if ("ls".equalsIgnoreCase(mapperType)) { try { return new LsMapper(new FileInputStream(src)); } catch (Exception e) { e.printStackTrace(); } } throw new IOException("Unknown mapper type '" + mapperType + "'"); } } jdeb/src/main/java/org/vafer/jdeb/ant/TaskConsole.java0000644000175000017500000000220612207644255022755 0ustar moellermoeller/* * 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.tools.ant.Task; import org.vafer.jdeb.Console; /** * Console implementation for Ant tasks. */ class TaskConsole implements Console { private final Task task; private final boolean verbose; public TaskConsole(Task task, boolean verbose) { this.task = task; this.verbose = verbose; } public void info(String message) { if (verbose) { task.log(message); } } public void warn(String message) { task.log(message); } } jdeb/src/main/java/org/vafer/jdeb/changes/0000755000175000017500000000000012207644255020513 5ustar moellermoellerjdeb/src/main/java/org/vafer/jdeb/changes/ChangeSet.java0000644000175000017500000000556012207644255023225 0ustar moellermoeller/* * 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.changes; import java.util.Date; /** * A ChangeSet basically reflect a release as defined in the changes file. * *
 * package (version) distribution(s); urgency=urgency
 *        [optional blank line(s), stripped]
 *   * change details
 *     more change details
 *        [blank line(s), included in output of dpkg-parsechangelog]
 *   * even more change details
 *        [optional blank line(s), stripped]
 *  -- maintainer name [two spaces]  date
 * 
* * @author Torsten Curdt * @see Debian Policy Manual - Debian changelog */ public final class ChangeSet { private final String packageName; private final String version; private final Date date; private final String distribution; private final String urgency; private final String changedBy; private final String[] changes; public ChangeSet(String packageName, String version, Date date, String distribution, String urgency, String changedBy, String[] changes) { this.packageName = packageName; this.version = version; this.date = date; this.distribution = distribution; this.urgency = urgency; this.changedBy = changedBy; this.changes = changes; } public String getPackage() { return packageName; } public String getVersion() { return version; } public Date getDate() { return date; } public String getDistribution() { return distribution; } public String getUrgency() { return urgency; } public String getChangedBy() { return changedBy; } public String[] getChanges() { return changes; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append(getTitle()).append('\n'); if (changes.length > 0) { sb.append("\n"); } for (String change : changes) { sb.append(" * ").append(change).append('\n'); } return sb.toString(); } private String getTitle() { return getPackage() + " (" + getVersion() + ") " + getDistribution() + "; urgency=" + getUrgency(); } } jdeb/src/main/java/org/vafer/jdeb/changes/ChangesProvider.java0000644000175000017500000000130712207644255024442 0ustar moellermoeller/* * 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.changes; public interface ChangesProvider { ChangeSet[] getChangesSets(); } jdeb/src/main/java/org/vafer/jdeb/changes/TextfileChangesProvider.java0000644000175000017500000001250212207644255026146 0ustar moellermoeller/* * 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.changes; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import org.vafer.jdeb.debian.BinaryPackageControlFile; /** * Gets the changes from a changes file. The first entry are the current changes. * The release line will be added. Example: * * release date=22:13 19.08.2007,version=1.5+r90114,urgency=low,by=Torsten Curdt * * debian changes support * release date=20:13 17.08.2007,version=1.4+r89114,urgency=low,by=Torsten Curdt * * debian changes support * * @author Torsten Curdt */ public final class TextfileChangesProvider implements ChangesProvider { private final ChangeSet[] changeSets; private DateFormat fmt = new SimpleDateFormat("HH:mm dd.MM.yyyy"); public TextfileChangesProvider( final InputStream pInput, final BinaryPackageControlFile packageControlFile ) throws IOException, ParseException { final BufferedReader reader = new BufferedReader(new InputStreamReader(pInput)); String packageName = packageControlFile.get("Package"); String version = packageControlFile.get("Version"); Date date = new Date(); String distribution = packageControlFile.get("Distribution"); String urgency = packageControlFile.get("Urgency"); String changedBy = packageControlFile.get("Maintainer"); Collection changesColl = new ArrayList(); Collection changeSetColl = new ArrayList(); while (true) { final String line = reader.readLine(); if (line == null) { final String[] changes = changesColl.toArray(new String[changesColl.size()]); final ChangeSet changeSet = new ChangeSet(packageName, version, date, distribution, urgency, changedBy, changes); changeSetColl.add(changeSet); break; } if (line.startsWith("release ")) { if (changesColl.size() > 0) { final String[] changes = changesColl.toArray(new String[changesColl.size()]); final ChangeSet changeSet = new ChangeSet(packageName, version, date, distribution, urgency, changedBy, changes); changeSetColl.add(changeSet); changesColl.clear(); } final String[] tokens = line.substring("release ".length()).split(","); for (String token : tokens) { final String[] lr = token.trim().split("="); final String key = lr[0]; final String value = lr[1]; if ("urgency".equals(key)) { urgency = value; } else if ("by".equals(key)) { changedBy = value; } else if ("date".equals(key)) { date = fmt.parse(value); } else if ("version".equals(key)) { version = value; } else if ("distribution".equals(key)) { distribution = value; } } continue; } if (line.startsWith(" * ")) { changesColl.add(line.substring(" * ".length())); continue; } throw new ParseException("Unknown line syntax [" + line + "]", 0); } reader.close(); changeSets = changeSetColl.toArray(new ChangeSet[changeSetColl.size()]); } public void save(OutputStream pOutput) throws IOException { BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(pOutput)); for (ChangeSet changeSet : changeSets) { writer.write("release "); writer.write("date=" + fmt.format(changeSet.getDate()) + ","); writer.write("version=" + changeSet.getVersion() + ","); writer.write("urgency=" + changeSet.getUrgency() + ","); writer.write("by=" + changeSet.getChangedBy() + ","); writer.write("distribution=" + changeSet.getDistribution()); writer.write("\n"); for (String change : changeSet.getChanges()) { writer.write(" * "); writer.write(change); writer.write("\n"); } } writer.close(); } public ChangeSet[] getChangesSets() { return changeSets; } } jdeb/src/main/java/org/vafer/jdeb/debian/0000755000175000017500000000000012207644255020325 5ustar moellermoellerjdeb/src/main/java/org/vafer/jdeb/debian/BinaryPackageControlFile.java0000644000175000017500000000536712207644255026044 0ustar moellermoeller/* * 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.IOException; import java.io.InputStream; import java.text.ParseException; /** * Binary package control file. * * @see Debian Policy Manual - Binary package control files * @author Torsten Curdt */ public final class BinaryPackageControlFile extends ControlFile { private static final ControlField[] FIELDS = { new ControlField("Package", true), new ControlField("Source"), new ControlField("Version", true), new ControlField("Section", true), new ControlField("Priority", true), new ControlField("Architecture", true), new ControlField("Essential"), new ControlField("Depends"), new ControlField("Pre-Depends"), new ControlField("Recommends"), new ControlField("Suggests"), new ControlField("Breaks"), new ControlField("Enhances"), new ControlField("Conflicts"), new ControlField("Provides"), new ControlField("Replaces"), new ControlField("Installed-Size"), new ControlField("Maintainer", true), new ControlField("Description", true, ControlField.Type.MULTILINE), new ControlField("Homepage") }; public BinaryPackageControlFile() { set("Architecture", "all"); set("Priority", "optional"); } public BinaryPackageControlFile(String input) throws IOException, ParseException { parse(input); } public BinaryPackageControlFile(InputStream input) throws IOException, ParseException { parse(input); } @Override protected ControlField[] getFields() { return FIELDS; } /** * 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]; } } jdeb/src/main/java/org/vafer/jdeb/debian/ChangesFile.java0000644000175000017500000000747712207644255023357 0ustar moellermoeller/* * 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.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Locale; import org.vafer.jdeb.changes.ChangeSet; /** * Reflecting a changes file * * @see Debian Policy Manual - Debian changes files * @author Torsten Curdt */ 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), new ControlField("Source", true), new ControlField("Binary", true), new ControlField("Architecture", true), new ControlField("Version", true), new ControlField("Distribution", true), new ControlField("Urgency", true), new ControlField("Maintainer", true), new ControlField("Changed-By"), new ControlField("Description", true, ControlField.Type.MULTILINE, true), new ControlField("Changes", true, ControlField.Type.MULTILINE, true), new ControlField("Closes"), new ControlField("Checksums-Sha1", true, ControlField.Type.MULTILINE, true), new ControlField("Checksums-Sha256", true, ControlField.Type.MULTILINE, true), new ControlField("Files", true, ControlField.Type.MULTILINE, true) }; public ChangesFile() { set("Format", "1.8"); 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) { set("Binary", packageControlFile.get("Package")); set("Source", packageControlFile.get("Package")); set("Architecture", packageControlFile.get("Architecture")); set("Version", packageControlFile.get("Version")); set("Maintainer", packageControlFile.get("Maintainer")); set("Changed-By", packageControlFile.get("Maintainer")); StringBuilder description = new StringBuilder(); description.append(packageControlFile.get("Package")); if (packageControlFile.get("Description") != null) { description.append(" - "); description.append(packageControlFile.getShortDescription()); } set("Description", description.toString()); } public void setChanges(ChangeSet[] changeSets) { StringBuilder sb = new StringBuilder(); if (changeSets.length > 0) { final ChangeSet mostRecentChangeSet = changeSets[0]; set("Urgency", mostRecentChangeSet.getUrgency()); set("Changed-By", mostRecentChangeSet.getChangedBy()); for (ChangeSet changeSet : changeSets) { sb.append(changeSet.toString()); } } set("Changes", sb.toString()); } @Override protected ControlField[] getFields() { return FIELDS; } } jdeb/src/main/java/org/vafer/jdeb/debian/ControlField.java0000644000175000017500000000724312207644255023562 0ustar moellermoeller/* * 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. * *
     * Field-Name: value
     * 
*/ 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(); } } jdeb/src/main/java/org/vafer/jdeb/debian/ControlFile.java0000644000175000017500000001053012207644255023407 0ustar moellermoeller/* * 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.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.text.ParseException; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * A control file as specified by the Debian policy. * * @author Torsten Curdt */ public abstract class ControlFile { protected final Map values = new LinkedHashMap(); public void parse(String input) throws IOException, ParseException { parse(new ByteArrayInputStream(input.getBytes("UTF-8"))); } public void parse(InputStream input) throws IOException, ParseException { BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); StringBuilder buffer = new StringBuilder(); String field = null; int linenr = 0; while (true) { final String line = reader.readLine(); if (line == null) { if (buffer.length() > 0) { // flush value of the previous field set(field, buffer.toString()); } break; } linenr++; if (line.length() == 0) { throw new ParseException("Empty line", linenr); } final char first = line.charAt(0); if (Character.isLetter(first)) { // new field if (buffer.length() > 0) { // flush value of the previous field set(field, buffer.toString()); buffer = new StringBuilder(); } final int i = line.indexOf(':'); if (i < 0) { throw new ParseException("Line misses ':' delimiter", linenr); } field = line.substring(0, i); buffer.append(line.substring(i + 1).trim()); continue; } // continuing old value, lines with only a dot are ignored buffer.append('\n'); if (!".".equals(line.substring(1).trim())) { buffer.append(line.substring(1)); } } reader.close(); } public void set(final String field, final String value) { if (!"".equals(value)) { values.put(field, value); } } public String get(String field) { return values.get(field); } protected abstract ControlField[] getFields(); public List getMandatoryFields() { List fields = new ArrayList(); for (ControlField field : getFields()) { if (field.isMandatory()) { fields.add(field.getName()); } } return fields; } public boolean isValid() { return invalidFields().size() == 0; } public Set invalidFields() { Set invalid = new HashSet(); for (ControlField field : getFields()) { if (field.isMandatory() && get(field.getName()) == null) { invalid.add(field.getName()); } } return invalid; } public String toString(ControlField... fields) { StringBuilder s = new StringBuilder(); for (ControlField field : fields) { String value = values.get(field.getName()); s.append(field.format(value)); } return s.toString(); } public String toString() { return toString(getFields()); } } jdeb/src/main/java/org/vafer/jdeb/mapping/0000755000175000017500000000000012207644255020536 5ustar moellermoellerjdeb/src/main/java/org/vafer/jdeb/mapping/LsMapper.java0000644000175000017500000001743112207644255023132 0ustar moellermoeller/* * 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.mapping; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; /** * Reads permissions and ownerships from a "ls -laR > mapping.txt" dump and * maps entries accordingly. * * @author Torsten Curdt */ public final class LsMapper implements Mapper { private final Map mapping; public final static class ParseError extends Exception { private static final long serialVersionUID = 1L; public ParseError( String message ) { super(message); } } public LsMapper( final InputStream pInput ) throws IOException, ParseError { mapping = parse(pInput); } /* ./trunk/target/test-classes/org/vafer/dependency: total 176 drwxr-xr-x 23 tcurdt tcurdt 782 Jun 25 03:48 . drwxr-xr-x 3 tcurdt tcurdt 102 Jun 25 03:48 .. -rw-r--r-- 1 tcurdt tcurdt 2934 Jun 25 03:48 DependenciesTestCase.class -rw-r--r-- 1 tcurdt tcurdt 786 Jun 25 03:48 JarCombiningTestCase$1.class -rw-r--r-- 1 tcurdt tcurdt 2176 Jun 25 03:48 WarTestCase.class drwxr-xr-x 4 tcurdt tcurdt 136 Jun 25 03:48 classes ./trunk/target/test-classes/org/vafer/dependency/classes: */ final private Pattern basePattern = Pattern.compile("^\\./(.*):$"); final private Pattern totalPattern = Pattern.compile("^total ([0-9]+)$"); final private Pattern dirPattern = Pattern.compile("^d([rwx-]{9})\\s+([0-9]+)\\s+(\\S*)\\s+(\\S*)\\s+([0-9]+)\\s+(.*)\\s+[\\.]{1,2}$"); final private Pattern filePattern = Pattern.compile("^([d-])([rwx-]{9})\\s+([0-9]+)\\s+(\\S*)\\s+(\\S*)\\s+([0-9]+)\\s+(.*)\\s+(.*)$"); final private Pattern newlinePattern = Pattern.compile("$"); private String readBase( final BufferedReader reader ) throws IOException, ParseError { final String line = reader.readLine(); if (line == null) { return null; } final Matcher matcher = basePattern.matcher(line); if (!matcher.matches()) { throw new ParseError("expected base line but got \"" + line + "\""); } return matcher.group(1); } private String readTotal( final BufferedReader reader ) throws IOException, ParseError { final String line = reader.readLine(); final Matcher matcher = totalPattern.matcher(line); if (!matcher.matches()) { throw new ParseError("expected total line but got \"" + line + "\""); } return matcher.group(1); } private TarArchiveEntry readDir( final BufferedReader reader, final String base ) throws IOException, ParseError { final String current = reader.readLine(); final Matcher currentMatcher = dirPattern.matcher(current); if (!currentMatcher.matches()) { throw new ParseError("expected dirline but got \"" + current + "\""); } final String parent = reader.readLine(); final Matcher parentMatcher = dirPattern.matcher(parent); if (!parentMatcher.matches()) { throw new ParseError("expected dirline but got \"" + parent + "\""); } final TarArchiveEntry entry = new TarArchiveEntry(base, true); entry.setMode(convertModeFromString(currentMatcher.group(1))); entry.setUserName(currentMatcher.group(3)); entry.setGroupName(currentMatcher.group(4)); return entry; } private int convertModeFromString( final String mode ) { final char[] m = mode.toCharArray(); /* -rwxrwxrwx 4000 set-user-ID-on-execution bit 2000 set-user-ID-on-execution bit 1000 sticky bit 0400 allow read by owner. 0200 allow write by owner. 0100 execute / search 0040 allow read by group members. 0020 allow write by group members. 0010 execute / search 0004 allow read by others. 0002 allow write by others. 0001 execute / search */ // TODO: simplified - needs fixing int sum = 0; int bit = 1; for (int i = m.length - 1; i >= 0; i--) { if (m[i] != '-') { sum += bit; } bit += bit; } return sum; } private TarArchiveEntry readFile( final BufferedReader reader, final String base ) throws IOException, ParseError { while (true) { final String line = reader.readLine(); if (line == null) { return null; } final Matcher currentMatcher = filePattern.matcher(line); if (!currentMatcher.matches()) { final Matcher newlineMatcher = newlinePattern.matcher(line); if (newlineMatcher.matches()) { return null; } throw new ParseError("expected file line but got \"" + line + "\""); } final String type = currentMatcher.group(1); if (type.startsWith("-")) { final TarArchiveEntry entry = new TarArchiveEntry(base + "/" + currentMatcher.group(8), true); entry.setMode(convertModeFromString(currentMatcher.group(2))); entry.setUserName(currentMatcher.group(4)); entry.setGroupName(currentMatcher.group(5)); return entry; } } } private Map parse( final InputStream pInput ) throws IOException, ParseError { final Map mapping = new HashMap(); final BufferedReader reader = new BufferedReader(new InputStreamReader(pInput)); boolean first = true; while (true) { final String base; if (first) { base = ""; first = false; } else { base = readBase(reader); if (base == null) { break; } } readTotal(reader); final TarArchiveEntry dir = readDir(reader, base); mapping.put(dir.getName(), dir); while (true) { final TarArchiveEntry file = readFile(reader, base); if (file == null) { break; } mapping.put(file.getName(), file); } } return mapping; } public TarArchiveEntry map( final TarArchiveEntry pEntry ) { final TarArchiveEntry entry = mapping.get(pEntry.getName()); if (entry != null) { final TarArchiveEntry newEntry = new TarArchiveEntry(entry.getName(), true); newEntry.setUserId(entry.getUserId()); newEntry.setGroupId(entry.getGroupId()); newEntry.setUserName(entry.getUserName()); newEntry.setGroupName(entry.getGroupName()); newEntry.setMode(entry.getMode()); newEntry.setSize(entry.getSize()); return newEntry; } return pEntry; } } jdeb/src/main/java/org/vafer/jdeb/mapping/Mapper.java0000644000175000017500000000162712207644255022633 0ustar moellermoeller/* * 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.mapping; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; /** * Maps one entry to another. So you modify ownerships permissions etc in a Mapper. * * @author Torsten Curdt */ public interface Mapper { public TarArchiveEntry map( final TarArchiveEntry entry ); } jdeb/src/main/java/org/vafer/jdeb/mapping/NullMapper.java0000644000175000017500000000166412207644255023467 0ustar moellermoeller/* * 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.mapping; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; public final class NullMapper implements Mapper { public static final Mapper INSTANCE = new NullMapper(); private NullMapper() { } public TarArchiveEntry map( final TarArchiveEntry pEntry ) { return pEntry; } } jdeb/src/main/java/org/vafer/jdeb/mapping/PermMapper.java0000644000175000017500000000632312207644255023455 0ustar moellermoeller/* * 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.mapping; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.vafer.jdeb.utils.Utils; /** * Applies a uniform set of permissions and ownership to all entries. * * @author Bryan Sant */ public final class PermMapper implements Mapper { private final int strip; private final String prefix; private int uid = -1; private int gid = -1; private String user; private String group; private int fileMode = -1; private int dirMode = -1; public static int toMode( String modeString ) { int mode = -1; if (modeString != null && modeString.length() > 0) { mode = Integer.parseInt(modeString, 8); } return mode; } public PermMapper( int uid, int gid, String user, String group, int fileMode, int dirMode, int strip, String prefix ) { this.strip = strip; this.prefix = (prefix == null) ? "" : prefix; this.uid = uid; this.gid = gid; this.user = user; this.group = group; this.fileMode = fileMode; this.dirMode = dirMode; } public PermMapper( int uid, int gid, String user, String group, String fileMode, String dirMode, int strip, String prefix ) { this(uid, gid, user, group, toMode(fileMode), toMode(dirMode), strip, prefix); } public TarArchiveEntry map( final TarArchiveEntry entry ) { final String name = entry.getName(); final TarArchiveEntry newEntry = new TarArchiveEntry(prefix + '/' + Utils.stripPath(strip, name), true); // Set ownership if (uid > -1) { newEntry.setUserId(uid); } else { newEntry.setUserId(entry.getUserId()); } if (gid > -1) { newEntry.setGroupId(gid); } else { newEntry.setGroupId(entry.getGroupId()); } if (user != null) { newEntry.setUserName(user); } else { newEntry.setUserName(entry.getUserName()); } if (group != null) { newEntry.setGroupName(group); } else { newEntry.setGroupName(entry.getGroupName()); } // Set permissions if (newEntry.isDirectory()) { if (dirMode > -1) { newEntry.setMode(dirMode); } else { newEntry.setMode(entry.getMode()); } } else { if (fileMode > -1) { newEntry.setMode(fileMode); } else { newEntry.setMode(entry.getMode()); } } newEntry.setSize(entry.getSize()); return newEntry; } } jdeb/src/main/java/org/vafer/jdeb/maven/0000755000175000017500000000000012207644255020211 5ustar moellermoellerjdeb/src/main/java/org/vafer/jdeb/maven/AbstractPluginMojo.java0000644000175000017500000000237312207644255024630 0ustar moellermoeller/* * 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; } } jdeb/src/main/java/org/vafer/jdeb/maven/Data.java0000644000175000017500000001412612207644255021731 0ustar moellermoeller/* * 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 static org.vafer.jdeb.maven.MissingSourceBehavior.FAIL; import static org.vafer.jdeb.maven.MissingSourceBehavior.IGNORE; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; 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.DataProducerLink; import org.vafer.jdeb.producers.DataProducerPathTemplate; /** * Maven "data" element acting as a factory for DataProducers. So far Archive and * Directory producers are supported. Both support the usual ant pattern set * matching. * * @author Bryan Sant */ public final class Data implements DataProducer { private File src; /** * @parameter expression="${src}" */ public void setSrc( File src ) { this.src = src; } private String dst; /** * @parameter expression="${dst}" */ public void setDst( String dst ) { this.dst = dst; } private String type; /** * @parameter expression="${type}" */ public void setType( String type ) { this.type = type; } private MissingSourceBehavior missingSrc = FAIL; /** * @parameter expression="${missingSrc}" */ public void setMissingSrc( String missingSrc ) { MissingSourceBehavior value = MissingSourceBehavior.valueOf(missingSrc.trim().toUpperCase()); if (value == null) { throw new IllegalArgumentException("Unknown " + MissingSourceBehavior.class.getSimpleName() + ": " + missingSrc); } this.missingSrc = value; } private String linkName; /** * @parameter expression="${linkName}" */ public void setLinkName(String linkName) { this.linkName = linkName; } private String linkTarget; /** * @parameter expression="${linkTarget}" */ public void setLinkTarget(String linkTarget) { this.linkTarget = linkTarget; } private boolean symlink = true; /** * @parameter expression="${symlink}" */ public void setSymlink(boolean symlink) { this.symlink = symlink; } private String[] includePatterns; /** * @parameter expression="${includes}" alias="includes" */ public void setIncludes( String includes ) { includePatterns = splitPatterns(includes); } private String[] excludePatterns; /** * @parameter expression="${excludes}" alias="excludes" */ public void setExcludes( String excludes ) { excludePatterns = splitPatterns(excludes); } /** * @parameter expression="${mapper}" */ private Mapper mapper; /** * @parameter expression="${paths}" */ private String[] paths; /* For testing only */ void setPaths( String[] paths ) { this.paths = paths; } public String[] splitPatterns( String patterns ) { String[] result = null; if (patterns != null && patterns.length() > 0) { List tokens = new ArrayList(); StringTokenizer tok = new StringTokenizer(patterns, ", ", false); while (tok.hasMoreTokens()) { tokens.add(tok.nextToken()); } result = tokens.toArray(new String[tokens.size()]); } return result; } public void produce( final DataConsumer pReceiver ) throws IOException { org.vafer.jdeb.mapping.Mapper[] mappers = null; if (mapper != null) { mappers = new org.vafer.jdeb.mapping.Mapper[] { mapper.createMapper() }; } // link type if ("link".equalsIgnoreCase(type)) { if (linkName == null) { throw new RuntimeException("linkName is not set"); } if (linkTarget == null) { throw new RuntimeException("linkTarget is not set"); } new DataProducerLink(linkName, linkTarget, symlink, includePatterns, excludePatterns, mappers).produce(pReceiver); return; } // template type if ("template".equalsIgnoreCase(type)) { if (paths == null || paths.length == 0) { throw new RuntimeException("paths is not set"); } new DataProducerPathTemplate(paths, includePatterns, excludePatterns, mappers).produce(pReceiver); return; } // Types that require src to exist if (src == null || !src.exists()) { if (missingSrc == IGNORE) { return; } else { throw new FileNotFoundException("Data source not found : " + src); } } if ("file".equalsIgnoreCase(type)) { new DataProducerFile(src, dst, includePatterns, excludePatterns, mappers).produce(pReceiver); return; } if ("archive".equalsIgnoreCase(type)) { new DataProducerArchive(src, includePatterns, excludePatterns, mappers).produce(pReceiver); return; } if ("directory".equalsIgnoreCase(type)) { new DataProducerDirectory(src, includePatterns, excludePatterns, mappers).produce(pReceiver); return; } throw new IOException("Unknown type '" + type + "' (file|directory|archive|template|link) for " + src); } } jdeb/src/main/java/org/vafer/jdeb/maven/DebMojo.java0000644000175000017500000003426012207644255022400 0ustar moellermoeller/* * 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 java.io.FileInputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.maven.artifact.Artifact; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectHelper; import org.apache.tools.tar.TarEntry; 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; /** * Creates deb archive * * @goal jdeb * @phase package */ public class DebMojo extends AbstractPluginMojo { /** * @component */ private MavenProjectHelper projectHelper; /** * Defines the name of deb package. * * @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]]" */ 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" */ private String controlDir; /** * Explicitly define the file to read the changes from. * * @parameter default-value="[[baseDir]]/CHANGES.txt" */ private String changesIn; /** * Explicitly define the file where to write the changes to. * * @parameter default-value="[[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" */ private String changesSave; /** * The compression method used for the data file (none, gzip, bzip2 or xz) * * @parameter default-value="gzip" */ private String compression; /** * Boolean option whether to attach the artifact to the project * * @parameter default-value="true" */ private String attach; /** * The location where all package files will be installed. By default, all * 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]]" */ private String installDir; /** * The type of attached artifact * * @parameter default-value="deb" */ private String type; /** * The project base directory * * @parameter default-value="${basedir}" * @required * @readonly */ 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" */ private boolean submodules; /** * The Maven Session Object * * @parameter expression="${session}" * @required * @readonly */ private MavenSession session; /** * The classifier of attached artifact * * @parameter */ private String classifier; /** * "data" entries used to determine which files should be added to this deb. * 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: * *
     *   
     *     
     *       
     *       jdeb
     *       org.vafer
     *       ...
     *       
     *         ...
     *         
     *           
     *             ${project.basedir}/target/my_archive.tar.gz
     *             ...
     *             ...
     *             
     *               perm
     *               1
     *               /somewhere/else
     *               santbj
     *               santbj
     *               600
     *             
     *           
     *           
     *             ${project.build.directory}/data
     *             
     *             **/.svn
     *             
     *               ls
     *               mapping.txt
     *             
     *           
     *           
     *             link
     *             /a/path/on/the/target/fs
     *             /a/sym/link/to/the/scr/file
     *             true
     *           
     *           
     *             ${project.basedir}/README.txt
     *           
     *         
     *       
     *     
     *   
     * 
* * @parameter expression="${dataSet}" */ private Data[] dataSet; /** * When SNAPSHOT version replace SNAPSHOT with current date * and time to make sure each build is unique. * * @parameter expression="${timestamped}" default-value="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" */ private boolean verbose; /* end of parameters */ private String openReplaceToken = "[["; private String closeReplaceToken = "]]"; private Collection dataProducers = new ArrayList(); 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(); if (dataSet != null) { Collections.addAll(dataProducers, dataSet); } } protected VariableResolver initializeVariableResolver( Map variables ) { ((Map) variables).putAll(getProject().getProperties()); ((Map) variables).putAll(System.getProperties()); variables.put("name", name != null ? name : getProject().getName()); variables.put("artifactId", getProject().getArtifactId()); variables.put("groupId", getProject().getGroupId()); variables.put("version", getProjectVersion()); variables.put("description", getProject().getDescription()); variables.put("extension", "deb"); variables.put("baseDir", getProject().getBasedir().getAbsolutePath()); variables.put("buildDir", buildDirectory.getAbsolutePath()); variables.put("project.version", getProject().getVersion()); variables.put("url", getProject().getUrl()); return new MapVariableResolver(variables); } /** * Doc some cleanup and conversion on the Maven project version. *
    *
  • any "-" is replaced by "+"
  • *
  • "SNAPSHOT" is replaced with the current time and date, prepended by "~"
  • *
* * @return the Maven project version */ private String getProjectVersion() { return Utils.convertToDebianVersion(getProject().getVersion(), this.timestamped ? session.getStartTime() : null); } /** * @return whether or not Maven is currently operating in the execution root */ private boolean isSubmodule() { // FIXME there must be a better way return !session.getExecutionRootDirectory().equalsIgnoreCase(baseDir.toString()); } /** * @return whether or not the main artifact was created */ private boolean hasMainArtifact() { final MavenProject project = getProject(); final Artifact artifact = project.getArtifact(); return artifact.getFile() != null && artifact.getFile().isFile(); } /** * Main entry point * * @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"); return; } setData(dataSet); Console console = new MojoConsole(getLog(), verbose); final VariableResolver resolver = initializeVariableResolver(new HashMap()); final File debFile = new File(Utils.replaceVariables(resolver, deb, openReplaceToken, closeReplaceToken)); final File controlDirFile = new File(Utils.replaceVariables(resolver, controlDir, openReplaceToken, closeReplaceToken)); final File installDirFile = new File(Utils.replaceVariables(resolver, installDir, openReplaceToken, closeReplaceToken)); 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)); // 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 tag or call the plugin directly?"); } } else { Set artifacts = new HashSet(); artifacts.add(project.getArtifact()); for (Artifact artifact : (Set) project.getArtifacts()) { artifacts.add(artifact); } for (Artifact artifact : (List) project.getAttachedArtifacts()) { artifacts.add(artifact); } for (Artifact artifact : artifacts) { final File file = artifact.getFile(); if (file != null) { dataProducers.add(new DataProducer() { @Override public void produce( final DataConsumer receiver ) { try { receiver.onEachFile( new FileInputStream(file), new File(installDirFile, file.getName()).getAbsolutePath(), "", "root", 0, "root", 0, TarEntry.DEFAULT_FILE_MODE, file.length()); } catch (Exception e) { getLog().error(e); } } }); } else { getLog().error("No file for artifact " + artifact); } } } } try { DebMaker debMaker = new DebMaker(console, dataProducers); debMaker.setDeb(debFile); debMaker.setControl(controlDirFile); debMaker.setPackage(getProject().getArtifactId()); debMaker.setDescription(getProject().getDescription()); debMaker.setHomepage(getProject().getUrl()); debMaker.setChangesIn(changesInFile); debMaker.setChangesOut(changesOutFile); debMaker.setChangesSave(changesSaveFile); debMaker.setCompression(compression); debMaker.setResolver(resolver); 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); } } catch (PackagingException e) { getLog().error("Failed to create debian package " + debFile, e); throw new MojoExecutionException("Failed to create debian package " + debFile, e); } } } jdeb/src/main/java/org/vafer/jdeb/maven/Mapper.java0000644000175000017500000000420512207644255022301 0ustar moellermoeller/* * 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 java.io.FileInputStream; import java.io.IOException; import org.vafer.jdeb.mapping.LsMapper; import org.vafer.jdeb.mapping.NullMapper; import org.vafer.jdeb.mapping.PermMapper; /** * Maven "mapper" element acting as factory for the entry mapper. * Supported types: ls, perm * * @author Bryan Sant */ public final class Mapper { /** * @parameter * @required */ private String type; /** * @parameter */ private int uid = -1; /** * @parameter */ private int gid = -1; /** * @parameter */ private String user; /** * @parameter */ private String group; /** * @parameter */ private String filemode; /** * @parameter */ private String dirmode; /** * @parameter */ private String prefix; /** * @parameter */ private int strip; /** * @parameter */ private File src; public org.vafer.jdeb.mapping.Mapper createMapper() throws IOException { if ("ls".equalsIgnoreCase(type)) { try { return new LsMapper(new FileInputStream(src)); } catch (Exception e) { e.printStackTrace(); } } if ("perm".equalsIgnoreCase(type)) { return new PermMapper(uid, gid, user, group, filemode, dirmode, strip, prefix); } /* NullMapper required for DataProducerPathTemplate */ return NullMapper.INSTANCE; } } jdeb/src/main/java/org/vafer/jdeb/maven/MissingSourceBehavior.java0000644000175000017500000000126312207644255025330 0ustar moellermoeller/* * 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; public enum MissingSourceBehavior { IGNORE, FAIL } jdeb/src/main/java/org/vafer/jdeb/maven/MojoConsole.java0000644000175000017500000000216712207644255023311 0ustar moellermoeller/* * 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 org.apache.maven.plugin.logging.Log; import org.vafer.jdeb.Console; /** * Console implementation for Maven plugins. */ class MojoConsole implements Console { private final Log log; private final boolean verbose; public MojoConsole(Log log, boolean verbose) { this.log = log; this.verbose = verbose; } public void info(String s) { if (verbose) { log.info(s); } } public void warn(String s) { log.warn(s); } } jdeb/src/main/java/org/vafer/jdeb/producers/0000755000175000017500000000000012207644255021111 5ustar moellermoellerjdeb/src/main/java/org/vafer/jdeb/producers/AbstractDataProducer.java0000644000175000017500000000454512207644255026025 0ustar moellermoeller/* * 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.producers; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.tools.ant.types.selectors.SelectorUtils; import org.vafer.jdeb.DataProducer; import org.vafer.jdeb.mapping.Mapper; /** * Base Producer class providing including/excluding. * * @author Torsten Curdt */ public abstract class AbstractDataProducer implements DataProducer { private final String[] includes; private final String[] excludes; private final Mapper[] mappers; public AbstractDataProducer( final String[] pIncludes, final String[] pExcludes, final Mapper[] pMapper ) { excludes = (pExcludes != null) ? pExcludes : new String[0]; includes = (pIncludes != null) ? pIncludes : new String[] { "**" }; mappers = (pMapper != null) ? pMapper : new Mapper[0]; } public boolean isIncluded( final String pName ) { if (!isIncluded(pName, includes)) { return false; } if (isExcluded(pName, excludes)) { return false; } return true; } private boolean isIncluded( String name, String[] includes ) { for (String include : includes) { if (SelectorUtils.matchPath(include, name)) { return true; } } return false; } private boolean isExcluded( String name, String[] excludes ) { for (String exclude : excludes) { if (SelectorUtils.matchPath(exclude, name)) { return true; } } return false; } public TarArchiveEntry map( final TarArchiveEntry pEntry ) { TarArchiveEntry entry = pEntry; for (Mapper mapper : mappers) { entry = mapper.map(entry); } return entry; } } jdeb/src/main/java/org/vafer/jdeb/producers/DataProducerArchive.java0000644000175000017500000001267412207644255025645 0ustar moellermoeller/* * 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.producers; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.archivers.ArchiveStreamFactory; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.commons.compress.compressors.CompressorException; import org.apache.commons.compress.compressors.CompressorInputStream; import org.apache.commons.compress.compressors.CompressorStreamFactory; import org.vafer.jdeb.DataConsumer; import org.vafer.jdeb.DataProducer; import org.vafer.jdeb.mapping.Mapper; /** * Providing data from an archive keeping permissions and ownerships. * * @author Torsten Curdt */ public final class DataProducerArchive extends AbstractDataProducer implements DataProducer { private final File archive; public DataProducerArchive( final File pArchive, final String[] pIncludes, final String[] pExcludes, final Mapper[] pMappers ) { super(pIncludes, pExcludes, pMappers); archive = pArchive; } public void produce( final DataConsumer pReceiver ) throws IOException { InputStream is = new BufferedInputStream(new FileInputStream(archive)); CompressorInputStream compressorInputStream = null; try { compressorInputStream = new CompressorStreamFactory().createCompressorInputStream(is); } catch (CompressorException e) { // expected if the input file is a zip archive } if (compressorInputStream != null) { is = new BufferedInputStream(compressorInputStream); } ArchiveInputStream archiveInputStream = null; try { archiveInputStream = new ArchiveStreamFactory().createArchiveInputStream(is); } catch (ArchiveException e) { throw new IOException("Unsupported archive format: " + archive, e); } EntryConverter converter = null; if (archiveInputStream instanceof TarArchiveInputStream) { converter = new EntryConverter() { public TarArchiveEntry convert( ArchiveEntry entry ) { TarArchiveEntry src = (TarArchiveEntry) entry; TarArchiveEntry dst = new TarArchiveEntry(src.getName(), true); dst.setSize(src.getSize()); dst.setGroupName(src.getGroupName()); dst.setGroupId(src.getGroupId()); dst.setUserId(src.getUserId()); dst.setMode(src.getMode()); dst.setModTime(src.getModTime()); return dst; } }; } else if (archiveInputStream instanceof ZipArchiveInputStream) { converter = new EntryConverter() { public TarArchiveEntry convert( ArchiveEntry entry ) { ZipArchiveEntry src = (ZipArchiveEntry) entry; TarArchiveEntry dst = new TarArchiveEntry(src.getName(), true); dst.setSize(src.getSize()); dst.setMode(src.getUnixMode()); dst.setModTime(src.getTime()); return dst; } }; } else { throw new IOException("Unsupported archive format: " + archive); } try { while (true) { ArchiveEntry archiveEntry = archiveInputStream.getNextEntry(); if (archiveEntry == null) { break; } if (!isIncluded(archiveEntry.getName())) { continue; } TarArchiveEntry entry = converter.convert(archiveEntry); entry = map(entry); if (entry.isDirectory()) { pReceiver.onEachDir(entry.getName(), entry.getLinkName(), entry.getUserName(), entry.getUserId(), entry.getGroupName(), entry.getGroupId(), entry.getMode(), entry.getSize()); continue; } pReceiver.onEachFile(archiveInputStream, entry.getName(), entry.getLinkName(), entry.getUserName(), entry.getUserId(), entry.getGroupName(), entry.getGroupId(), entry.getMode(), entry.getSize()); } } finally { if (archiveInputStream != null) { archiveInputStream.close(); } } } private interface EntryConverter { public TarArchiveEntry convert( ArchiveEntry entry ); } }jdeb/src/main/java/org/vafer/jdeb/producers/DataProducerDirectory.java0000644000175000017500000001035212207644255026217 0ustar moellermoeller/* * 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.producers; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.tools.ant.DirectoryScanner; import org.vafer.jdeb.DataConsumer; import org.vafer.jdeb.DataProducer; import org.vafer.jdeb.mapping.Mapper; import org.vafer.jdeb.utils.Utils; /** * DataProducer iterating over a directory. * For cross-platform permissions and ownerships you probably want to use a Mapper, too. * * @author Torsten Curdt */ public final class DataProducerDirectory extends AbstractDataProducer implements DataProducer { private final DirectoryScanner scanner = new DirectoryScanner(); public DataProducerDirectory( final File pDir, final String[] pIncludes, final String[] pExcludes, final Mapper[] pMappers ) { super(pIncludes, pExcludes, pMappers); scanner.setBasedir(pDir); scanner.setIncludes(pIncludes); scanner.setExcludes(pExcludes); scanner.setCaseSensitive(true); scanner.setFollowSymlinks(true); } public void produce( final DataConsumer pReceiver ) throws IOException { scanner.scan(); final File baseDir = scanner.getBasedir(); for (String dir : scanner.getIncludedDirectories()) { final File file = new File(baseDir, dir); String dirname = getFilename(baseDir, file); if ("".equals(dirname)) { continue; } if (!isIncluded(dirname)) { continue; } if ('/' != File.separatorChar) { dirname = dirname.replace(File.separatorChar, '/'); } 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()); } for (String f : scanner.getIncludedFiles()) { 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(); } } } private String getFilename( File root, File file ) { final String relativeFilename = file.getAbsolutePath().substring(root.getAbsolutePath().length()); return Utils.stripLeadingSlash(relativeFilename); } }jdeb/src/main/java/org/vafer/jdeb/producers/DataProducerFile.java0000644000175000017500000000466512207644255025144 0ustar moellermoeller/* * 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.producers; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.vafer.jdeb.DataConsumer; import org.vafer.jdeb.DataProducer; import org.vafer.jdeb.mapping.Mapper; /** * DataProducer representing a single file * For cross-platform permissions and ownerships you probably want to use a Mapper, too. * * @author Torsten Curdt */ public final class DataProducerFile extends AbstractDataProducer implements DataProducer { private final File file; private final String destinationName; public DataProducerFile( final File pFile, String pDestinationName, String[] pIncludes, String[] pExcludes, Mapper[] pMapper ) { super(pIncludes, pExcludes, pMapper); file = pFile; destinationName = pDestinationName; } public void produce( final DataConsumer pReceiver ) throws IOException { String fileName; if (destinationName != null && destinationName.trim().length() > 0) { fileName = destinationName.trim(); } else { 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); 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(); } } } jdeb/src/main/java/org/vafer/jdeb/producers/DataProducerFileSet.java0000644000175000017500000000572012207644255025611 0ustar moellermoeller/* * 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.producers; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.taskdefs.Tar; import org.apache.tools.ant.types.FileSet; import org.apache.tools.tar.TarEntry; import org.vafer.jdeb.DataConsumer; import org.vafer.jdeb.DataProducer; /** * DataProducer providing data from an Ant fileset. TarFileSets are also * supported with their permissions. * * @author Emmanuel Bourg */ public final class DataProducerFileSet implements DataProducer { private final FileSet fileset; public DataProducerFileSet( final FileSet fileset ) { this.fileset = fileset; } public void produce( final DataConsumer pReceiver ) throws IOException { String user = "root"; int uid = 0; String group = "root"; int gid = 0; int filemode = TarEntry.DEFAULT_FILE_MODE; int dirmode = TarEntry.DEFAULT_DIR_MODE; String prefix = ""; if (fileset instanceof Tar.TarFileSet) { Tar.TarFileSet tarfileset = (Tar.TarFileSet) fileset; user = tarfileset.getUserName(); uid = tarfileset.getUid(); group = tarfileset.getGroup(); gid = tarfileset.getGid(); filemode = tarfileset.getMode(); dirmode = tarfileset.getDirMode(tarfileset.getProject()); prefix = tarfileset.getPrefix(tarfileset.getProject()); } final DirectoryScanner scanner = fileset.getDirectoryScanner(fileset.getProject()); scanner.scan(); final File basedir = scanner.getBasedir(); for (String directory : scanner.getIncludedDirectories()) { String name = directory.replace('\\', '/'); pReceiver.onEachDir(prefix + "/" + name, null, user, uid, group, gid, dirmode, 0); } for (String filename : scanner.getIncludedFiles()) { final String name = filename.replace('\\', '/'); final File file = new File(basedir, name); final InputStream inputStream = new FileInputStream(file); try { pReceiver.onEachFile(inputStream, prefix + "/" + name, null, user, uid, group, gid, filemode, file.length()); } finally { inputStream.close(); } } } } jdeb/src/main/java/org/vafer/jdeb/producers/DataProducerLink.java0000644000175000017500000000413312207644255025150 0ustar moellermoeller/* * 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.producers; import java.io.IOException; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.vafer.jdeb.DataConsumer; import org.vafer.jdeb.DataProducer; import org.vafer.jdeb.mapping.Mapper; /** * DataProducer representing a single file * For cross-platform permissions and ownerships you probably want to use a Mapper, too. * * @author Thomas Mortagne */ public final class DataProducerLink extends AbstractDataProducer implements DataProducer { private final String path; private final String linkName; private final boolean symlink; public DataProducerLink(final String path, final String linkName, final boolean symlink, String[] pIncludes, String[] pExcludes, Mapper[] pMapper) { super(pIncludes, pExcludes, pMapper); this.path = path; this.symlink = symlink; 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.setMode(TarArchiveEntry.DEFAULT_FILE_MODE); entry = map(entry); pReceiver.onEachLink(path, linkName, symlink, entry.getUserName(), entry.getUserId(), entry.getGroupName(), entry.getGroupId(), entry.getMode()); } } jdeb/src/main/java/org/vafer/jdeb/producers/DataProducerPathTemplate.java0000644000175000017500000000351412207644255026645 0ustar moellermoeller/* * 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.producers; import java.io.IOException; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.vafer.jdeb.DataConsumer; import org.vafer.jdeb.DataProducer; import org.vafer.jdeb.mapping.Mapper; public class DataProducerPathTemplate extends AbstractDataProducer implements DataProducer { private final String[] literalPaths; public DataProducerPathTemplate( String[] pLiteralPaths, String[] pIncludes, String[] pExcludes, Mapper[] pMapper ) { super(pIncludes, pExcludes, pMapper); literalPaths = pLiteralPaths; } 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()); } } } jdeb/src/main/java/org/vafer/jdeb/signing/0000755000175000017500000000000012207644255020541 5ustar moellermoellerjdeb/src/main/java/org/vafer/jdeb/signing/PGPSigner.java0000644000175000017500000001311412207644255023202 0ustar moellermoeller/* * 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); } } jdeb/src/main/java/org/vafer/jdeb/utils/0000755000175000017500000000000012207644255020243 5ustar moellermoellerjdeb/src/main/java/org/vafer/jdeb/utils/FilteredFile.java0000644000175000017500000000413312207644255023445 0ustar moellermoeller/* * 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.utils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; public class FilteredFile { private static String openToken = "[["; private static String closeToken = "]]"; private List lines = new ArrayList(); public FilteredFile(InputStream in, VariableResolver resolver) throws IOException { parse(in, resolver); } public static void setOpenToken(String token) { openToken = token; } public static void setCloseToken(String token) { closeToken = token; } private void parse(InputStream in, VariableResolver resolver) throws IOException { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(in)); String line; while ((line = reader.readLine()) != null) { if (resolver != null) { lines.add(Utils.replaceVariables(resolver, line, openToken, closeToken)); } else { lines.add(line); } } } finally { if (reader != null) { reader.close(); } } } public String toString() { StringBuilder builder = new StringBuilder(); for (String line : lines) { builder.append(line).append('\n'); } return builder.toString(); } } jdeb/src/main/java/org/vafer/jdeb/utils/InformationInputStream.java0000644000175000017500000001200112207644255025561 0ustar moellermoeller/* * 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.utils; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; public final class InformationInputStream extends FilterInputStream { private long i; private long ascii; private long nonascii; private long cr; private long lf; private long zero; private final Map bomPositions = new HashMap(); private final Map shellPositions = new HashMap(); /** * Byte Order Marks */ private enum BOM { NONE(null), UTF8("UTF-8", 0xEF, 0xBB, 0xBF), UTF16LE("UTF-16LE", 0xFF, 0xFE), UTF16BE("UTF-16BE", 0xFE, 0xFF); int[] sequence; String encoding; private BOM( String encoding, int... sequence ) { this.encoding = encoding; this.sequence = sequence; } } /** * Shebang for shell scripts in various encodings. */ private enum Shell { NONE, ASCII(0x23, 0x21), UTF16BE(0x00, 0x23, 0x00, 0x21), UTF16LE(0x23, 0x00, 0x21, 0x00); int[] header; private Shell( int... header ) { this.header = header; } } private BOM bom = BOM.NONE; private Shell shell = Shell.NONE; public InformationInputStream( InputStream in ) { super(in); } public boolean hasBom() { return bom != BOM.NONE; } public boolean isShell() { return shell != Shell.NONE; } public boolean hasUnixLineEndings() { return cr == 0; } public String getEncoding() { String encoding = bom.encoding; if (encoding == null) { // guess the encoding from the shebang if (shell == Shell.UTF16BE) { encoding = BOM.UTF16BE.encoding; } else if (shell == Shell.UTF16LE) { encoding = BOM.UTF16LE.encoding; } } return encoding; } private void add( int c ) { if (i < 10) { if (shell == Shell.NONE) { for (Shell shell : Shell.values()) { int position = shellPositions.containsKey(shell) ? shellPositions.get(shell) : 0; if (position < shell.header.length) { if (c == shell.header[position]) { shellPositions.put(shell, position + 1); } else { shellPositions.put(shell, 0); } } else { this.shell = shell; } } } if (bom == BOM.NONE) { for (BOM bom : BOM.values()) { int position = bomPositions.containsKey(bom) ? bomPositions.get(bom) : 0; if (position < bom.sequence.length) { if (c == bom.sequence[position] && position == i) { bomPositions.put(bom, position + 1); } else { bomPositions.put(bom, 0); } } else { this.bom = bom; } } } } i++; if (c == '\n') { lf++; return; } if (c == '\r') { cr++; return; } if (c >= ' ' && c <= '~') { ascii++; return; } if (c == 0) { zero++; return; } nonascii++; } public int read() throws IOException { int b = super.read(); if (b != -1) { add(b & 0xFF); } return b; } public int read( byte[] b, int off, int len ) throws IOException { int length = super.read(b, off, len); for (int i = 0; i < length; i++) { add(b[off + i] & 0xFF); } return length; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append("{"); sb.append("total=").append(i); sb.append(",noascii=").append(nonascii); sb.append(",ascii=").append(ascii); sb.append(",cr=").append(cr); sb.append(",lf=").append(lf); sb.append(",zero=").append(zero); sb.append("}"); return sb.toString(); } } jdeb/src/main/java/org/vafer/jdeb/utils/InformationOutputStream.java0000644000175000017500000000311512207644255025770 0ustar moellermoeller/* * 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.utils; import java.io.IOException; import java.io.OutputStream; import java.security.DigestOutputStream; import java.security.MessageDigest; /** * Convenience class to provide digest info and length of a stream. * * ATTENTION: don't use outside of jdeb * * @author Torsten Curdt */ public class InformationOutputStream extends DigestOutputStream { private final MessageDigest digest; private long size; public InformationOutputStream( OutputStream pStream, MessageDigest pDigest ) { super(pStream, pDigest); digest = pDigest; size = 0; } public String getHexDigest() { return Utils.toHex(digest.digest()); } public void write( byte[] b, int off, int len ) throws IOException { super.write(b, off, len); size += len; } public void write( int b ) throws IOException { super.write(b); size++; } public long getSize() { return size; } }jdeb/src/main/java/org/vafer/jdeb/utils/MapVariableResolver.java0000644000175000017500000000206312207644255025014 0ustar moellermoeller/* * 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.utils; import java.util.Map; /** * Resolve variables based on a Map. * * ATTENTION: don't use outside of jdeb * * @author Torsten Curdt */ public final class MapVariableResolver implements VariableResolver { private final Map map; public MapVariableResolver( Map map ) { this.map = map; } public String get( String key ) { return map.get(key); } } jdeb/src/main/java/org/vafer/jdeb/utils/Utils.java0000644000175000017500000001272412207644255022214 0ustar moellermoeller/* * 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.utils; import java.io.ByteArrayOutputStream; 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 org.apache.tools.ant.filters.FixCrLfFilter; import org.apache.tools.ant.util.ReaderInputStream; /** * Simple utils functions. * * ATTENTION: don't use outside of jdeb * * @author Torsten Curdt */ public final class Utils { public static int copy( final InputStream pInput, final OutputStream pOutput ) throws IOException { final byte[] buffer = new byte[2048]; int count = 0; int n; while (-1 != (n = pInput.read(buffer))) { pOutput.write(buffer, 0, n); count += n; } return count; } public static String toHex( final byte[] bytes ) { final StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(Integer.toHexString((b >> 4) & 0x0f)); sb.append(Integer.toHexString(b & 0x0f)); } return sb.toString(); } public static String stripPath( final int p, final String s ) { if (p <= 0) { return s; } int x = 0; for (int i = 0; i < p; i++) { x = s.indexOf('/', x + 1); if (x < 0) { return s; } } return s.substring(x + 1); } public static String stripLeadingSlash( final String s ) { if (s == null) { return s; } if (s.length() == 0) { return s; } if (s.charAt(0) == '/' || s.charAt(0) == '\\') { return s.substring(1); } return s; } /** * Substitute the variables in the given expression with the * values from the resolver * * @param pResolver * @param pExpression */ public static String replaceVariables( final VariableResolver pResolver, final String pExpression, final String pOpen, final String pClose ) { final char[] open = pOpen.toCharArray(); final char[] close = pClose.toCharArray(); final StringBuilder out = new StringBuilder(); StringBuilder sb = new StringBuilder(); char[] watch = open; int w = 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 final String variable = pResolver.get(sb.toString()); if (variable != null) { out.append(variable); } else { out.append(pOpen); out.append(sb); out.append(pClose); } sb = new StringBuilder(); // search for open watch = open; } w = 0; } } else { if (w > 0) { sb.append(watch, 0, w); } sb.append(c); w = 0; } } if (watch == close) { out.append(open); } out.append(sb); return out.toString(); } /** * Replaces new line delimiters in the input stream with the Unix line feed. * * @param input */ public static byte[] toUnixLineEndings( InputStream input ) throws IOException { String encoding = "ISO-8859-1"; FixCrLfFilter filter = new FixCrLfFilter(new InputStreamReader(input, encoding)); filter.setEol(FixCrLfFilter.CrLf.newInstance("unix")); ByteArrayOutputStream filteredFile = new ByteArrayOutputStream(); Utils.copy(new ReaderInputStream(filter, encoding), filteredFile); return filteredFile.toByteArray(); } /** * convert to debian version format */ public static String convertToDebianVersion( String version, Date timestamp ) { version = version.replace('-', '+'); if (version.endsWith("+SNAPSHOT")) { version = version.substring(0, version.length() - "+SNAPSHOT".length()); version += "~"; if (timestamp != null) { version += new SimpleDateFormat("yyyyMMddHHmmss").format(timestamp); } else { version += "SNAPSHOT"; } } return version; } } jdeb/src/main/java/org/vafer/jdeb/utils/VariableResolver.java0000644000175000017500000000156712207644255024366 0ustar moellermoeller/* * 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.utils; /** * Interface for resolving variables. * See Utils.replaceVariables() * * ATTENTION: don't use outside of jdeb * * @author Torsten Curdt */ public interface VariableResolver { public String get( final String pKey ); } jdeb/src/main/resources/0000755000175000017500000000000012207644255015376 5ustar moellermoellerjdeb/src/main/resources/org/0000755000175000017500000000000012207644255016165 5ustar moellermoellerjdeb/src/main/resources/org/vafer/0000755000175000017500000000000012207644255017270 5ustar moellermoellerjdeb/src/main/resources/org/vafer/jdeb/0000755000175000017500000000000012207644255020174 5ustar moellermoellerjdeb/src/main/resources/org/vafer/jdeb/ant/0000755000175000017500000000000012207644255020756 5ustar moellermoellerjdeb/src/main/resources/org/vafer/jdeb/ant/antlib.xml0000644000175000017500000000017612207644255022755 0ustar moellermoeller jdeb/src/test/0000755000175000017500000000000012207644255013417 5ustar moellermoellerjdeb/src/test/java/0000755000175000017500000000000012207644255014340 5ustar moellermoellerjdeb/src/test/java/org/0000755000175000017500000000000012207644255015127 5ustar moellermoellerjdeb/src/test/java/org/vafer/0000755000175000017500000000000012207644255016232 5ustar moellermoellerjdeb/src/test/java/org/vafer/jdeb/0000755000175000017500000000000012207644255017136 5ustar moellermoellerjdeb/src/test/java/org/vafer/jdeb/ArchiveVisitor.java0000644000175000017500000000167012207644255022746 0ustar moellermoeller/* * 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 { void visit(E entry, byte[] content) throws IOException; } jdeb/src/test/java/org/vafer/jdeb/ArchiveWalker.java0000644000175000017500000001027212207644255022532 0ustar moellermoeller/* * 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 visitor) throws IOException { return walkEmbedded(deb, "control.tar", visitor, Compression.GZIP); } public static boolean walkData(File deb, final ArchiveVisitor visitor, final Compression compression) throws IOException { return walkEmbedded(deb, "data.tar", visitor, compression); } public static boolean walkEmbedded(File deb, final String name, final ArchiveVisitor visitor, final Compression compression) throws IOException { final AtomicBoolean found = new AtomicBoolean(false); ArArchiveInputStream in = new ArArchiveInputStream(new FileInputStream(deb)); ArchiveWalker.walk(in, new ArchiveVisitor() { 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() { public void visit(TarArchiveEntry entry, byte[] content) throws IOException { found.set(true); visitor.visit(entry, content); } }); } } }); return found.get(); } } jdeb/src/test/java/org/vafer/jdeb/DataBuilderTestCase.java0000644000175000017500000000565412207644255023627 0ustar moellermoeller/* * 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); } } jdeb/src/test/java/org/vafer/jdeb/DebMakerTestCase.java0000644000175000017500000001662412207644255023120 0ustar moellermoeller/* * 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.IOException; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; import junit.framework.TestCase; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.io.output.NullOutputStream; import org.vafer.jdeb.debian.BinaryPackageControlFile; import org.vafer.jdeb.producers.DataProducerArchive; import org.vafer.jdeb.producers.DataProducerDirectory; import org.vafer.jdeb.producers.DataProducerLink; import org.vafer.jdeb.utils.InformationInputStream; import org.vafer.jdeb.utils.MapVariableResolver; 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()); 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) }; File deb = File.createTempFile("jdeb", ".deb"); DebMaker maker = new DebMaker(new NullConsole(), Arrays.asList(data)); maker.setControl(new File(getClass().getResource("deb/control").toURI())); maker.setDeb(deb); BinaryPackageControlFile packageControlFile = maker.createDeb(Compression.GZIP); assertTrue(packageControlFile.isValid()); final Map filesInDeb = new HashMap(); ArchiveWalker.walkData(deb, new ArchiveVisitor() { public void visit(TarArchiveEntry entry, byte[] content) throws IOException { filesInDeb.put(entry.getName(), entry); } }, Compression.GZIP); 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()); assertTrue("Cannot delete the file " + deb, deb.delete()); } public void testControlFilesPermissions() throws Exception { File deb = new File("target/test-classes/test-control.deb"); if (deb.exists() && !deb.delete()) { fail("Couldn't delete " + deb); } Collection producers = Arrays.asList(new DataProducer[] {new EmptyDataProducer()}); DebMaker maker = new DebMaker(new NullConsole(), producers); maker.setDeb(deb); maker.setControl(new File("target/test-classes/org/vafer/jdeb/deb/control")); maker.createDeb(Compression.NONE); // now reopen the package and check the control files assertTrue("package not build", deb.exists()); boolean found = ArchiveWalker.walkControl(deb, new ArchiveVisitor() { public void visit(TarArchiveEntry entry, byte[] content) throws IOException { assertFalse("directory found in the control archive", entry.isDirectory()); assertTrue("prefix", entry.getName().startsWith("./")); InformationInputStream infoStream = new InformationInputStream(new ByteArrayInputStream(content)); IOUtils.copy(infoStream, NullOutputStream.NULL_OUTPUT_STREAM); if (infoStream.isShell()) { assertTrue("Permissions on " + entry.getName() + " should be 755", entry.getMode() == 0755); } else { assertTrue("Permissions on " + entry.getName() + " should be 644", entry.getMode() == 0644); } assertTrue(entry.getName() + " doesn't have Unix line endings", infoStream.hasUnixLineEndings()); assertEquals("user", "root", entry.getUserName()); assertEquals("group", "root", entry.getGroupName()); } }); assertTrue("Control files not found in the package", found); } public void testControlFilesVariables() throws Exception { File deb = new File("target/test-classes/test-control.deb"); if (deb.exists() && !deb.delete()) { fail("Couldn't delete " + deb); } Map variables = new HashMap(); variables.put("name", "jdeb"); variables.put("version", "1.0"); Collection producers = Arrays.asList(new DataProducer[] {new EmptyDataProducer()}); DebMaker maker = new DebMaker(new NullConsole(), producers); maker.setDeb(deb); maker.setControl(new File("target/test-classes/org/vafer/jdeb/deb/control")); maker.setResolver(new MapVariableResolver(variables)); maker.createDeb(Compression.NONE); // now reopen the package and check the control files assertTrue("package not build", deb.exists()); boolean found = ArchiveWalker.walkControl(deb, new ArchiveVisitor() { public void visit(TarArchiveEntry entry, byte[] content) throws IOException { if (entry.getName().contains("postinst") || entry.getName().contains("prerm")) { String body = new String(content, "ISO-8859-1"); assertFalse("Variables not replaced in the control file " + entry.getName(), body.contains("[[name]] [[version]]")); assertTrue("Expected variables not found in the control file " + entry.getName(), body.contains("jdeb 1.0")); } } }); assertTrue("Control files not found in the package", found); } } jdeb/src/test/java/org/vafer/jdeb/EmptyDataProducer.java0000644000175000017500000000153012207644255023374 0ustar moellermoeller/* * 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 { } } jdeb/src/test/java/org/vafer/jdeb/NullConsole.java0000644000175000017500000000145712207644255022245 0ustar moellermoeller/* * 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) { } } jdeb/src/test/java/org/vafer/jdeb/ant/0000755000175000017500000000000012207644255017720 5ustar moellermoellerjdeb/src/test/java/org/vafer/jdeb/ant/AntSelectorTestCase.java0000644000175000017500000000204112207644255024437 0ustar moellermoeller/* * 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 junit.framework.TestCase; import org.apache.tools.ant.types.selectors.SelectorUtils; public final class AntSelectorTestCase extends TestCase { public void testExclusion() throws Exception { assertTrue("should match", SelectorUtils.matchPath("**/bin/**", "/some/bin/stuff")); assertFalse("should not match", SelectorUtils.matchPath("**/bin/**", "/some/stuff")); } } jdeb/src/test/java/org/vafer/jdeb/ant/DebAntTaskTestCase.java0000644000175000017500000002504712207644255024207 0ustar moellermoeller/* * 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 java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.concurrent.atomic.AtomicBoolean; import junit.framework.TestCase; 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.compressors.bzip2.BZip2CompressorInputStream; import org.apache.commons.compress.compressors.xz.XZCompressorInputStream; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DefaultLogger; import org.apache.tools.ant.Project; import org.apache.tools.ant.ProjectHelper; import org.apache.tools.tar.TarInputStream; import org.vafer.jdeb.ArchiveVisitor; import org.vafer.jdeb.ArchiveWalker; import org.vafer.jdeb.Compression; /** * @author Emmanuel Bourg */ public final class DebAntTaskTestCase extends TestCase { private Project project; protected void setUp() throws Exception { project = new Project(); project.setCoreLoader(getClass().getClassLoader()); project.init(); File buildFile = new File("target/test-classes/testbuild.xml"); project.setBaseDir(buildFile.getParentFile()); final ProjectHelper helper = ProjectHelper.getProjectHelper(); helper.parse(project, buildFile); // remove the package previously build File deb = new File("target/test.deb"); if (deb.exists()) { assertTrue("Unable to remove the test archive", deb.delete()); } } public void testMissingControl() { try { project.executeTarget("missing-control"); fail("No exception thrown"); } catch (BuildException e) { // expected } } public void testInvalidControl() { try { project.executeTarget("invalid-control"); fail("No exception thrown"); } catch (BuildException e) { // expected } } public void testMissingDestFile() { try { project.executeTarget("missing-destfile"); fail("No exception thrown"); } catch (BuildException e) { // expected } } public void testEmptyPackage() { try { project.executeTarget("empty-package"); fail("No exception thrown"); } catch (BuildException e) { // expected } } public void testPackageWithArchive() { project.executeTarget("with-archive"); assertTrue("package not build", new File("target/test-classes/test.deb").exists()); } public void testPackageWithMissingArchive() { try { project.executeTarget("with-missing-archive"); fail("No exception thrown"); } catch (BuildException e) { // expected } } public void testPackageWithDirectory() { project.executeTarget("with-directory"); assertTrue("package not build", new File("target/test-classes/test.deb").exists()); } public void testPackageWithMissingDirectory() { try { project.executeTarget("with-missing-directory"); fail("No exception thrown"); } catch (BuildException e) { // expected } } /** * Redirects the Ant output to the specified stream. */ private void redirectOutput( OutputStream out ) { DefaultLogger logger = new DefaultLogger(); logger.setOutputPrintStream(new PrintStream(out)); logger.setMessageOutputLevel(Project.MSG_INFO); project.addBuildListener(logger); } public void testVerboseEnabled() { ByteArrayOutputStream out = new ByteArrayOutputStream(); redirectOutput(out); project.executeTarget("verbose-enabled"); assertTrue(out.toString().contains("Total size")); } public void testVerboseDisabled() { ByteArrayOutputStream out = new ByteArrayOutputStream(); redirectOutput(out); project.executeTarget("verbose-disabled"); assertTrue(!out.toString().contains("Total size")); } public void testMissingDataType() { try { project.executeTarget("missing-data-type"); fail("No exception thrown"); } catch (BuildException e) { // expected } } public void testUnknownDataType() { try { project.executeTarget("unknown-data-type"); fail("No exception thrown"); } catch (BuildException e) { // expected } } public void testFileSet() { project.executeTarget("fileset"); assertTrue("package not build", new File("target/test-classes/test.deb").exists()); } public void testTarFileSet() throws Exception { project.executeTarget("tarfileset"); File deb = new File("target/test-classes/test.deb"); assertTrue("package not build", deb.exists()); ArchiveWalker.walkData(deb, new ArchiveVisitor() { public void visit(TarArchiveEntry entry, byte[] content) throws IOException { assertTrue("prefix: " + entry.getName(), entry.getName().startsWith("./foo/")); if (entry.isDirectory()) { assertEquals("directory mode (" + entry.getName() + ")", 040700, entry.getMode()); } else { assertEquals("file mode (" + entry.getName() + ")", 0100600, entry.getMode()); } assertEquals("user", "ebourg", entry.getUserName()); assertEquals("group", "ebourg", entry.getGroupName()); } }, Compression.GZIP); } public void testLink() throws Exception { project.executeTarget("link"); File deb = new File("target/test-classes/test.deb"); assertTrue("package not build", deb.exists()); final AtomicBoolean linkFound = new AtomicBoolean(false); ArchiveWalker.walkData(deb, new ArchiveVisitor() { public void visit(TarArchiveEntry entry, byte[] content) throws IOException { if (entry.isSymbolicLink()) { linkFound.set(true); assertEquals("link mode (" + entry.getName() + ")", 0120755, entry.getMode()); } assertEquals("user", "ebourg", entry.getUserName()); assertEquals("group", "ebourg", entry.getGroupName()); } }, Compression.GZIP); assertTrue("Link not found", linkFound.get()); } public void testUnkownCompression() throws Exception { try { project.executeTarget("unknown-compression"); fail("No exception thrown"); } catch (BuildException e) { // expected } } public void testBZip2Compression() throws Exception { project.executeTarget("bzip2-compression"); File deb = new File("target/test-classes/test.deb"); assertTrue("package not build", deb.exists()); final AtomicBoolean found = new AtomicBoolean(false); ArArchiveInputStream in = new ArArchiveInputStream(new FileInputStream(deb)); ArchiveWalker.walk(in, new ArchiveVisitor() { public void visit(ArArchiveEntry entry, byte[] content) throws IOException { if (entry.getName().equals("data.tar.bz2")) { found.set(true); assertEquals("header 0", (byte) 'B', content[0]); assertEquals("header 1", (byte) 'Z', content[1]); TarInputStream tar = new TarInputStream(new BZip2CompressorInputStream(new ByteArrayInputStream(content))); while ((tar.getNextEntry()) != null) ; tar.close(); } } }); assertTrue("bz2 file not found", found.get()); } public void testXZCompression() throws Exception { project.executeTarget("xz-compression"); File deb = new File("target/test-classes/test.deb"); assertTrue("package not build", deb.exists()); final AtomicBoolean found = new AtomicBoolean(false); ArArchiveInputStream in = new ArArchiveInputStream(new FileInputStream(deb)); ArchiveWalker.walk(in, new ArchiveVisitor() { public void visit(ArArchiveEntry entry, byte[] content) throws IOException { if (entry.getName().equals("data.tar.xz")) { found.set(true); assertEquals("header 0", (byte) 0xFD, content[0]); assertEquals("header 1", (byte) '7', content[1]); assertEquals("header 2", (byte) 'z', content[2]); assertEquals("header 3", (byte) 'X', content[3]); assertEquals("header 4", (byte) 'Z', content[4]); assertEquals("header 5", (byte) '\0', content[5]); TarInputStream tar = new TarInputStream(new XZCompressorInputStream(new ByteArrayInputStream(content))); while ((tar.getNextEntry()) != null) ; tar.close(); } } }); assertTrue("xz file not found", found.get()); } public void testNoCompression() throws Exception { project.executeTarget("no-compression"); File deb = new File("target/test-classes/test.deb"); assertTrue("package not build", deb.exists()); boolean found = ArchiveWalker.walkData(deb, new ArchiveVisitor() { public void visit(TarArchiveEntry entry, byte[] content) throws IOException { } }, Compression.NONE); assertTrue("tar file not found", found); } } jdeb/src/test/java/org/vafer/jdeb/changes/0000755000175000017500000000000012207644255020546 5ustar moellermoellerjdeb/src/test/java/org/vafer/jdeb/changes/TextfileChangesProviderTestCase.java0000644000175000017500000000640012207644255027635 0ustar moellermoeller/* * 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.changes; import java.io.ByteArrayInputStream; import junit.framework.TestCase; import org.vafer.jdeb.debian.BinaryPackageControlFile; public final class TextfileChangesProviderTestCase extends TestCase { public void testParsing() throws Exception { final String input = " * change1\n" + " * change2\n" + "release date=14:00 13.01.2007, version=12324, urgency=low, by=tcurdt@joost.com\n" + " * change1\n" + " * change2\n" + "release date=12:00 10.01.2007, version=10324, urgency=low, by=tcurdt@joost.com\n" + " * change1\n" + " * change2\n"; BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile(); packageControlFile.set("Package", "package"); packageControlFile.set("Version", "version"); packageControlFile.set("Distribution", "distribution"); packageControlFile.set("Date", "Mon, 20 Aug 2007 15:25:57 +0200"); final TextfileChangesProvider provider = new TextfileChangesProvider(new ByteArrayInputStream(input.getBytes("UTF-8")), packageControlFile); final ChangeSet[] changeSets = provider.getChangesSets(); assertNotNull(changeSets); assertEquals(3, changeSets.length); } public void testDistributionFromChangesProvider() throws Exception { final String input = "release distribution=production\n" + " * change1\n" + " * change2\n" + "release distribution=staging, date=14:00 13.01.2007, version=12324, urgency=low, by=tcurdt@joost.com\n" + " * change1\n" + " * change2\n" + "release distribution=development, date=12:00 10.01.2007, version=10324, urgency=low, by=tcurdt@joost.com\n" + " * change1\n" + " * change2\n"; BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile(); packageControlFile.set("Package", "package"); packageControlFile.set("Version", "version"); packageControlFile.set("Date", "Mon, 20 Aug 2007 15:25:57 +0200"); final TextfileChangesProvider provider = new TextfileChangesProvider(new ByteArrayInputStream(input.getBytes("UTF-8")), packageControlFile); final ChangeSet[] changeSets = provider.getChangesSets(); assertNotNull(changeSets); assertEquals(3, changeSets.length); assertEquals("production", changeSets[0].getDistribution()); assertEquals("staging", changeSets[1].getDistribution()); assertEquals("development", changeSets[2].getDistribution()); } } jdeb/src/test/java/org/vafer/jdeb/debian/0000755000175000017500000000000012207644255020360 5ustar moellermoellerjdeb/src/test/java/org/vafer/jdeb/debian/ChangesFileTestCase.java0000644000175000017500000000246212207644255025033 0ustar moellermoeller/* * 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; import org.vafer.jdeb.changes.ChangeSet; public final class ChangesFileTestCase extends TestCase { public void testToString() throws Exception { BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile(); packageControlFile.set("Package", "test-package"); packageControlFile.set("Description", "This is\na description\non several lines"); packageControlFile.set("Version", "1.0"); ChangesFile changes = new ChangesFile(); changes.setChanges(new ChangeSet[0]); changes.initialize(packageControlFile); assertEquals("1.0", changes.get("Version")); } } jdeb/src/test/java/org/vafer/jdeb/debian/ControlFieldTestCase.java0000644000175000017500000000305112207644255025242 0ustar moellermoeller/* * 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")); } } jdeb/src/test/java/org/vafer/jdeb/debian/PackageControlFileTestCase.java0000644000175000017500000000714412207644255026361 0ustar moellermoeller/* * 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.FileInputStream; import java.text.ParseException; import junit.framework.TestCase; public final class PackageControlFileTestCase extends TestCase { public void testParse() throws Exception { String input = "Key1: Value1\n" + "Key2: Value2\n" + " Value2.1\n" + " Value2.2\n" + "Key3: Value3\n"; BinaryPackageControlFile d = new BinaryPackageControlFile(input); assertFalse(d.isValid()); assertEquals("key 1", "Value1", d.get("Key1")); assertEquals("key 2", "Value2\nValue2.1\nValue2.2", d.get("Key2")); assertEquals("key 3", "Value3", d.get("Key3")); } public void testToString() throws Exception { BinaryPackageControlFile packageControlFile = new BinaryPackageControlFile(); 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")); assertEquals("Version 3", packageControlFile.get("Version"), packageControlFile2.get("Version")); } public void testEmptyLines() throws Exception { String input = "Key1: Value1\n" + "Key2: Value2\n" + "\n"; try { new BinaryPackageControlFile(input); fail("Should throw a ParseException"); } 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")); } } jdeb/src/test/java/org/vafer/jdeb/mapping/0000755000175000017500000000000012207644255020571 5ustar moellermoellerjdeb/src/test/java/org/vafer/jdeb/mapping/LsMapperTestCase.java0000644000175000017500000000776312207644255024630 0ustar moellermoeller/* * 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.mapping; import java.io.ByteArrayInputStream; import junit.framework.TestCase; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.vafer.jdeb.mapping.LsMapper.ParseError; public final class LsMapperTestCase extends TestCase { private final static String output = "total 0\n" + "drwxr-xr-x 23 tcurdt tcurdt 782 Jun 25 03:48 .\n" + "drwxr-xr-x 3 tcurdt tcurdt 102 Jun 25 03:48 ..\n" + "\n" + "./trunk/target/test-classes/org/vafer/dependency:\n" + "total 176\n" + "drwxr-xr-x 23 tcurdt tcurdt 782 Jun 25 03:48 .\n" + "drwxr-xr-x 3 tcurdt tcurdt 102 Jun 25 03:48 ..\n" + "-rw-r--r-- 1 tcurdt tcurdt 2934 Jun 25 03:48 DependenciesTestCase.class\n" + "-rw-r--r-- 1 tcurdt tcurdt 786 Jun 25 03:48 JarCombiningTestCase$1.class\n" + "drwxr-xr-x 4 tcurdt tcurdt 136 Jun 25 03:48 classes\n" + "\n" + "./trunk/src/test-classes/org/vafer/dependency:\n" + "total 76\n" + "drwxr-xr-x 23 tcurdt tcurdt 782 Jun 25 03:48 .\n" + "drwxr-xr-x 3 tcurdt tcurdt 102 Jun 25 03:48 ..\n" + "-rw-r--r-- 1 tcurdt tcurdt 2934 Jun 25 03:48 DependenciesTestCase.class\n" + "-rw-r--r-- 1 tcurdt tcurdt 786 Jun 25 03:48 JarCombiningTestCase$1.class\n" + "drwxr-xr-x 4 tcurdt tcurdt 136 Jun 25 03:48 classes\n" + "\n"; public void testModes() throws Exception { final ByteArrayInputStream is = new ByteArrayInputStream(output.getBytes("UTF-8")); final Mapper mapper = new LsMapper(is); final TarArchiveEntry entry1 = mapper.map(new TarArchiveEntry("trunk/target/test-classes/org/vafer/dependency", true)); assertEquals(493, entry1.getMode()); assertEquals("tcurdt", entry1.getUserName()); assertEquals("tcurdt", entry1.getGroupName()); final TarArchiveEntry entry2 = mapper.map(new TarArchiveEntry("trunk/target/test-classes/org/vafer/dependency/DependenciesTestCase.class", true)); assertEquals(420, entry2.getMode()); assertEquals("tcurdt", entry2.getUserName()); assertEquals("tcurdt", entry2.getGroupName()); } public void testSuccessfulParsing() throws Exception { final ByteArrayInputStream is = new ByteArrayInputStream(output.getBytes("UTF-8")); final Mapper mapper = new LsMapper(is); final TarArchiveEntry unknown = new TarArchiveEntry("xyz", true); assertSame(unknown, mapper.map(unknown)); final TarArchiveEntry known = new TarArchiveEntry("trunk/target/test-classes/org/vafer/dependency", true); final TarArchiveEntry knownMapped = mapper.map(known); assertNotSame(known, knownMapped); } public void testPrematureEOF() throws Exception { final ByteArrayInputStream is = new ByteArrayInputStream(output.substring(0, 200).getBytes("UTF-8")); try { new LsMapper(is); fail("should fail to parse"); } catch (ParseError e) { } } public void testWrongFormat() throws Exception { final ByteArrayInputStream is = new ByteArrayInputStream("asas\n".getBytes("UTF-8")); try { new LsMapper(is); fail("should fail to parse"); } catch (ParseError e) { } } } jdeb/src/test/java/org/vafer/jdeb/maven/0000755000175000017500000000000012207644255020244 5ustar moellermoellerjdeb/src/test/java/org/vafer/jdeb/maven/DataTestCase.java0000644000175000017500000000743312207644255023423 0ustar moellermoeller/* * 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 java.io.FileNotFoundException; import java.io.IOException; import junit.framework.TestCase; /* * Admittedly not the nicest way to assert that failOnMissingSrc functions. However, the best that can be done without * refactoring, mocking, or extending the scope of the test beyond this unit. */ public class DataTestCase extends TestCase { private Data data; private File missingFile; private File file; protected void setUp() throws Exception { data = new Data(); missingFile = new File("this-file-does-not-exist"); file = File.createTempFile(getClass().getSimpleName(), "dat"); } protected void tearDown() throws Exception { if (file != null) { file.delete(); } } public void testFailOnUnknownValue() throws IOException { try { data.setSrc(missingFile); data.setMissingSrc("not a value value"); data.produce(null); fail(); } catch (IllegalArgumentException expected) { } } public void testFailOnMissingSrcDefaultFileMissing() throws IOException { try { data.setSrc(missingFile); data.produce(null); fail(); } catch (FileNotFoundException expected) { } } public void testFailOnMissingSrcIgnoreFileMissing() throws IOException { data.setSrc(missingFile); data.setMissingSrc("ignore"); data.produce(null); } public void testFailOnMissingSrcIgnoreFileMissingVaryInput() throws IOException { data.setSrc(missingFile); data.setMissingSrc(" IGNORE "); data.produce(null); } public void testFailOnMissingSrcFailFileMissing() throws IOException { try { data.setSrc(missingFile); data.setMissingSrc("fail"); data.produce(null); fail(); } catch (FileNotFoundException expected) { } } public void testFailOnMissingSrcDefaultFileExists() throws IOException { IOException unknownTypeException = null; try { data.setSrc(file); data.produce(null); } catch (IOException expected) { unknownTypeException = expected; } assertTrue(unknownTypeException.getMessage().startsWith("Unknown type")); } public void testFailOnMissingSrcIgnoreFileExists() throws IOException { IOException unknownTypeException = null; try { data.setSrc(file); data.setMissingSrc("ignore"); data.produce(null); } catch (IOException expected) { unknownTypeException = expected; } assertTrue(unknownTypeException.getMessage().startsWith("Unknown type")); } public void testFailOnMissingSrcFailFileExists() throws IOException { IOException unknownTypeException = null; try { data.setSrc(file); data.setMissingSrc("fail"); data.produce(null); } catch (IOException expected) { unknownTypeException = expected; } assertTrue(unknownTypeException.getMessage().startsWith("Unknown type")); } } jdeb/src/test/java/org/vafer/jdeb/producers/0000755000175000017500000000000012207644255021144 5ustar moellermoellerjdeb/src/test/java/org/vafer/jdeb/producers/DataProducerPathTemplateTestCase.java0000644000175000017500000001014712207644255030334 0ustar moellermoeller/* * 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.producers; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import junit.framework.TestCase; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.vafer.jdeb.DataConsumer; import org.vafer.jdeb.DataProducer; import org.vafer.jdeb.mapping.Mapper; public class DataProducerPathTemplateTestCase extends TestCase { private static final String[] INCLUDES = { }; private static final String[] EXCLUDES = { }; private CaptureDataConsumer captureDataConsumer = new CaptureDataConsumer(); private Mapper[] mappers = new Mapper[0]; private DataProducer dataProducer; public void testTypical() throws Exception { String[] paths = { "/var/log", "/var/lib" }; dataProducer = new DataProducerPathTemplate(paths, INCLUDES, EXCLUDES, mappers); dataProducer.produce(captureDataConsumer); assertEquals(2, captureDataConsumer.invocations.size()); CaptureDataConsumer.Invocation invocation = captureDataConsumer.invocations.get(0); assertEquals(invocation.dirname, "/var/log"); assertEquals(invocation.gid, 0); assertEquals(invocation.group, "root"); assertEquals(invocation.linkname, ""); assertEquals(invocation.mode, TarArchiveEntry.DEFAULT_DIR_MODE); assertEquals(invocation.size, 0); assertEquals(invocation.uid, 0); assertEquals(invocation.user, "root"); invocation = captureDataConsumer.invocations.get(1); assertEquals(invocation.dirname, "/var/lib"); assertEquals(invocation.gid, 0); assertEquals(invocation.group, "root"); assertEquals(invocation.linkname, ""); assertEquals(invocation.mode, TarArchiveEntry.DEFAULT_DIR_MODE); assertEquals(invocation.size, 0); assertEquals(invocation.uid, 0); assertEquals(invocation.user, "root"); } public class CaptureDataConsumer implements DataConsumer { private List invocations; public CaptureDataConsumer() { invocations = new ArrayList(); } @Override public void onEachDir( String dirname, String linkname, String user, int uid, String group, int gid, int mode, long size ) throws IOException { invocations.add(new Invocation(dirname, linkname, user, uid, group, gid, mode, size)); } @Override public void onEachFile( InputStream input, String filename, String linkname, String user, int uid, String group, int gid, int mode, long size ) throws IOException { } @Override public void onEachLink(String path, String linkName, boolean symlink, String user, int uid, String group, int gid, int mode) throws IOException { } private class Invocation { private String dirname; private String linkname; private String user; private int uid; private String group; private int gid; private int mode; private long size; private Invocation( String dirname, String linkname, String user, int uid, String group, int gid, int mode, long size ) throws IOException { this.dirname = dirname; this.linkname = linkname; this.user = user; this.uid = uid; this.group = group; this.gid = gid; this.mode = mode; this.size = size; } } } } jdeb/src/test/java/org/vafer/jdeb/signing/0000755000175000017500000000000012207644255020574 5ustar moellermoellerjdeb/src/test/java/org/vafer/jdeb/signing/PGPSignerTestCase.java0000644000175000017500000000471412207644255024677 0ustar moellermoeller/* * 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.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.Arrays; import junit.framework.TestCase; public final class PGPSignerTestCase extends TestCase { public void testClearSign() throws Exception { final InputStream ring = getClass().getClassLoader().getResourceAsStream("org/vafer/gpg/secring.gpg"); assertNotNull(ring); String input = "TEST1 \n-TEST2 \n \nTEST3 \n"; final String expectedOutputStr = "-----BEGIN PGP SIGNED MESSAGE-----\n" + "Hash: SHA1\n" + "\n" + "TEST1\n" + "- -TEST2\n" + "\n" + "TEST3\n" + "-----BEGIN PGP SIGNATURE-----\n" + "Version: BCPG v1.48\n" + "\n" + "iEYEARECABAFAkax1rgJEHM9pIAuB02PAABIJgCghFmoCJCZ0CGiqgVLGGPd/Yh5\n" + "FQQAnRVqvI2ij45JQSHYJBblZ0Vv2meN\n" + "=aAAT\n" + "-----END PGP SIGNATURE-----\n"; 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 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)); } private byte[] fixCRLF(byte[] b) { String s = new String(b); s = s.replaceAll("\r\n", "\n"); return s.getBytes(); } } jdeb/src/test/java/org/vafer/jdeb/utils/0000755000175000017500000000000012207644255020276 5ustar moellermoellerjdeb/src/test/java/org/vafer/jdeb/utils/FilteredFileTestCase.java0000644000175000017500000000515712207644255025143 0ustar moellermoeller/* * 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.utils; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.StringReader; import java.util.HashMap; import java.util.Map; import junit.framework.TestCase; import org.apache.tools.ant.util.ReaderInputStream; import org.vafer.jdeb.debian.BinaryPackageControlFile; public class FilteredFileTestCase extends TestCase { private VariableResolver variableResolver; protected void setUp() throws Exception { Map map = new HashMap(); map.put("artifactId", "jdeb"); map.put("myProperty1", "custom1"); map.put("myProperty2", "custom2"); variableResolver = new MapVariableResolver(map); } public void testTokenSubstitution() throws Exception { InputStream in = new ReaderInputStream(new StringReader("#!/bin/sh\ncat [[artifactId]][[myProperty1]] \necho '[[myProperty2]]'\n")); FilteredFile placeHolder = new FilteredFile(in, variableResolver); String actual = placeHolder.toString(); assertEquals("#!/bin/sh\ncat jdebcustom1 \necho 'custom2'\n", actual); } public void testVariableSubstitution() throws Exception { Map map = new HashMap(); map.put("VERSION", "1.2"); map.put("MAINTAINER", "Torsten Curdt "); String controlFile = "Version: [[VERSION]]\n" + "Maintainer: [[MAINTAINER]]\n" + "NoResolve1: test[[test\n" + "NoResolve2: [[test]]\n"; FilteredFile filteredFile = new FilteredFile(new ByteArrayInputStream(controlFile.getBytes()), new MapVariableResolver(map)); BinaryPackageControlFile d = new BinaryPackageControlFile(filteredFile.toString()); assertEquals("1.2", d.get("Version")); assertEquals("Torsten Curdt ", d.get("Maintainer")); assertEquals("test[[test", d.get("NoResolve1")); assertEquals("[[test]]", d.get("NoResolve2")); } } jdeb/src/test/java/org/vafer/jdeb/utils/InformationInputStreamTestCase.java0000644000175000017500000001014712207644255027261 0ustar moellermoeller/* * 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.utils; import java.io.ByteArrayOutputStream; import java.io.InputStream; import junit.framework.TestCase; public class InformationInputStreamTestCase extends TestCase { private InputStream getStream( String file ) { return getClass().getClassLoader().getResourceAsStream("org/vafer/jdeb/utils/" + file); } public void testUTF8CRLF() throws Exception { InformationInputStream informationStream = new InformationInputStream(getStream("utf8-crlf.txt")); Utils.copy(informationStream, new ByteArrayOutputStream()); assertTrue("Should be windows line endings", !informationStream.hasUnixLineEndings()); assertTrue("Shebang not detected", informationStream.isShell()); assertTrue("BOM detected", !informationStream.hasBom()); assertEquals("Encoding", null, informationStream.getEncoding()); } public void testUTF8() throws Exception { InformationInputStream informationStream = new InformationInputStream(getStream("utf8-lf.txt")); Utils.copy(informationStream, new ByteArrayOutputStream()); assertTrue("Shebang not detected", informationStream.isShell()); assertTrue("BOM detected", !informationStream.hasBom()); assertEquals("Encoding", null, informationStream.getEncoding()); } public void testUTF8BOM() throws Exception { InformationInputStream informationStream = new InformationInputStream(getStream("utf8-lf-bom.txt")); Utils.copy(informationStream, new ByteArrayOutputStream()); assertTrue("Shebang not detected", informationStream.isShell()); assertTrue("BOM not detected", informationStream.hasBom()); assertEquals("Encoding", "UTF-8", informationStream.getEncoding()); } public void testUTF16BE() throws Exception { InformationInputStream informationStream = new InformationInputStream(getStream("utf16be-lf.txt")); Utils.copy(informationStream, new ByteArrayOutputStream()); assertTrue("Shebang not detected", informationStream.isShell()); assertTrue("BOM detected", !informationStream.hasBom()); assertEquals("Encoding", "UTF-16BE", informationStream.getEncoding()); } public void testUTF16BEBOM() throws Exception { InformationInputStream informationStream = new InformationInputStream(getStream("utf16be-lf-bom.txt")); Utils.copy(informationStream, new ByteArrayOutputStream()); assertTrue("Shebang not detected", informationStream.isShell()); assertTrue("BOM not detected", informationStream.hasBom()); assertEquals("Encoding", "UTF-16BE", informationStream.getEncoding()); } public void testUTF16LE() throws Exception { InformationInputStream informationStream = new InformationInputStream(getStream("utf16le-lf.txt")); Utils.copy(informationStream, new ByteArrayOutputStream()); assertTrue("Shebang not detected", informationStream.isShell()); assertTrue("BOM detected", !informationStream.hasBom()); assertEquals("Encoding", "UTF-16LE", informationStream.getEncoding()); } public void testUTF16LEBOM() throws Exception { InformationInputStream informationStream = new InformationInputStream(getStream("utf16le-lf-bom.txt")); Utils.copy(informationStream, new ByteArrayOutputStream()); assertTrue("Shebang not detected", informationStream.isShell()); assertTrue("BOM not detected", informationStream.hasBom()); assertEquals("Encoding", "UTF-16LE", informationStream.getEncoding()); } } jdeb/src/test/java/org/vafer/jdeb/utils/UtilsTestCase.java0000644000175000017500000000721612207644255023703 0ustar moellermoeller/* * 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.utils; import java.io.ByteArrayInputStream; import java.util.HashMap; import java.util.Map; import java.util.Calendar; import java.util.GregorianCalendar; import junit.framework.TestCase; public class UtilsTestCase extends TestCase { public void testStripPath() throws Exception { assertEquals("foo/bar", Utils.stripPath(0, "foo/bar")); assertEquals("bar", Utils.stripPath(1, "foo/bar")); assertEquals("bar/baz", Utils.stripPath(1, "foo/bar/baz")); assertEquals("baz", Utils.stripPath(2, "foo/bar/baz")); assertEquals("foo/", Utils.stripPath(0, "foo/")); assertEquals("", Utils.stripPath(1, "foo/")); assertEquals("foo/", Utils.stripPath(2, "foo/")); } private String convert(String s) throws Exception { byte[] data = Utils.toUnixLineEndings(new ByteArrayInputStream(s.getBytes("UTF-8"))); return new String(data, "UTF-8"); } public void testNewlineConversionLF() throws Exception { String expected = "test\ntest\n\ntest\n"; String actual = convert("test\ntest\n\ntest"); assertEquals(expected, actual); } public void testNewlineConversionCRLF() throws Exception { String expected = "test\ntest\n\ntest\n"; String actual = convert("test\r\ntest\r\n\r\ntest"); assertEquals(expected, actual); } public void testNewlineConversionCR() throws Exception { String expected = "test\ntest\n\ntest\n"; String actual = convert("test\rtest\r\rtest"); assertEquals(expected, actual); } public void testReplaceVariables() { Map variables = new HashMap(); variables.put("version", "1.2.3"); variables.put("name", "jdeb"); variables.put("url", "https://github.com/tcurdt/jdeb"); VariableResolver resolver = new MapVariableResolver(variables); // main case String result = Utils.replaceVariables(resolver, "Version: [[version]]", "[[", "]]"); assertEquals("Version: 1.2.3", result); // multiple variables in the same expression result = Utils.replaceVariables(resolver, "[[name]] [[version]]", "[[", "]]"); assertEquals("jdeb 1.2.3", result); // collision with script syntax result = Utils.replaceVariables(resolver, "if [[ \"${HOST_TYPE}\" -eq \"admin\" ]] ; then", "[[", "]]"); assertEquals("if [[ \"${HOST_TYPE}\" -eq \"admin\" ]] ; then", result); // mixed valid and unknown variables result = Utils.replaceVariables(resolver, "[[name]] [[test]]", "[[", "]]"); assertEquals("jdeb [[test]]", 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())); } } jdeb/src/test/resources/0000755000175000017500000000000012207644255015431 5ustar moellermoellerjdeb/src/test/resources/org/0000755000175000017500000000000012207644255016220 5ustar moellermoellerjdeb/src/test/resources/org/vafer/0000755000175000017500000000000012207644255017323 5ustar moellermoellerjdeb/src/test/resources/org/vafer/gpg/0000755000175000017500000000000012207644255020100 5ustar moellermoellerjdeb/src/test/resources/org/vafer/gpg/fingerprint.txt0000644000175000017500000000032312207644255023166 0ustar moellermoellerpub 1024D/2E074D8F 2007-08-02 Key fingerprint = 5A17 CB12 37F0 85BC 8264 E649 733D A480 2E07 4D8F uid Unit test user (only for testing) sub 2048g/5E8CA506 2007-08-02 jdeb/src/test/resources/org/vafer/gpg/pubring.gpg0000644000175000017500000000223612207644255022250 0ustar moellermoellerFv# VUmZXs M@8k'&$7bI+uJ'H D%OAISvw:HD >#2yw #cxY8({GE^uI^+,?y,Z+C4ue;W)PpThfSV>k sbKF۽i6ib 7|pBҝhv,bb#㸍tI+ ,BveH^cT'"N4w[ Ѽ@6N= OT=6vKh~L葴2Unit test user (only for testing) ` Fv  s=.M~WC.iGHC.Z4ݠ䴽?C}IW6;Ұ F|0z Vb?rI q4;ҡ^U8Q;[^>"@Z7 JxFȒO wOs%t0"Z/,.n~&#2yw #cxY8({GE^uI^+,?y,Z+C4ue;W)PpThfSV>k sbKF۽i6ib 7|pBҝhv,bb#㸍tI+ ,BveH^cT'"N4w[ Ѽ@6N= OT=6vKh~LЇ`fT)4t<G%{ė ଷ7J P42Unit test user (only for testing) ` Fv  s=.M~WC.iGHC.Z4ݠ䴽?C}IW6;ҰcF|0z Vb?rI q4;ҡ^U8Q;[^>"@Z7 JxFȒO wOs%t0"Z/,.n~&x䟈C5~lI F| s=.MdGyV=>fzgQӈE3mjdeb/src/test/resources/org/vafer/jdeb/0000755000175000017500000000000012207644255020227 5ustar moellermoellerjdeb/src/test/resources/org/vafer/jdeb/ar/0000755000175000017500000000000012207644255020631 5ustar moellermoellerjdeb/src/test/resources/org/vafer/jdeb/ar/data.ar0000644000175000017500000000033012207644255022062 0ustar moellermoeller! data.tgz 1195927949 501 501 100644 148 ` iHGA 0@9JnLL jQ7Y-2qP{!gmbj^/sJu_{Lǘc[);] * debian changes supportjdeb/src/test/resources/org/vafer/jdeb/deb/0000755000175000017500000000000012207644255020761 5ustar moellermoellerjdeb/src/test/resources/org/vafer/jdeb/deb/control/0000755000175000017500000000000012207644255022441 5ustar moellermoellerjdeb/src/test/resources/org/vafer/jdeb/deb/control/control0000644000175000017500000000043712207644255024050 0ustar moellermoellerPackage: test Version: 1.0.1 Section: misc Priority: optional Architecture: i386 Depends: some-package Maintainer: John Doe Distribution: development Description: revision @REVISION@, test package This is a sample package control file. . Use for testing purposes only. jdeb/src/test/resources/org/vafer/jdeb/deb/control/postinst0000644000175000017500000000010612207644255024244 0ustar moellermoeller#!/bin/sh # # Post installation script for [[name]] [[version]] # jdeb/src/test/resources/org/vafer/jdeb/deb/control/prerm0000644000175000017500000000010012207644255023500 0ustar moellermoeller#!/bin/sh # # Pre removal script for [[name]] [[version]] # jdeb/src/test/resources/org/vafer/jdeb/deb/data.tar.bz20000644000175000017500000000024412207644255023076 0ustar moellermoellerBZh91AY&SY{@s JCGb2m Q=M4@2mLrR ]XDCUqMto9&h,#d,h2,^9 e:_ŒI<1bKf44IlYf)„o5jdeb/src/test/resources/org/vafer/jdeb/deb/data.tgz0000644000175000017500000000022412207644255022416 0ustar moellermoelleriHGA 0@9JnLL jQ7Y-2qP{!gmbj^/sJu_{Lǘc[);] jdeb/target/0000755000175000017500000000000012207661047013135 5ustar moellermoellerjdeb/pom.xml0000644000175000017500000002675712207657701013207 0ustar moellermoeller 4.0.0 org.vafer jdeb maven-plugin jdeb 1.0.2-SNAPSHOT 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. http://github.com/tcurdt/jdeb tcurdt Torsten Curdt tcurdt at apache.org Lead Developer +1 ebourg Emmanuel Bourg ebourg at apache.org +1 tmortagne Thomas Mortagne thomas.mortagne at gmail.com +1 Bryan Sant Christian Rigdon Elliot West Jeroen Rosenberg Manuel Woelker Patrick Schultz Petr Kozelka Scott Kuehn Ralph van Etten Alexander Horz Apache License 2 http://www.apache.org/licenses/LICENSE-2.0.txt repo scm:git:git://github.com:tcurdt/jdeb.git scm:git:git://github.com:tcurdt/jdeb.git http://github.com/tcurdt/jdeb/tree/master UTF-8 UTF-8 1.6 1.6 maven-site-plugin 3.1 org.apache.maven.plugins maven-compiler-plugin 2.5.1 ${maven.compiler.source} ${maven.compiler.target} ${project.build.sourceEncoding} org.apache.maven.plugins maven-shade-plugin 1.7.1 package shade true org.apache.commons:commons-compress commons-io:commons-io org.apache.commons org.vafer.jdeb.shaded.compress org.apache.maven.plugins maven-surefire-plugin 2.11 never **/*TestCase.java **/Abstract* false false org.apache.maven.plugins maven-invoker-plugin 1.6 src/it ${project.build.directory}/it setup verify ${project.build.directory}/local-repo src/it/settings.xml */pom.xml integration-test commons-io commons-io 2.4 org.apache.commons commons-compress 1.5 org.apache.maven maven-core 2.2.1 org.apache.maven maven-plugin-api 2.2.1 org.apache.maven maven-project 2.2.1 org.apache.maven maven-artifact 2.2.1 org.codehaus.plexus plexus-utils 1.4.1 org.apache.ant ant 1.7.1 org.bouncycastle bcpg-jdk15on 1.48 junit junit 3.8.2 test true ${project.build.directory}/site org.apache.maven.plugins maven-project-info-reports-plugin 2.4 false false project-team dependencies license scm org.apache.maven.plugins maven-javadoc-plugin 2.8.1 true http://java.sun.com/javase/6/docs/api org.apache.maven.plugins maven-surefire-report-plugin 2.12 org.apache.maven.plugins maven-pmd-plugin 2.7.1 org.apache.maven.plugins maven-jxr-plugin 2.3 org.codehaus.mojo taglist-maven-plugin 2.4 FIXME TODO @todo @deprecated true