001 /*
002 * Copyright 2010 The Apache Software Foundation.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.vafer.jdeb.ant;
017
018 import java.io.File;
019 import java.io.FileInputStream;
020 import java.io.FileOutputStream;
021 import java.util.ArrayList;
022 import java.util.Collection;
023
024 import org.apache.tools.ant.BuildException;
025 import org.apache.tools.ant.taskdefs.MatchingTask;
026 import org.apache.tools.ant.taskdefs.Tar;
027 import org.apache.tools.ant.types.FileSet;
028 import org.vafer.jdeb.Console;
029 import org.vafer.jdeb.DataProducer;
030 import org.vafer.jdeb.Processor;
031 import org.vafer.jdeb.changes.TextfileChangesProvider;
032 import org.vafer.jdeb.descriptors.PackageDescriptor;
033 import org.vafer.jdeb.producers.FileSetDataProducer;
034
035 /**
036 * TODO generalize with DebMaker
037 *
038 * AntTask for creating debian archives.
039 * Even supports signed changes files.
040 *
041 * @author Torsten Curdt <tcurdt@vafer.org>
042 */
043
044 public class DebAntTask extends MatchingTask {
045
046 /** The Debian package produced */
047 private File deb;
048
049 /** The directory containing the control files to build the package */
050 private File control;
051
052 /** The file containing the PGP keys */
053 private File keyring;
054
055 /** The key to use in the keyring */
056 private String key;
057
058 /** The passphrase for the key to sign the changes file */
059 private String passphrase;
060
061 /** The file to read the changes from */
062 private File changesIn;
063
064 /** The file where to write the changes to */
065 private File changesOut;
066
067 /** The file where to write the changes of the changes input to */
068 private File changesSave;
069
070 /** The compression method used for the data file (none, gzip or bzip2) */
071 private String compression = "gzip";
072
073 /** Trigger the verbose mode detailing all operations */
074 private boolean verbose;
075
076 private Collection dataProducers = new ArrayList();
077
078
079 public void setDestfile( File deb ) {
080 this.deb = deb;
081 }
082
083 public void setControl( File control ) {
084 this.control = control;
085 }
086
087 public void setChangesIn( File changes ) {
088 this.changesIn = changes;
089 }
090
091 public void setChangesOut( File changes ) {
092 this.changesOut = changes;
093 }
094
095 public void setChangesSave( File changes ) {
096 this.changesSave = changes;
097 }
098
099 public void setKeyring( File keyring ) {
100 this.keyring = keyring;
101 }
102
103 public void setKey( String key ) {
104 this.key = key;
105 }
106
107 public void setPassphrase( String passphrase ) {
108 this.passphrase = passphrase;
109 }
110
111 public void setCompression( String compression ) {
112 this.compression = compression;
113 }
114
115 public void setVerbose( boolean verbose ) {
116 this.verbose = verbose;
117 }
118
119 public void addFileSet( FileSet fileset ) {
120 dataProducers.add(new FileSetDataProducer(fileset));
121 }
122
123 public void addTarFileSet( Tar.TarFileSet fileset ) {
124 dataProducers.add(new FileSetDataProducer(fileset));
125 }
126
127 public void addData( Data data ) {
128 dataProducers.add(data);
129 }
130
131 private boolean isPossibleOutput( File file ) {
132
133 if (file.exists()) {
134 return file.isFile() && file.canWrite();
135 }
136
137 return true;
138 }
139
140 public void execute() {
141
142 if (control == null || !control.isDirectory()) {
143 throw new BuildException("You need to point the 'control' attribute to the control directory.");
144 }
145
146 if (changesIn != null) {
147
148 if (!changesIn.isFile() || !changesIn.canRead()) {
149 throw new BuildException("The 'changesIn' attribute needs to point to a readable file. " + changesIn + " was not found/readable.");
150 }
151
152 if (changesOut == null) {
153 throw new BuildException("A 'changesIn' without a 'changesOut' does not make much sense.");
154 }
155
156 if (!isPossibleOutput(changesOut)) {
157 throw new BuildException("Cannot write the output for 'changesOut' to " + changesOut);
158 }
159
160 if (changesSave != null && !isPossibleOutput(changesSave)) {
161 throw new BuildException("Cannot write the output for 'changesSave' to " + changesSave);
162 }
163
164 } else {
165 if (changesOut != null || changesSave != null) {
166 throw new BuildException("The 'changesOut' or 'changesSave' attributes may only be used when there is a 'changesIn' specified.");
167 }
168 }
169
170 if (!"gzip".equals(compression) && !"bzip2".equals(compression) && !"none".equals(compression)) {
171 throw new BuildException("The compression method '" + compression + "' is not supported");
172 }
173
174 if (dataProducers.size() == 0) {
175 throw new BuildException("You need to provide at least one reference to a tgz or directory with data.");
176 }
177
178 if (deb == null) {
179 throw new BuildException("You need to point the 'destfile' attribute to where the deb is supposed to be created.");
180 }
181
182 final File[] controlFiles = control.listFiles();
183
184 final DataProducer[] data = new DataProducer[dataProducers.size()];
185 dataProducers.toArray(data);
186
187 final Processor processor = new Processor(new Console() {
188 public void println(String s) {
189 if (verbose) {
190 log(s);
191 }
192 }
193 }, null);
194
195 final PackageDescriptor packageDescriptor;
196 try {
197
198 log("Creating debian package: " + deb);
199
200 packageDescriptor = processor.createDeb(controlFiles, data, deb, compression);
201
202 } catch (Exception e) {
203 throw new BuildException("Failed to create debian package " + deb, e);
204 }
205
206 final TextfileChangesProvider changesProvider;
207
208 try {
209 if (changesOut == null) {
210 return;
211 }
212
213 log("Creating changes file: " + changesOut);
214
215 // for now only support reading the changes form a textfile provider
216 changesProvider = new TextfileChangesProvider(new FileInputStream(changesIn), packageDescriptor);
217
218 processor.createChanges(packageDescriptor, changesProvider, (keyring!=null)?new FileInputStream(keyring):null, key, passphrase, new FileOutputStream(changesOut));
219
220 } catch (Exception e) {
221 throw new BuildException("Failed to create debian changes file " + changesOut, e);
222 }
223
224 try {
225 if (changesSave == null) {
226 return;
227 }
228
229 log("Saving changes to file: " + changesSave);
230
231 changesProvider.save(new FileOutputStream(changesSave));
232
233 } catch (Exception e) {
234 throw new BuildException("Failed to save debian changes file " + changesSave, e);
235 }
236
237 }
238 }