2 * Copyright (C) 2007-2012 Mathieu Baudier
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.argeo
.slc
.lib
.linux
.rpmfactory
;
19 import java
.io
.IOException
;
20 import java
.io
.InputStream
;
21 import java
.io
.OutputStream
;
22 import java
.util
.ArrayList
;
23 import java
.util
.List
;
25 import org
.apache
.commons
.exec
.Executor
;
26 import org
.apache
.commons
.io
.FileUtils
;
27 import org
.apache
.commons
.io
.IOUtils
;
28 import org
.apache
.commons
.logging
.Log
;
29 import org
.apache
.commons
.logging
.LogFactory
;
30 import org
.argeo
.slc
.SlcException
;
31 import org
.argeo
.slc
.core
.execution
.tasks
.SystemCall
;
32 import org
.springframework
.core
.io
.Resource
;
33 import org
.springframework
.core
.io
.UrlResource
;
35 /** Generates an SRPM from a spec file */
36 public class CreateSrpm
implements Runnable
{
37 private final static Log log
= LogFactory
.getLog(CreateSrpm
.class);
41 /** Directory where to cache downloaded distributions. */
42 private File distributionCache
;
44 private Resource specFile
;
46 private RpmBuildEnvironment rpmBuildEnvironment
;
48 private Boolean overwriteSources
= false;
50 private File srpmFile
;
52 private Executor executor
;
55 File sourcesDir
= new File(topdir
, "SOURCES");
57 File specsDir
= new File(topdir
, "SPECS");
58 File srpmsDir
= new File(topdir
, "SRPMS");
61 // Parse spec file and copy required resources
62 RpmSpecFile spec
= new RpmSpecFile(specFile
);
63 copyToSources(spec
, sourcesDir
);
66 File targetFile
= new File(specsDir
, specFile
.getFilename())
68 copyResourceToFile(specFile
, targetFile
);
70 // Generate rpmbuild config files
71 rpmBuildEnvironment
.writeRpmbuildConfigFiles(topdir
);
75 SystemCall packageSrpm
= new SystemCall();
76 packageSrpm
.arg("rpmbuild");
77 packageSrpm
.arg("-bs").arg("--nodeps");
78 packageSrpm
.arg("--rcfile=rpmrc");
79 packageSrpm
.arg("--macros=" + RpmBuildEnvironment
.defaultMacroFiles
81 // buildSrpm.arg("-D", "_topdir " + topdir.getCanonicalPath() + "");
82 packageSrpm
.arg("SPECS/" + specFile
.getFilename());
83 packageSrpm
.setExecDir(topdir
.getCanonicalPath());
84 packageSrpm
.setLogCommand(true);
87 packageSrpm
.setExecutor(executor
);
88 String answer
= packageSrpm
.function();
90 // Extract generated SRPM path
91 // TODO: make it safer
92 String srpmPath
= answer
.split(":")[1].trim();
93 srpmFile
= new File(srpmPath
);
94 } catch (IOException e
) {
95 throw new SlcException("Cannot generate SRPM from " + specFile
, e
);
100 protected void copyToSources(RpmSpecFile spec
, File sourcesDir
) {
102 List
<Resource
> toCopyToSources
= new ArrayList
<Resource
>();
103 List
<Resource
> toDownload
= new ArrayList
<Resource
>();
104 for (String file
: spec
.getSources().values()) {
108 res
= specFile
.createRelative("../SOURCES/" + file
);
110 res
= new UrlResource(file
);
112 } catch (Exception e
) {
113 res
= new UrlResource(file
);
116 toCopyToSources
.add(res
);
117 } catch (Exception e
) {
118 log
.error("Cannot interpret " + file
, e
);
121 for (String file
: spec
.getPatches().values()) {
125 res
= specFile
.createRelative("../SOURCES/" + file
);
127 res
= new UrlResource(file
);
129 } catch (Exception e
) {
130 res
= new UrlResource(file
);
133 toCopyToSources
.add(res
);
134 } catch (Exception e
) {
135 log
.error("Cannot interpret " + file
, e
);
139 // FIXME: we may have missed some files here
140 for (Resource res
: toCopyToSources
) {
142 if (distributionCache
!= null && toDownload
.contains(res
)) {
143 if (!distributionCache
.exists())
144 distributionCache
.mkdirs();
145 targetDir
= distributionCache
;
146 if (log
.isDebugEnabled())
147 log
.debug("Cache " + res
+ " in " + targetDir
);
149 targetDir
= sourcesDir
;
150 File targetFile
= new File(targetDir
, res
.getFilename())
152 if (!targetFile
.exists() || overwriteSources
)
153 copyResourceToFile(res
, targetFile
);
154 if (!targetDir
.equals(sourcesDir
)) {
155 File fileInSourcesDir
= new File(sourcesDir
,
156 targetFile
.getName());
157 if (!fileInSourcesDir
.exists()
158 || !(fileInSourcesDir
.length() == targetFile
160 FileUtils
.copyFile(targetFile
, fileInSourcesDir
);
163 } catch (Exception e
) {
164 throw new SlcException("Cannot copy to " + sourcesDir
, e
);
168 private static void copyResourceToFile(Resource res
, File targetFile
) {
170 if (targetFile
.equals(res
.getFile())) {
171 if (log
.isDebugEnabled())
172 log
.debug("Target identical to source, skipping... "
173 + targetFile
+ " <=> " + res
);
176 } catch (IOException e1
) {
180 OutputStream out
= null;
181 InputStream in
= null;
183 out
= FileUtils
.openOutputStream(targetFile
);
184 in
= res
.getInputStream();
185 IOUtils
.copy(in
, out
);
186 if (log
.isDebugEnabled())
187 log
.debug("Copied " + targetFile
+ " from " + res
);
188 } catch (Exception e
) {
189 throw new SlcException("Cannot copy " + res
+ " to " + targetFile
,
192 IOUtils
.closeQuietly(in
);
193 IOUtils
.closeQuietly(out
);
198 public void setSpecFile(Resource specFile
) {
199 this.specFile
= specFile
;
202 public void setTopdir(File topdir
) {
203 this.topdir
= topdir
;
206 public void setOverwriteSources(Boolean overwriteSources
) {
207 this.overwriteSources
= overwriteSources
;
210 public File
getSrpmFile() {
214 public void setRpmBuildEnvironment(RpmBuildEnvironment rpmBuildEnvironment
) {
215 this.rpmBuildEnvironment
= rpmBuildEnvironment
;
218 public void setDistributionCache(File distributionCache
) {
219 this.distributionCache
= distributionCache
;
222 public void setExecutor(Executor executor
) {
223 this.executor
= executor
;