]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/lib/linux/rpmfactory/CreateSrpm.java
Save current state even if not completely stable
[gpl/argeo-slc.git] / runtime / org.argeo.slc.support.simple / src / main / java / org / argeo / slc / lib / linux / rpmfactory / CreateSrpm.java
1 package org.argeo.slc.lib.linux.rpmfactory;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.OutputStream;
7 import java.util.ArrayList;
8 import java.util.List;
9
10 import org.apache.commons.exec.Executor;
11 import org.apache.commons.io.FileUtils;
12 import org.apache.commons.io.IOUtils;
13 import org.apache.commons.logging.Log;
14 import org.apache.commons.logging.LogFactory;
15 import org.argeo.slc.SlcException;
16 import org.argeo.slc.core.execution.tasks.SystemCall;
17 import org.springframework.core.io.Resource;
18 import org.springframework.core.io.UrlResource;
19
20 /** Generates an SRPM from a spec file */
21 public class CreateSrpm implements Runnable {
22 private final static Log log = LogFactory.getLog(CreateSrpm.class);
23
24 private File topdir;
25
26 /** Directory where to cache downloaded distributions. */
27 private File distributionCache;
28
29 private Resource specFile;
30
31 private RpmBuildEnvironment rpmBuildEnvironment;
32
33 private Boolean overwriteSources = false;
34
35 private File srpmFile;
36
37 private Executor executor;
38
39 public void run() {
40 File sourcesDir = new File(topdir, "SOURCES");
41 sourcesDir.mkdirs();
42 File specsDir = new File(topdir, "SPECS");
43 File srpmsDir = new File(topdir, "SRPMS");
44
45 try {
46 // Parse spec file and copy required resources
47 RpmSpecFile spec = new RpmSpecFile(specFile);
48 copyToSources(spec, sourcesDir);
49
50 // Copy spec file
51 File targetFile = new File(specsDir, specFile.getFilename())
52 .getCanonicalFile();
53 copyResourceToFile(specFile, targetFile);
54
55 // Generate rpmbuild config files
56 rpmBuildEnvironment.writeRpmbuildConfigFiles(topdir);
57
58 // Build SRPM
59 srpmsDir.mkdirs();
60 SystemCall packageSrpm = new SystemCall();
61 packageSrpm.arg("rpmbuild");
62 packageSrpm.arg("-bs").arg("--nodeps");
63 packageSrpm.arg("--rcfile=rpmrc");
64 packageSrpm.arg("--macros=" + RpmBuildEnvironment.defaultMacroFiles
65 + ":rpmmacros");
66 // buildSrpm.arg("-D", "_topdir " + topdir.getCanonicalPath() + "");
67 packageSrpm.arg("SPECS/" + specFile.getFilename());
68 packageSrpm.setExecDir(topdir.getCanonicalPath());
69 packageSrpm.setLogCommand(true);
70
71 // Execute
72 packageSrpm.setExecutor(executor);
73 String answer = packageSrpm.function();
74
75 // Extract generated SRPM path
76 // TODO: make it safer
77 String srpmPath = answer.split(":")[1].trim();
78 srpmFile = new File(srpmPath);
79 } catch (IOException e) {
80 throw new SlcException("Cannot generate SRPM from " + specFile, e);
81 }
82
83 }
84
85 protected void copyToSources(RpmSpecFile spec, File sourcesDir) {
86 try {
87 List<Resource> toCopyToSources = new ArrayList<Resource>();
88 List<Resource> toDownload = new ArrayList<Resource>();
89 for (String file : spec.getSources().values()) {
90 try {
91 Resource res;
92 try {
93 res = specFile.createRelative("../SOURCES/" + file);
94 if (!res.exists())
95 res = new UrlResource(file);
96
97 } catch (Exception e) {
98 res = new UrlResource(file);
99 toDownload.add(res);
100 }
101 toCopyToSources.add(res);
102 } catch (Exception e) {
103 log.error("Cannot interpret " + file, e);
104 }
105 }
106 for (String file : spec.getPatches().values()) {
107 try {
108 Resource res;
109 try {
110 res = specFile.createRelative("../SOURCES/" + file);
111 if (!res.exists()) {
112 res = new UrlResource(file);
113 }
114 } catch (Exception e) {
115 res = new UrlResource(file);
116 toDownload.add(res);
117 }
118 toCopyToSources.add(res);
119 } catch (Exception e) {
120 log.error("Cannot interpret " + file, e);
121 }
122 }
123
124 // FIXME: we may have missed some files here
125 for (Resource res : toCopyToSources) {
126 File targetDir;
127 if (distributionCache != null && toDownload.contains(res)) {
128 if (!distributionCache.exists())
129 distributionCache.mkdirs();
130 targetDir = distributionCache;
131 if (log.isDebugEnabled())
132 log.debug("Cache " + res + " in " + targetDir);
133 } else
134 targetDir = sourcesDir;
135 File targetFile = new File(targetDir, res.getFilename())
136 .getCanonicalFile();
137 if (!targetFile.exists() || overwriteSources)
138 copyResourceToFile(res, targetFile);
139 if (!targetDir.equals(sourcesDir)) {
140 File fileInSourcesDir = new File(sourcesDir,
141 targetFile.getName());
142 if (!fileInSourcesDir.exists()
143 || !(fileInSourcesDir.length() == targetFile
144 .length()))
145 FileUtils.copyFile(targetFile, fileInSourcesDir);
146 }
147 }
148 } catch (Exception e) {
149 throw new SlcException("Cannot copy to " + sourcesDir, e);
150 }
151 }
152
153 private static void copyResourceToFile(Resource res, File targetFile) {
154 try {
155 if (targetFile.equals(res.getFile())) {
156 if (log.isDebugEnabled())
157 log.debug("Target identical to source, skipping... "
158 + targetFile + " <=> " + res);
159 return;
160 }
161 } catch (IOException e1) {
162 // silent
163 }
164
165 OutputStream out = null;
166 InputStream in = null;
167 try {
168 out = FileUtils.openOutputStream(targetFile);
169 in = res.getInputStream();
170 IOUtils.copy(in, out);
171 if (log.isDebugEnabled())
172 log.debug("Copied " + targetFile + " from " + res);
173 } catch (Exception e) {
174 throw new SlcException("Cannot copy " + res + " to " + targetFile,
175 e);
176 } finally {
177 IOUtils.closeQuietly(in);
178 IOUtils.closeQuietly(out);
179 }
180
181 }
182
183 public void setSpecFile(Resource specFile) {
184 this.specFile = specFile;
185 }
186
187 public void setTopdir(File topdir) {
188 this.topdir = topdir;
189 }
190
191 public void setOverwriteSources(Boolean overwriteSources) {
192 this.overwriteSources = overwriteSources;
193 }
194
195 public File getSrpmFile() {
196 return srpmFile;
197 }
198
199 public void setRpmBuildEnvironment(RpmBuildEnvironment rpmBuildEnvironment) {
200 this.rpmBuildEnvironment = rpmBuildEnvironment;
201 }
202
203 public void setDistributionCache(File distributionCache) {
204 this.distributionCache = distributionCache;
205 }
206
207 public void setExecutor(Executor executor) {
208 this.executor = executor;
209 }
210
211 }