]> git.argeo.org Git - gpl/argeo-slc.git/blobdiff - org.argeo.slc.support/src/org/argeo/slc/lib/linux/rpmfactory/CreateSrpm.java
Move SLC Support
[gpl/argeo-slc.git] / org.argeo.slc.support / src / org / argeo / slc / lib / linux / rpmfactory / CreateSrpm.java
diff --git a/org.argeo.slc.support/src/org/argeo/slc/lib/linux/rpmfactory/CreateSrpm.java b/org.argeo.slc.support/src/org/argeo/slc/lib/linux/rpmfactory/CreateSrpm.java
new file mode 100644 (file)
index 0000000..b5f7bd0
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.slc.lib.linux.rpmfactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.exec.Executor;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.core.execution.tasks.SystemCall;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+
+/** Generates an SRPM from a spec file */
+public class CreateSrpm implements Runnable {
+       private final static Log log = LogFactory.getLog(CreateSrpm.class);
+
+       private File topdir;
+
+       /** Directory where to cache downloaded distributions. */
+       private File distributionCache;
+
+       private Resource specFile;
+
+       private RpmBuildEnvironment rpmBuildEnvironment;
+
+       private Boolean overwriteSources = false;
+
+       private File srpmFile;
+
+       private Executor executor;
+
+       public void run() {
+               File sourcesDir = new File(topdir, "SOURCES");
+               sourcesDir.mkdirs();
+               File specsDir = new File(topdir, "SPECS");
+               File srpmsDir = new File(topdir, "SRPMS");
+
+               try {
+                       // Parse spec file and copy required resources
+                       RpmSpecFile spec = new RpmSpecFile(specFile);
+                       copyToSources(spec, sourcesDir);
+
+                       // Copy spec file
+                       File targetFile = new File(specsDir, specFile.getFilename())
+                                       .getCanonicalFile();
+                       copyResourceToFile(specFile, targetFile);
+
+                       // Generate rpmbuild config files
+                       rpmBuildEnvironment.writeRpmbuildConfigFiles(topdir);
+
+                       // Build SRPM
+                       srpmsDir.mkdirs();
+                       SystemCall packageSrpm = new SystemCall();
+                       packageSrpm.arg("rpmbuild");
+                       packageSrpm.arg("-bs").arg("--nodeps");
+                       packageSrpm.arg("--rcfile=rpmrc");
+                       packageSrpm.arg("--macros=" + RpmBuildEnvironment.defaultMacroFiles
+                                       + ":rpmmacros");
+                       // buildSrpm.arg("-D", "_topdir " + topdir.getCanonicalPath() + "");
+                       packageSrpm.arg("SPECS/" + specFile.getFilename());
+                       packageSrpm.setExecDir(topdir.getCanonicalPath());
+                       packageSrpm.setLogCommand(true);
+
+                       // Execute
+                       packageSrpm.setExecutor(executor);
+                       String answer = packageSrpm.function();
+
+                       // Extract generated SRPM path
+                       // TODO: make it safer
+                       String srpmPath = answer.split(":")[1].trim();
+                       srpmFile = new File(srpmPath);
+               } catch (IOException e) {
+                       throw new SlcException("Cannot generate SRPM from " + specFile, e);
+               }
+
+       }
+
+       protected void copyToSources(RpmSpecFile spec, File sourcesDir) {
+               try {
+                       List<Resource> toCopyToSources = new ArrayList<Resource>();
+                       List<Resource> toDownload = new ArrayList<Resource>();
+                       for (String file : spec.getSources().values()) {
+                               try {
+                                       Resource res;
+                                       try {
+                                               res = specFile.createRelative("../SOURCES/" + file);
+                                               if (!res.exists())
+                                                       res = new UrlResource(file);
+
+                                       } catch (Exception e) {
+                                               res = new UrlResource(file);
+                                               toDownload.add(res);
+                                       }
+                                       toCopyToSources.add(res);
+                               } catch (Exception e) {
+                                       log.error("Cannot interpret " + file, e);
+                               }
+                       }
+                       for (String file : spec.getPatches().values()) {
+                               try {
+                                       Resource res;
+                                       try {
+                                               res = specFile.createRelative("../SOURCES/" + file);
+                                               if (!res.exists()) {
+                                                       res = new UrlResource(file);
+                                               }
+                                       } catch (Exception e) {
+                                               res = new UrlResource(file);
+                                               toDownload.add(res);
+                                       }
+                                       toCopyToSources.add(res);
+                               } catch (Exception e) {
+                                       log.error("Cannot interpret " + file, e);
+                               }
+                       }
+
+                       // FIXME: we may have missed some files here
+                       for (Resource res : toCopyToSources) {
+                               File targetDir;
+                               if (distributionCache != null && toDownload.contains(res)) {
+                                       if (!distributionCache.exists())
+                                               distributionCache.mkdirs();
+                                       targetDir = distributionCache;
+                                       if (log.isDebugEnabled())
+                                               log.debug("Cache " + res + " in " + targetDir);
+                               } else
+                                       targetDir = sourcesDir;
+                               File targetFile = new File(targetDir, res.getFilename())
+                                               .getCanonicalFile();
+                               if (!targetFile.exists() || overwriteSources)
+                                       copyResourceToFile(res, targetFile);
+                               if (!targetDir.equals(sourcesDir)) {
+                                       File fileInSourcesDir = new File(sourcesDir,
+                                                       targetFile.getName());
+                                       if (!fileInSourcesDir.exists()
+                                                       || !(fileInSourcesDir.length() == targetFile
+                                                                       .length()))
+                                               FileUtils.copyFile(targetFile, fileInSourcesDir);
+                               }
+                       }
+               } catch (Exception e) {
+                       throw new SlcException("Cannot copy to " + sourcesDir, e);
+               }
+       }
+
+       private static void copyResourceToFile(Resource res, File targetFile) {
+               try {
+                       if (targetFile.equals(res.getFile())) {
+                               if (log.isDebugEnabled())
+                                       log.debug("Target identical to source, skipping... "
+                                                       + targetFile + " <=> " + res);
+                               return;
+                       }
+               } catch (IOException e1) {
+                       // silent
+               }
+
+               OutputStream out = null;
+               InputStream in = null;
+               try {
+                       out = FileUtils.openOutputStream(targetFile);
+                       in = res.getInputStream();
+                       IOUtils.copy(in, out);
+                       if (log.isDebugEnabled())
+                               log.debug("Copied " + targetFile + " from " + res);
+               } catch (Exception e) {
+                       throw new SlcException("Cannot copy " + res + " to " + targetFile,
+                                       e);
+               } finally {
+                       IOUtils.closeQuietly(in);
+                       IOUtils.closeQuietly(out);
+               }
+
+       }
+
+       public void setSpecFile(Resource specFile) {
+               this.specFile = specFile;
+       }
+
+       public void setTopdir(File topdir) {
+               this.topdir = topdir;
+       }
+
+       public void setOverwriteSources(Boolean overwriteSources) {
+               this.overwriteSources = overwriteSources;
+       }
+
+       public File getSrpmFile() {
+               return srpmFile;
+       }
+
+       public void setRpmBuildEnvironment(RpmBuildEnvironment rpmBuildEnvironment) {
+               this.rpmBuildEnvironment = rpmBuildEnvironment;
+       }
+
+       public void setDistributionCache(File distributionCache) {
+               this.distributionCache = distributionCache;
+       }
+
+       public void setExecutor(Executor executor) {
+               this.executor = executor;
+       }
+
+}