001 /*
002 * Copyright 2005 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 * AntTask for creating debian archives.
037 * Even supports signed changes files.
038 *
039 * @author Torsten Curdt <tcurdt@vafer.org>
040 */
041
042 public class DebAntTask extends MatchingTask {
043
044 /** The Debian package produced */
045 private File deb;
046
047 /** The directory containing the control files to build the package */
048 private File control;
049
050 /** The file containing the PGP keys */
051 private File keyring;
052
053 /** The key to use in the keyring */
054 private String key;
055
056 /** The passphrase for the key to sign the changes file */
057 private String passphrase;
058
059 /** The file to read the changes from */
060 private File changesIn;
061
062 /** The file where to write the changes to */
063 private File changesOut;
064
065 /** The file where to write the changes of the changes input to */
066 private File changesSave;
067
068 /** The compression method used for the data file (none, gzip or bzip2) */
069 private String compression = "gzip";
070
071 /** Trigger the verbose mode detailing all operations */
072 private boolean verbose;
073
074 private Collection dataProducers = new ArrayList();
075
076
077 public void setDestfile( File deb ) {
078 this.deb = deb;
079 }
080
081 public void setControl( File control ) {
082 this.control = control;
083 }
084
085 public void setChangesIn( File changes ) {
086 this.changesIn = changes;
087 }
088
089 public void setChangesOut( File changes ) {
090 this.changesOut = changes;
091 }
092
093 public void setChangesSave( File changes ) {
094 this.changesSave = changes;
095 }
096
097 public void setKeyring( File keyring ) {
098 this.keyring = keyring;
099 }
100
101 public void setKey( String key ) {
102 this.key = key;
103 }
104
105 public void setPassphrase( String passphrase ) {
106 this.passphrase = passphrase;
107 }
108
109 public void setCompression(String compression) {
110 this.compression = compression;
111 }
112
113 public void setVerbose(boolean verbose) {
114 this.verbose = verbose;
115 }
116
117 public void addFileSet(FileSet fileset) {
118 dataProducers.add(new FileSetDataProducer(fileset));
119 }
120
121 public void addTarFileSet(Tar.TarFileSet fileset) {
122 dataProducers.add(new FileSetDataProducer(fileset));
123 }
124
125 public void addData( Data data ) {
126 dataProducers.add(data);
127 }
128
129 private boolean isPossibleOutput( File file ) {
130
131 if (file.exists()) {
132 return file.isFile() && file.canWrite();
133 }
134
135 return true;
136 }
137
138 public void execute() {
139
140 if (control == null || !control.isDirectory()) {
141 throw new BuildException("You need to point the 'control' attribute to the control directory.");
142 }
143
144 if (changesIn != null) {
145
146 if (!changesIn.isFile() || !changesIn.canRead()) {
147 throw new BuildException("The 'changesIn' attribute needs to point to a readable file. " + changesIn + " was not found/readable.");
148 }
149
150 if (changesOut == null) {
151 throw new BuildException("A 'changesIn' without a 'changesOut' does not make much sense.");
152 }
153
154 if (!isPossibleOutput(changesOut)) {
155 throw new BuildException("Cannot write the output for 'changesOut' to " + changesOut);
156 }
157
158 if (changesSave != null && !isPossibleOutput(changesSave)) {
159 throw new BuildException("Cannot write the output for 'changesSave' to " + changesSave);
160 }
161
162 } else {
163 if (changesOut != null || changesSave != null) {
164 throw new BuildException("The 'changesOut' or 'changesSave' attributes may only be used when there is a 'changesIn' specified.");
165 }
166 }
167
168 if (!"gzip".equals(compression) && !"bzip2".equals(compression) && !"none".equals(compression)) {
169 throw new BuildException("The compression method '" + compression + "' is not supported");
170 }
171
172 if (dataProducers.size() == 0) {
173 throw new BuildException("You need to provide at least one reference to a tgz or directory with data.");
174 }
175
176 if (deb == null) {
177 throw new BuildException("You need to point the 'destfile' attribute to where the deb is supposed to be created.");
178 }
179
180 final File[] controlFiles = control.listFiles();
181
182 final DataProducer[] data = new DataProducer[dataProducers.size()];
183 dataProducers.toArray(data);
184
185 final Processor processor = new Processor(new Console() {
186 public void println(String s) {
187 if (verbose) {
188 log(s);
189 }
190 }
191 }, null);
192
193 final PackageDescriptor packageDescriptor;
194 try {
195
196 log("Creating debian package: " + deb);
197
198 packageDescriptor = processor.createDeb(controlFiles, data, deb, compression);
199
200 } catch (Exception e) {
201 throw new BuildException("Failed to create debian package " + deb, e);
202 }
203
204 final TextfileChangesProvider changesProvider;
205
206 try {
207 if (changesOut == null) {
208 return;
209 }
210
211 log("Creating changes file: " + changesOut);
212
213 // for now only support reading the changes form a textfile provider
214 changesProvider = new TextfileChangesProvider(new FileInputStream(changesIn), packageDescriptor);
215
216 processor.createChanges(packageDescriptor, changesProvider, (keyring!=null)?new FileInputStream(keyring):null, key, passphrase, new FileOutputStream(changesOut));
217
218 } catch (Exception e) {
219 throw new BuildException("Failed to create debian changes file " + changesOut, e);
220 }
221
222 try {
223 if (changesSave == null) {
224 return;
225 }
226
227 log("Saving changes to file: " + changesSave);
228
229 changesProvider.save(new FileOutputStream(changesSave));
230
231 } catch (Exception e) {
232 throw new BuildException("Failed to save debian changes file " + changesSave, e);
233 }
234
235 }
236 }