comparison lib/mod/src/de/masters_of_disaster/ant/tasks/deb/Deb.java @ 33:3d86f0391168

Work on improving the build system.
author David Barts <davidb@stashtea.com>
date Fri, 24 Apr 2020 19:45:57 -0700
parents
children
comparison
equal deleted inserted replaced
32:c06edc56669b 33:3d86f0391168
1 package de.masters_of_disaster.ant.tasks.deb;
2
3 import de.masters_of_disaster.ant.tasks.ar.Ar;
4 import de.masters_of_disaster.ant.tasks.ar.Ar.ArFileSet;
5 import java.io.File;
6 import java.util.Enumeration;
7 import java.util.Vector;
8 import org.apache.tools.ant.BuildException;
9 import org.apache.tools.ant.Project;
10 import org.apache.tools.ant.Task;
11 import org.apache.tools.ant.taskdefs.Checksum;
12 import org.apache.tools.ant.taskdefs.Echo;
13 import org.apache.tools.ant.taskdefs.Echo.EchoLevel;
14 import org.apache.tools.ant.taskdefs.Mkdir;
15 import org.apache.tools.ant.taskdefs.MatchingTask;
16 import org.apache.tools.ant.taskdefs.Tar;
17 import org.apache.tools.ant.taskdefs.Tar.TarCompressionMethod;
18 import org.apache.tools.ant.taskdefs.Tar.TarFileSet;
19 import org.apache.tools.ant.util.FileUtils;
20 import org.apache.tools.ant.util.MergingMapper;
21 import org.apache.tools.ant.util.SourceFileScanner;
22
23 /**
24 * Creates a deb package.
25 *
26 * @ant.task category="packaging"
27 */
28 public class Deb extends MatchingTask {
29 Vector controlFileSets = new Vector();
30 Vector dataFileSets = new Vector();
31 File baseDir;
32 File destFile;
33 File tempDir;
34 boolean deleteTempFiles = true;
35 boolean includeMd5sums = false;
36 Tar controlTarGz = new Tar();
37 Tar dataTarGz = new Tar();
38 Ar debPackage = new Ar();
39
40 {
41 fileset = dataTarGz.createTarFileSet();
42 }
43
44 /**
45 * Add a new fileset for the control files with the option to specify permissions
46 *
47 * @return the tar fileset to be used as the nested element.
48 */
49 public TarFileSet createControlFileSet() {
50 TarFileSet fileSet = controlTarGz.createTarFileSet();
51 controlFileSets.addElement(fileSet);
52 return fileSet;
53 }
54
55 /**
56 * Add a new fileset for the data files with the option to specify permissions
57 *
58 * @return the tar fileset to be used as the nested element.
59 */
60 public TarFileSet createDataFileSet() {
61 TarFileSet fileSet = dataTarGz.createTarFileSet();
62 dataFileSets.addElement(fileSet);
63 return fileSet;
64 }
65
66 /**
67 * Set the name/location of where to create the deb file.
68 *
69 * @param destFile The output of the deb
70 */
71 public void setDestFile(File destFile) {
72 this.destFile = destFile;
73 debPackage.setDestFile(destFile);
74 }
75
76 /**
77 * This is the base directory to look in for things to include in the data files.
78 *
79 * @param baseDir the base directory.
80 */
81 public void setBaseDir(File baseDir) {
82 this.baseDir = baseDir;
83 fileset.setDir(baseDir);
84 }
85
86 /**
87 * This is the temp directory where to create the temporary files.
88 * If not set, the current projects baseDir is used.
89 *
90 * @param tempDir the temp directory.
91 */
92 public void setTempDir(File tempDir) {
93 this.tempDir = tempDir;
94 }
95
96 /**
97 * This specifies if the temporary files should get deleted.
98 *
99 * @param deleteTempFiles whether to delete the temporary files or not.
100 */
101 public void setDeleteTempFiles(boolean deleteTempFiles) {
102 this.deleteTempFiles = deleteTempFiles;
103 }
104
105 /**
106 * This specifies if the MD5 sums of the files in the data section should be
107 * included in the file "md5sums" in the control section.
108 *
109 * @param includeMd5sums whether to include MD5 sums in the control section or not.
110 */
111 public void setIncludeMd5sums(boolean includeMd5sums) {
112 this.includeMd5sums = includeMd5sums;
113 }
114
115 /**
116 * do the business
117 *
118 * @throws BuildException on error
119 */
120 public void execute() throws BuildException {
121 prepareTask(controlTarGz);
122 prepareTask(dataTarGz);
123 prepareTask(debPackage);
124 TarFileSet tarFileSet = controlTarGz.createTarFileSet();
125 tarFileSet.setFile(new File(System.getProperty("user.dir")));
126 tarFileSet.setUserName("root");
127 tarFileSet.setGroup("root");
128 tarFileSet.setFullpath("./");
129 tarFileSet = dataTarGz.createTarFileSet();
130 tarFileSet.setFile(new File(System.getProperty("user.dir")));
131 tarFileSet.setUserName("root");
132 tarFileSet.setGroup("root");
133 tarFileSet.setFullpath("./");
134
135 if (null == tempDir) {
136 tempDir = getProject().getBaseDir();
137 }
138
139 if (null != baseDir) {
140 // add the main fileset to the list of filesets to process.
141 dataFileSets.addElement(fileset);
142 } else {
143 fileset.setDir(new File(System.getProperty("user.dir")));
144 fileset.setExcludes("**");
145 }
146
147 boolean controlFound = false;
148 for (Enumeration e=controlFileSets.elements() ; e.hasMoreElements() ; ) {
149 TarFileSet fileSet = (TarFileSet)e.nextElement();
150 String[] files = fileSet.getFiles(getProject());
151 int i = 0;
152 int c;
153
154 for (c=files.length ; i<c && !controlFound ; i++) {
155 if (files[i].endsWith("control")
156 && (new File(fileSet.getDir(getProject()),files[i])).isFile()) {
157 controlFound = true;
158 }
159 }
160 }
161 if (!controlFound) {
162 throw new BuildException("The control fileset must contain a file \"control\"", getLocation());
163 }
164
165 // check if deb is out of date with respect to each fileset
166 boolean upToDate = true;
167 for (Enumeration e=controlFileSets.elements() ; e.hasMoreElements() ; ) {
168 TarFileSet fileSet = (TarFileSet)e.nextElement();
169 String[] files = fileSet.getFiles(getProject());
170
171 if (!packageIsUpToDate(files,fileSet.getDir(getProject()))) {
172 upToDate = false;
173 }
174 }
175
176 for (Enumeration e=dataFileSets.elements() ; e.hasMoreElements() ; ) {
177 TarFileSet fileSet = (TarFileSet)e.nextElement();
178 String[] files = fileSet.getFiles(getProject());
179
180 if (!packageIsUpToDate(files,fileSet.getDir(getProject()))) {
181 upToDate = false;
182 }
183 }
184
185 if (upToDate) {
186 log("Nothing to do: " + destFile.getAbsolutePath()
187 + " is up to date.", Project.MSG_INFO);
188 return;
189 }
190
191 log("Building deb: " + destFile.getAbsolutePath(), Project.MSG_INFO);
192
193 Mkdir mkdir = new Mkdir();
194 prepareTask(mkdir);
195 mkdir.setDir(tempDir);
196 mkdir.perform();
197
198 EchoLevel echoLevel = new EchoLevel();
199 echoLevel.setValue("error");
200 File debianBinaryFile = new File(tempDir,"debian-binary");
201 Echo echo = new Echo();
202 prepareTask(echo);
203 echo.setFile(debianBinaryFile);
204 echo.setLevel(echoLevel);
205 echo.setMessage("2.0\n");
206 echo.perform();
207
208 for (Enumeration e=controlFileSets.elements() ; e.hasMoreElements() ; ) {
209 TarFileSet fileSet = (TarFileSet)e.nextElement();
210 String prefix = fileSet.getPrefix();
211 String fullpath = fileSet.getFullpath();
212 if ("".equals(fullpath) && !prefix.startsWith("./")) {
213 if (prefix.startsWith("/")) {
214 fileSet.setPrefix("." + prefix);
215 } else {
216 fileSet.setPrefix("./" + prefix);
217 }
218 }
219 if ((fullpath.length() > 0) && !fullpath.startsWith("./")) {
220 fileSet.setPrefix("");
221 if (fullpath.startsWith("/")) {
222 fileSet.setFullpath("." + fullpath);
223 } else {
224 fileSet.setFullpath("./" + fullpath);
225 }
226 }
227 if ((0 == fileSet.getUid()) && ("" == fileSet.getUserName())) {
228 fileSet.setUserName("root");
229 }
230 if ((0 == fileSet.getGid()) && ("" == fileSet.getGroup())) {
231 fileSet.setGroup("root");
232 }
233 }
234
235 for (Enumeration e=dataFileSets.elements() ; e.hasMoreElements() ; ) {
236 TarFileSet fileSet = (TarFileSet)e.nextElement();
237 String prefix = fileSet.getPrefix();
238 String fullpath = fileSet.getFullpath();
239 if ("".equals(fullpath) && !prefix.startsWith("./")) {
240 if (prefix.startsWith("/")) {
241 fileSet.setPrefix("." + prefix);
242 } else {
243 fileSet.setPrefix("./" + prefix);
244 }
245 }
246 if ((fullpath.length() > 0) && !fullpath.startsWith("./")) {
247 fileSet.setPrefix("");
248 if (fullpath.startsWith("/")) {
249 fileSet.setFullpath("." + fullpath);
250 } else {
251 fileSet.setFullpath("./" + fullpath);
252 }
253 }
254 if ((0 == fileSet.getUid()) && ("" == fileSet.getUserName())) {
255 fileSet.setUserName("root");
256 }
257 if ((0 == fileSet.getGid()) && ("" == fileSet.getGroup())) {
258 fileSet.setGroup("root");
259 }
260 }
261
262 File md5sumsFile = new File(tempDir,"md5sums");
263 if (includeMd5sums) {
264 Checksum md5 = new Checksum();
265 prepareTask(md5);
266 int md5Count = 0;
267 StringBuffer md5sums = new StringBuffer();
268 for (Enumeration e=dataFileSets.elements() ; e.hasMoreElements() ; ) {
269 TarFileSet fileSet = (TarFileSet)e.nextElement();
270 String[] files = fileSet.getDirectoryScanner(getProject()).getIncludedFiles();
271 File fileSetDir = fileSet.getDir(getProject());
272 for (int i=0, c=files.length ; i<c ; i++) {
273 md5.setFile(new File(fileSetDir,files[i]));
274 md5.setProperty("md5_"+md5Count);
275 md5.perform();
276 md5sums.append(getProject().getProperty("md5_"+md5Count)).append(" ");
277 String fullpath = fileSet.getFullpath();
278 if (fullpath.length() > 0) {
279 md5sums.append(fullpath.substring(2));
280 } else {
281 md5sums.append(fileSet.getPrefix().substring(2)).append(files[i].replace('\\','/'));
282 }
283 md5sums.append("\n");
284 md5Count++;
285 }
286 }
287 echo = new Echo();
288 prepareTask(echo);
289 echo.setFile(md5sumsFile);
290 echo.setLevel(echoLevel);
291 echo.setMessage(md5sums.toString());
292 echo.perform();
293 tarFileSet = controlTarGz.createTarFileSet();
294 tarFileSet.setFile(md5sumsFile);
295 tarFileSet.setUserName("root");
296 tarFileSet.setGroup("root");
297 tarFileSet.setPrefix("./");
298 }
299
300 TarCompressionMethod tarCompressionMethod = new TarCompressionMethod();
301 tarCompressionMethod.setValue("gzip");
302 controlTarGz.setCompression(tarCompressionMethod);
303 File controlTarGzFile = new File(tempDir,"control.tar.gz");
304 controlTarGz.setDestFile(controlTarGzFile);
305 controlTarGz.perform();
306
307 dataTarGz.setCompression(tarCompressionMethod);
308 File dataTarGzFile = new File(tempDir,"data.tar.gz");
309 dataTarGz.setDestFile(dataTarGzFile);
310 dataTarGz.perform();
311
312 FileUtils.delete(destFile);
313 ArFileSet fileSet = debPackage.createArFileSet();
314 fileSet.setFile(debianBinaryFile);
315 fileSet = debPackage.createArFileSet();
316 fileSet.setFile(controlTarGzFile);
317 fileSet = debPackage.createArFileSet();
318 fileSet.setFile(dataTarGzFile);
319 debPackage.perform();
320
321 if (deleteTempFiles) {
322 FileUtils.delete(debianBinaryFile);
323 FileUtils.delete(controlTarGzFile);
324 FileUtils.delete(dataTarGzFile);
325 FileUtils.delete(md5sumsFile);
326 }
327 }
328
329 /**
330 * Checks whether the package is up to date in relationship to a list of files.
331 *
332 * @param files the files to check
333 * @param dir the base directory for the files.
334 * @return true if the archive is up to date.
335 */
336 protected boolean packageIsUpToDate(String[] files, File dir) {
337 SourceFileScanner sfs = new SourceFileScanner(this);
338 MergingMapper mm = new MergingMapper();
339 mm.setTo(destFile.getAbsolutePath());
340 return sfs.restrict(files, dir, null, mm).length == 0;
341 }
342
343 /**
344 * Prepares a task for execution.
345 *
346 * @param task the task to prepare
347 */
348 protected void prepareTask(Task task) {
349 task.setProject(getProject());
350 task.setOwningTarget(getOwningTarget());
351 task.setTaskName(getTaskName());
352 task.setTaskType(getTaskType());
353 }
354 }