Refactor RPM Factory
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 16 Jul 2013 13:07:48 +0000 (13:07 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 16 Jul 2013 13:07:48 +0000 (13:07 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@6380 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

runtime/org.argeo.slc.rpmfactory/src/main/java/org/argeo/slc/rpmfactory/RpmFactory.java [new file with mode: 0644]
runtime/org.argeo.slc.rpmfactory/src/main/java/org/argeo/slc/rpmfactory/core/BuildInMock.java
runtime/org.argeo.slc.rpmfactory/src/main/java/org/argeo/slc/rpmfactory/core/CreateRpmDistribution.java
runtime/org.argeo.slc.rpmfactory/src/main/java/org/argeo/slc/rpmfactory/core/ReleaseStaging.java
runtime/org.argeo.slc.rpmfactory/src/main/java/org/argeo/slc/rpmfactory/core/RpmFactory.java [deleted file]
runtime/org.argeo.slc.rpmfactory/src/main/java/org/argeo/slc/rpmfactory/core/RpmFactoryImpl.java [new file with mode: 0644]

diff --git a/runtime/org.argeo.slc.rpmfactory/src/main/java/org/argeo/slc/rpmfactory/RpmFactory.java b/runtime/org.argeo.slc.rpmfactory/src/main/java/org/argeo/slc/rpmfactory/RpmFactory.java
new file mode 100644 (file)
index 0000000..aee2956
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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.rpmfactory;
+
+import java.io.File;
+import java.util.List;
+
+import javax.jcr.Node;
+
+/**
+ * Defines a build environment. This information is typically used by other
+ * components performing the various actions related to RPM build.
+ */
+public interface RpmFactory {
+       //
+       // DIRECT ACTIONS ON JCR REPOSITORY
+       //
+       public void indexWorkspace(String workspace);
+
+       public Node newDistribution(String distributionId);
+
+       //
+       // CONFIG FILES GENERATION
+       //
+       /** Creates a mock config file. */
+       public File getMockConfigFile(String arch, String branch);
+
+       /** Creates a yum config file. */
+       public File getYumRepoFile(String arch);
+
+       //
+       // WORKSPACES
+       //
+       public String getStagingWorkspace();
+
+       /**
+        * @return the name of the testing workspace, or null if and only if the
+        *         testing workspace was not enabled.
+        */
+       public String getTestingWorkspace();
+
+       public String getStableWorkspace();
+
+       public File getWorkspaceDir(String workspace);
+
+       //
+       // ARCH DEPENDENT INFOS
+       //
+       public List<String> getArchs();
+
+       public String getMockConfig(String arch);
+
+       public String getIdWithArch(String arch);
+
+       public File getResultDir(String arch);
+
+       //
+       // DEPLOYMENT
+       //
+       public String getGitBaseUrl();
+
+       public Boolean isDeveloperInstance();
+
+}
index f2b1dbaf3428382f022dba3f730339cb90ade01b..1f815eac5a82ce26bbbf5497c02edb4b2306e349 100644 (file)
@@ -29,6 +29,7 @@ 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.argeo.slc.rpmfactory.RpmFactory;
 
 /** Build an RPM in mock. */
 public class BuildInMock implements Runnable {
index f2548f04b9adf9b7cd62295d2e84fbab6b38f121..9fd4993cf18d600bdeafa4ca8523cf2898eb8010 100644 (file)
@@ -16,6 +16,7 @@ import org.apache.commons.logging.LogFactory;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.slc.SlcException;
 import org.argeo.slc.core.execution.tasks.SystemCall;
+import org.argeo.slc.rpmfactory.RpmFactory;
 
 /**
  * Gather RPMs from various sources (local builds or third party) into a
index 44fb368f3265c9ac248d3fcd858b81249a0edf30..76a67005a2c536f187303e18eb31ac107f98a6e8 100644 (file)
@@ -11,6 +11,7 @@ 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.argeo.slc.rpmfactory.RpmFactory;
 
 /** Releases the content of staging to a public repository. */
 public class ReleaseStaging implements Runnable {
@@ -23,14 +24,14 @@ public class ReleaseStaging implements Runnable {
 
        @Override
        public void run() {
-               File stagingDir = rpmFactory.getWorkspaceDir(rpmFactory
-                               .getStagingWorkspace());
-               // TODO deal with testing
-               File targetRepoDir = rpmFactory.getWorkspaceDir(rpmFactory
-                               .getStableWorkspace());
+               String sourceWorkspace = rpmFactory.getStagingWorkspace();
+               File sourceRepoDir = rpmFactory.getWorkspaceDir(sourceWorkspace);
+               String targetWorkspace = rpmFactory.getTestingWorkspace() != null ? rpmFactory
+                               .getTestingWorkspace() : rpmFactory.getStableWorkspace();
+               File targetRepoDir = rpmFactory.getWorkspaceDir(targetWorkspace);
                List<File> reposToRecreate = new ArrayList<File>();
 
-               stagingChildren: for (File dir : stagingDir.listFiles()) {
+               stagingChildren: for (File dir : sourceRepoDir.listFiles()) {
                        if (!dir.isDirectory())
                                continue stagingChildren;
                        if (dir.getName().equals("lost+found"))
@@ -42,7 +43,7 @@ public class ReleaseStaging implements Runnable {
                                if (log.isDebugEnabled())
                                        log.debug(dir + " => " + targetDir);
                        } catch (IOException e) {
-                               throw new SlcException(stagingDir
+                               throw new SlcException(sourceRepoDir
                                                + " could not be copied properly, check it manually."
                                                + " Metadata have NOT been updated.", e);
                        }
@@ -59,7 +60,7 @@ public class ReleaseStaging implements Runnable {
                }
 
                // clear staging
-               for (File dir : stagingDir.listFiles()) {
+               for (File dir : sourceRepoDir.listFiles()) {
                        try {
                                if (dir.getName().equals("lost+found"))
                                        continue;
@@ -89,6 +90,8 @@ public class ReleaseStaging implements Runnable {
                        log.info("Updated repo " + repoToRecreate);
                }
 
+               rpmFactory.indexWorkspace(sourceWorkspace);
+               rpmFactory.indexWorkspace(targetWorkspace);
        }
 
        public void setRpmFactory(RpmFactory rpmFactory) {
diff --git a/runtime/org.argeo.slc.rpmfactory/src/main/java/org/argeo/slc/rpmfactory/core/RpmFactory.java b/runtime/org.argeo.slc.rpmfactory/src/main/java/org/argeo/slc/rpmfactory/core/RpmFactory.java
deleted file mode 100644 (file)
index c09ed36..0000000
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * 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.rpmfactory.core;
-
-import java.io.File;
-import java.io.IOException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.apache.commons.io.FileUtils;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.slc.SlcConstants;
-import org.argeo.slc.SlcException;
-import org.argeo.slc.core.execution.tasks.SystemCall;
-import org.argeo.slc.repo.NodeIndexerVisitor;
-import org.argeo.slc.rpmfactory.RpmRepository;
-
-/**
- * Defines a build environment. This information is typically used by other
- * components performing the various actions related to RPM build.
- */
-public class RpmFactory {
-       private Repository rpmRepository;
-       private Repository distRepository;
-
-       private String id;
-       private List<RpmRepository> repositories = new ArrayList<RpmRepository>();
-       private List<String> archs = new ArrayList<String>();
-
-       private String rpmBase = "/mnt/slc/repos/rpm";
-       private String distBase = "/mnt/slc/repos/dist";
-       private String mockVar = "/var/lib/mock";
-       private String mockEtc = "/etc/mock";
-
-       private DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmm");
-
-       private String gitWorkspace = "git";
-
-       private String localUrlBase = "http://localhost:7070/";
-       /** If not null or empty, this is a developer instance. */
-       private String gitDevBaseUrl = null;
-
-       private Boolean withTestingRepository = false;
-
-       private String yumConfigMainSection = "cachedir=/var/cache/yum\n"
-                       + "debuglevel=1\n" + "reposdir=/dev/null\n"
-                       + "logfile=/var/log/yum.log\n" + "retries=20\n" + "obsoletes=1\n"
-                       + "gpgcheck=0\n" + "assumeyes=1\n" + "syslog_ident=mock\n"
-                       + "syslog_device=\n" + "http_caching=none\n";
-
-       private String defaultMacroFiles = "/usr/lib/rpm/macros:"
-                       + "/usr/lib/rpm/ia32e-linux/macros:"
-                       + "/usr/lib/rpm/redhat/macros:" + "/etc/rpm/macros.*:"
-                       + "/etc/rpm/macros:" + "/etc/rpm/ia32e-linux/macros:"
-                       + "~/.rpmmacros";
-       private Map<String, String> rpmmacros = new HashMap<String, String>();
-
-       // set by init
-       private String proxiedReposBase;
-       private String managedReposBase;
-
-       private String stagingWorkspace;
-       private String testingWorkspace;
-       private String stableWorkspace;
-
-       private File rpmFactoryBaseDir;
-       private File mockConfDir;
-       private File yumConfDir;
-
-       public void init() {
-               // local URL bases
-               proxiedReposBase = localUrlBase + "repo/rpm/";
-               managedReposBase = localUrlBase + "data/public/rpm/";
-
-               // local directories
-               rpmFactoryBaseDir.mkdirs();
-               mockConfDir = new File(rpmFactoryBaseDir.getPath() + "/conf/mock");
-               mockConfDir.mkdirs();
-               yumConfDir = new File(rpmFactoryBaseDir.getPath() + "/conf/yum");
-               yumConfDir.mkdirs();
-
-               // managed repositories
-               stagingWorkspace = id + "-staging";
-               if (withTestingRepository)
-                       testingWorkspace = id + "-testing";
-               stableWorkspace = id;
-
-               initDistWorkspace(stableWorkspace);
-               initGitWorkspace();
-               initRpmWorkspace(stagingWorkspace);
-               if (withTestingRepository)
-                       initRpmWorkspace(testingWorkspace);
-               initRpmWorkspace(stableWorkspace);
-       }
-
-       protected void initRpmWorkspace(String workspace) {
-               Session session = null;
-               try {
-                       session = JcrUtils.loginOrCreateWorkspace(rpmRepository, workspace);
-                       JcrUtils.addPrivilege(session, "/", "anonymous", "jcr:read");
-                       JcrUtils.addPrivilege(session, "/", SlcConstants.ROLE_SLC,
-                                       "jcr:all");
-
-                       for (String arch : archs) {
-                               Node archFolder = JcrUtils.mkfolders(session, "/" + arch);
-                               session.save();
-                               if (!archFolder.hasNode("repodata")) {
-                                       File workspaceDir = getWorkspaceDir(workspace);
-                                       // touch a file in order to make sue this is properly
-                                       // mounted.
-                                       File touch = new File(workspaceDir, ".touch");
-                                       touch.createNewFile();
-                                       touch.delete();
-
-                                       SystemCall createrepo = new SystemCall();
-                                       createrepo.arg("createrepo");
-                                       createrepo.arg("-q");
-                                       File archDir = new File(workspaceDir, arch);
-                                       createrepo.arg(archDir.getAbsolutePath());
-                                       createrepo.run();
-                               }
-                       }
-               } catch (Exception e) {
-                       throw new SlcException("Cannot initialize workspace " + workspace,
-                                       e);
-               } finally {
-                       JcrUtils.logoutQuietly(session);
-               }
-       }
-
-       /** Caller must logout the underlying session. */
-       protected Node newDistribution(String distributionId) {
-               Session session = null;
-               try {
-                       session = JcrUtils.loginOrCreateWorkspace(rpmRepository,
-                                       distributionId);
-                       JcrUtils.addPrivilege(session, "/", "anonymous", "jcr:read");
-                       JcrUtils.addPrivilege(session, "/", SlcConstants.ROLE_SLC,
-                                       "jcr:all");
-
-                       Calendar now = new GregorianCalendar();
-                       String folderName = dateFormat.format(now.getTime());
-                       return JcrUtils.mkfolders(session, "/" + folderName);
-               } catch (Exception e) {
-                       JcrUtils.logoutQuietly(session);
-                       throw new SlcException("Cannot initialize distribution workspace "
-                                       + distributionId, e);
-               }
-       }
-
-       protected void initGitWorkspace() {
-               Session session = null;
-               try {
-                       session = JcrUtils.loginOrCreateWorkspace(rpmRepository,
-                                       gitWorkspace);
-                       JcrUtils.addPrivilege(session, "/", "anonymous", "jcr:read");
-                       JcrUtils.addPrivilege(session, "/", SlcConstants.ROLE_SLC,
-                                       "jcr:all");
-               } catch (Exception e) {
-                       throw new SlcException("Cannot initialize workspace "
-                                       + gitWorkspace, e);
-               } finally {
-                       JcrUtils.logoutQuietly(session);
-               }
-       }
-
-       protected void initDistWorkspace(String workspace) {
-               Session session = null;
-               try {
-                       session = JcrUtils
-                                       .loginOrCreateWorkspace(distRepository, workspace);
-                       JcrUtils.addPrivilege(session, "/", "anonymous", "jcr:read");
-               } catch (RepositoryException e) {
-                       throw new SlcException("Cannot initialize workspace " + workspace,
-                                       e);
-               } finally {
-                       JcrUtils.logoutQuietly(session);
-               }
-       }
-
-       public void destroy() {
-
-       }
-
-       public String generateMockConfigFile(String arch, String branch) {
-               StringBuffer buf = new StringBuffer();
-
-               buf.append("config_opts['root'] = '" + getIdWithArch(arch) + "'\n");
-               buf.append("config_opts['target_arch'] = '" + arch + "'\n");
-               buf.append("config_opts['legal_host_arches'] = ('" + arch + "',)\n");
-               buf.append("config_opts['chroot_setup_cmd'] = 'groupinstall buildsys-build'\n");
-               // buf.append("config_opts['dist'] = 'el6'\n");
-               buf.append("config_opts['plugin_conf']['yum_cache_enable'] = False\n");
-
-               buf.append("config_opts['scm'] = False\n");
-               buf.append("config_opts['scm_opts']['method'] = 'git'\n");
-               buf.append("config_opts['scm_opts']['spec'] = 'SCM_PKG.spec'\n");
-               buf.append("config_opts['scm_opts']['ext_src_dir'] = '"
-                               + getSourcesDir().getAbsolutePath() + "'\n");
-               buf.append("config_opts['scm_opts']['git_timestamps'] = True\n");
-
-               // development
-               if (gitDevBaseUrl != null && !gitDevBaseUrl.trim().equals(""))
-                       buf.append("config_opts['scm_opts']['git_get'] = 'git clone "
-                                       + (branch != null ? "-b " + branch : "") + " "
-                                       + gitDevBaseUrl + "/SCM_PKG SCM_PKG'\n");
-               else
-                       buf.append("config_opts['scm_opts']['git_get'] = 'git clone "
-                                       + (branch != null ? "-b " + branch : "") + " "
-                                       + getGitBaseUrl() + "/SCM_PKG.git SCM_PKG'\n");
-
-               buf.append("\nconfig_opts['yum.conf'] = \"\"\"\n");
-               buf.append(generateYumConfigFile(arch)).append('\n');
-               buf.append("\"\"\"\n");
-               return buf.toString();
-       }
-
-       public String generateYumConfigFile(String arch) {
-               StringBuffer buf = new StringBuffer();
-               buf.append("[main]\n");
-               buf.append(yumConfigMainSection).append('\n');
-
-               for (RpmRepository repository : repositories) {
-                       buf.append('[').append(repository.getId()).append("]\n");
-                       buf.append("name=").append(repository.getId()).append('\n');
-                       if (repository instanceof ThirdPartyRpmRepository) {
-                               buf.append("#baseurl=").append(repository.getUrl())
-                                               .append(arch).append('/').append("\n");
-                               buf.append("baseurl=").append(proxiedReposBase)
-                                               .append(repository.getId()).append('/').append(arch)
-                                               .append('/').append("\n");
-                               if (((ThirdPartyRpmRepository) repository).getYumConf() != null)
-                                       buf.append(
-                                                       ((ThirdPartyRpmRepository) repository).getYumConf()
-                                                                       .trim()).append('\n');
-                       }
-               }
-
-               // managed repos
-               addManagedRepository(buf, stagingWorkspace, arch);
-               if (withTestingRepository)
-                       addManagedRepository(buf, testingWorkspace, arch);
-               addManagedRepository(buf, stableWorkspace, arch);
-               return buf.toString();
-       }
-
-       protected void addManagedRepository(StringBuffer buf, String workspace,
-                       String arch) {
-               buf.append('[').append(workspace).append("]\n");
-               buf.append("baseurl=").append(managedReposBase).append(workspace)
-                               .append('/').append(arch).append('/').append("\n");
-               buf.append("gpgcheck=0").append("\n");
-       }
-
-       /** Creates a mock config file. */
-       public File getMockConfigFile(String arch, String branch) {
-               File mockSiteDefaultsFile = new File(mockConfDir, "site-defaults.cfg");
-               File mockLoggingFile = new File(mockConfDir, "logging.ini");
-               File mockConfigFile = new File(mockConfDir, getIdWithArch(arch)
-                               + ".cfg");
-               try {
-                       if (!mockSiteDefaultsFile.exists())
-                               mockSiteDefaultsFile.createNewFile();
-                       if (!mockLoggingFile.exists())
-                               FileUtils.copyFile(new File(mockEtc + "/logging.ini"),
-                                               mockLoggingFile);
-
-                       FileUtils.writeStringToFile(mockConfigFile,
-                                       generateMockConfigFile(arch, branch));
-                       return mockConfigFile;
-               } catch (IOException e) {
-                       throw new SlcException("Cannot write mock config file to "
-                                       + mockConfigFile, e);
-               }
-       }
-
-       /** Creates a yum config file. */
-       public File getYumRepoFile(String arch) {
-               File yumConfigFile = new File(yumConfDir, getIdWithArch(arch) + ".repo");
-               try {
-                       FileUtils.writeStringToFile(yumConfigFile,
-                                       generateYumConfigFile(arch));
-                       return yumConfigFile;
-               } catch (IOException e) {
-                       throw new SlcException("Cannot write yum config file to "
-                                       + yumConfigFile, e);
-               }
-       }
-
-       public File getResultDir(String arch) {
-               return new File(mockVar + "/" + getIdWithArch(arch) + "/result");
-       }
-
-       public File getWorkspaceDir(String workspace) {
-               return new File(rpmBase + "/" + workspace);
-       }
-
-       public File getSourcesDir() {
-               return new File(distBase + "/" + stableWorkspace);
-       }
-
-       public String getMockConfig(String arch) {
-               return getIdWithArch(arch);
-       }
-
-       public String getIdWithArch(String arch) {
-               return id + "-" + arch;
-       }
-
-       public String getGitBaseUrl() {
-               return managedReposBase + gitWorkspace;
-       }
-
-       public void indexWorkspace(String workspace) {
-               Session session = null;
-               try {
-                       session = rpmRepository.login(workspace);
-                       session.getRootNode().accept(
-                                       new NodeIndexerVisitor(new RpmIndexer()));
-               } catch (RepositoryException e) {
-                       throw new SlcException("Cannot index workspace " + workspace, e);
-               } finally {
-                       JcrUtils.logoutQuietly(session);
-               }
-       }
-
-       public Boolean isDeveloperInstance() {
-               return gitDevBaseUrl != null;
-       }
-
-       /** Write (topdir)/rpmmacros and (topdir)/rpmrc */
-       public void writeRpmbuildConfigFiles(File topdir) {
-               writeRpmbuildConfigFiles(topdir, new File(topdir, "rpmmacros"),
-                               new File(topdir, "rpmrc"));
-       }
-
-       public void writeRpmbuildConfigFiles(File topdir, File rpmmacroFile,
-                       File rpmrcFile) {
-               try {
-                       List<String> macroLines = new ArrayList<String>();
-                       macroLines.add("%_topdir " + topdir.getCanonicalPath());
-                       for (String macroKey : rpmmacros.keySet()) {
-                               macroLines.add(macroKey + " " + rpmmacros.get(macroKey));
-                       }
-                       FileUtils.writeLines(rpmmacroFile, macroLines);
-
-                       List<String> rpmrcLines = new ArrayList<String>();
-                       rpmrcLines.add("include: /usr/lib/rpm/rpmrc");
-                       rpmrcLines.add("macrofiles: " + defaultMacroFiles + ":"
-                                       + rpmmacroFile.getCanonicalPath());
-                       FileUtils.writeLines(rpmrcFile, rpmrcLines);
-               } catch (IOException e) {
-                       throw new SlcException("Cannot write rpmbuild config files", e);
-               }
-
-       }
-
-       public Map<String, String> getRpmmacros() {
-               return rpmmacros;
-       }
-
-       public void setRpmmacros(Map<String, String> rpmmacros) {
-               this.rpmmacros = rpmmacros;
-       }
-
-       public String getDefaultMacroFiles() {
-               return defaultMacroFiles;
-       }
-
-       public void setDefaultMacroFiles(String defaultMacroFiles) {
-               this.defaultMacroFiles = defaultMacroFiles;
-       }
-
-       public void setArchs(List<String> archs) {
-               this.archs = archs;
-       }
-
-       public List<String> getArchs() {
-               return archs;
-       }
-
-       public void setRpmBase(String stagingBase) {
-               this.rpmBase = stagingBase;
-       }
-
-       public void setId(String id) {
-               this.id = id;
-       }
-
-       public void setMockVar(String mockVar) {
-               this.mockVar = mockVar;
-       }
-
-       public void setRpmRepository(Repository rpmRepository) {
-               this.rpmRepository = rpmRepository;
-       }
-
-       public void setDistRepository(Repository distRepository) {
-               this.distRepository = distRepository;
-       }
-
-       public void setLocalUrlBase(String localUrlBase) {
-               this.localUrlBase = localUrlBase;
-       }
-
-       public void setYumConfigMainSection(String yumConfigMainSection) {
-               this.yumConfigMainSection = yumConfigMainSection;
-       }
-
-       public void setRepositories(List<RpmRepository> repositories) {
-               this.repositories = repositories;
-       }
-
-       public void setRpmFactoryBaseDir(File rpmFactoryBaseDir) {
-               this.rpmFactoryBaseDir = rpmFactoryBaseDir;
-       }
-
-       public String getStagingWorkspace() {
-               return stagingWorkspace;
-       }
-
-       public String getTestingWorkspace() {
-               return testingWorkspace;
-       }
-
-       public String getStableWorkspace() {
-               return stableWorkspace;
-       }
-
-       public void setWithTestingRepository(Boolean withTestingRepository) {
-               this.withTestingRepository = withTestingRepository;
-       }
-
-       public void setGitDevBaseUrl(String gitBaseUrl) {
-               this.gitDevBaseUrl = gitBaseUrl;
-       }
-}
diff --git a/runtime/org.argeo.slc.rpmfactory/src/main/java/org/argeo/slc/rpmfactory/core/RpmFactoryImpl.java b/runtime/org.argeo.slc.rpmfactory/src/main/java/org/argeo/slc/rpmfactory/core/RpmFactoryImpl.java
new file mode 100644 (file)
index 0000000..a5012fa
--- /dev/null
@@ -0,0 +1,468 @@
+/*
+ * 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.rpmfactory.core;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.SlcConstants;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.core.execution.tasks.SystemCall;
+import org.argeo.slc.repo.NodeIndexerVisitor;
+import org.argeo.slc.rpmfactory.RpmFactory;
+import org.argeo.slc.rpmfactory.RpmRepository;
+
+/**
+ * Defines a build environment. This information is typically used by other
+ * components performing the various actions related to RPM build.
+ */
+public class RpmFactoryImpl implements RpmFactory {
+       private Log log = LogFactory.getLog(RpmFactoryImpl.class);
+
+       private Repository rpmRepository;
+       private Repository distRepository;
+
+       private String id;
+       private List<RpmRepository> repositories = new ArrayList<RpmRepository>();
+       private List<String> archs = new ArrayList<String>();
+
+       private String rpmBase = "/mnt/slc/repos/rpm";
+       private String distBase = "/mnt/slc/repos/dist";
+       private String mockVar = "/var/lib/mock";
+       private String mockEtc = "/etc/mock";
+
+       private DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmm");
+
+       private String gitWorkspace = "git";
+
+       private String localUrlBase = "http://localhost:7070/";
+       /** If not null or empty, this is a developer instance. */
+       private String gitDevBaseUrl = null;
+
+       private Boolean withTestingRepository = false;
+
+       private String yumConfigMainSection = "cachedir=/var/cache/yum\n"
+                       + "debuglevel=1\n" + "reposdir=/dev/null\n"
+                       + "logfile=/var/log/yum.log\n" + "retries=20\n" + "obsoletes=1\n"
+                       + "gpgcheck=0\n" + "assumeyes=1\n" + "syslog_ident=mock\n"
+                       + "syslog_device=\n" + "http_caching=none\n";
+
+       private String defaultMacroFiles = "/usr/lib/rpm/macros:"
+                       + "/usr/lib/rpm/ia32e-linux/macros:"
+                       + "/usr/lib/rpm/redhat/macros:" + "/etc/rpm/macros.*:"
+                       + "/etc/rpm/macros:" + "/etc/rpm/ia32e-linux/macros:"
+                       + "~/.rpmmacros";
+       private Map<String, String> rpmmacros = new HashMap<String, String>();
+
+       // set by init
+       private String proxiedReposBase;
+       private String managedReposBase;
+
+       private String stagingWorkspace;
+       private String testingWorkspace;
+       private String stableWorkspace;
+
+       private File rpmFactoryBaseDir;
+       private File mockConfDir;
+       private File yumConfDir;
+
+       public void init() {
+               // local URL bases
+               proxiedReposBase = localUrlBase + "repo/rpm/";
+               managedReposBase = localUrlBase + "data/public/rpm/";
+
+               // local directories
+               rpmFactoryBaseDir.mkdirs();
+               mockConfDir = new File(rpmFactoryBaseDir.getPath() + "/conf/mock");
+               mockConfDir.mkdirs();
+               yumConfDir = new File(rpmFactoryBaseDir.getPath() + "/conf/yum");
+               yumConfDir.mkdirs();
+
+               // managed repositories
+               stagingWorkspace = id + "-staging";
+               if (withTestingRepository)
+                       testingWorkspace = id + "-testing";
+               stableWorkspace = id;
+
+               initDistWorkspace(stableWorkspace);
+               initGitWorkspace();
+               initRpmWorkspace(stagingWorkspace);
+               if (withTestingRepository)
+                       initRpmWorkspace(testingWorkspace);
+               initRpmWorkspace(stableWorkspace);
+       }
+
+       protected void initRpmWorkspace(String workspace) {
+               Session session = null;
+               try {
+                       session = JcrUtils.loginOrCreateWorkspace(rpmRepository, workspace);
+                       JcrUtils.addPrivilege(session, "/", "anonymous", "jcr:read");
+                       JcrUtils.addPrivilege(session, "/", SlcConstants.ROLE_SLC,
+                                       "jcr:all");
+
+                       for (String arch : archs) {
+                               Node archFolder = JcrUtils.mkfolders(session, "/" + arch);
+                               session.save();
+                               if (!archFolder.hasNode("repodata")) {
+                                       File workspaceDir = getWorkspaceDir(workspace);
+                                       // touch a file in order to make sue this is properly
+                                       // mounted.
+                                       File touch = new File(workspaceDir, ".touch");
+                                       touch.createNewFile();
+                                       touch.delete();
+
+                                       SystemCall createrepo = new SystemCall();
+                                       createrepo.arg("createrepo");
+                                       createrepo.arg("-q");
+                                       File archDir = new File(workspaceDir, arch);
+                                       createrepo.arg(archDir.getAbsolutePath());
+                                       createrepo.run();
+                               }
+                       }
+               } catch (Exception e) {
+                       throw new SlcException("Cannot initialize workspace " + workspace,
+                                       e);
+               } finally {
+                       JcrUtils.logoutQuietly(session);
+               }
+       }
+
+       /** Caller must logout the underlying session. */
+       public Node newDistribution(String distributionId) {
+               Session session = null;
+               try {
+                       session = JcrUtils.loginOrCreateWorkspace(rpmRepository,
+                                       distributionId);
+                       JcrUtils.addPrivilege(session, "/", "anonymous", "jcr:read");
+                       JcrUtils.addPrivilege(session, "/", SlcConstants.ROLE_SLC,
+                                       "jcr:all");
+
+                       Calendar now = new GregorianCalendar();
+                       String folderName = dateFormat.format(now.getTime());
+                       return JcrUtils.mkfolders(session, "/" + folderName);
+               } catch (Exception e) {
+                       JcrUtils.logoutQuietly(session);
+                       throw new SlcException("Cannot initialize distribution workspace "
+                                       + distributionId, e);
+               }
+       }
+
+       protected void initGitWorkspace() {
+               Session session = null;
+               try {
+                       session = JcrUtils.loginOrCreateWorkspace(rpmRepository,
+                                       gitWorkspace);
+                       JcrUtils.addPrivilege(session, "/", "anonymous", "jcr:read");
+                       JcrUtils.addPrivilege(session, "/", SlcConstants.ROLE_SLC,
+                                       "jcr:all");
+               } catch (Exception e) {
+                       throw new SlcException("Cannot initialize workspace "
+                                       + gitWorkspace, e);
+               } finally {
+                       JcrUtils.logoutQuietly(session);
+               }
+       }
+
+       protected void initDistWorkspace(String workspace) {
+               Session session = null;
+               try {
+                       session = JcrUtils
+                                       .loginOrCreateWorkspace(distRepository, workspace);
+                       JcrUtils.addPrivilege(session, "/", "anonymous", "jcr:read");
+               } catch (RepositoryException e) {
+                       throw new SlcException("Cannot initialize workspace " + workspace,
+                                       e);
+               } finally {
+                       JcrUtils.logoutQuietly(session);
+               }
+       }
+
+       public void destroy() {
+
+       }
+
+       public String generateMockConfigFile(String arch, String branch) {
+               StringBuffer buf = new StringBuffer();
+
+               buf.append("config_opts['root'] = '" + getIdWithArch(arch) + "'\n");
+               buf.append("config_opts['target_arch'] = '" + arch + "'\n");
+               buf.append("config_opts['legal_host_arches'] = ('" + arch + "',)\n");
+               buf.append("config_opts['chroot_setup_cmd'] = 'groupinstall buildsys-build'\n");
+               // buf.append("config_opts['dist'] = 'el6'\n");
+               buf.append("config_opts['plugin_conf']['yum_cache_enable'] = False\n");
+
+               buf.append("config_opts['scm'] = False\n");
+               buf.append("config_opts['scm_opts']['method'] = 'git'\n");
+               buf.append("config_opts['scm_opts']['spec'] = 'SCM_PKG.spec'\n");
+               buf.append("config_opts['scm_opts']['ext_src_dir'] = '"
+                               + getSourcesDir().getAbsolutePath() + "'\n");
+               buf.append("config_opts['scm_opts']['git_timestamps'] = True\n");
+
+               // development
+               if (gitDevBaseUrl != null && !gitDevBaseUrl.trim().equals(""))
+                       buf.append("config_opts['scm_opts']['git_get'] = 'git clone "
+                                       + (branch != null ? "-b " + branch : "") + " "
+                                       + gitDevBaseUrl + "/SCM_PKG SCM_PKG'\n");
+               else
+                       buf.append("config_opts['scm_opts']['git_get'] = 'git clone "
+                                       + (branch != null ? "-b " + branch : "") + " "
+                                       + getGitBaseUrl() + "/SCM_PKG.git SCM_PKG'\n");
+
+               buf.append("\nconfig_opts['yum.conf'] = \"\"\"\n");
+               buf.append(generateYumConfigFile(arch)).append('\n');
+               buf.append("\"\"\"\n");
+               return buf.toString();
+       }
+
+       public String generateYumConfigFile(String arch) {
+               StringBuffer buf = new StringBuffer();
+               buf.append("[main]\n");
+               buf.append(yumConfigMainSection).append('\n');
+
+               for (RpmRepository repository : repositories) {
+                       buf.append('[').append(repository.getId()).append("]\n");
+                       buf.append("name=").append(repository.getId()).append('\n');
+                       if (repository instanceof ThirdPartyRpmRepository) {
+                               buf.append("#baseurl=").append(repository.getUrl())
+                                               .append(arch).append('/').append("\n");
+                               buf.append("baseurl=").append(proxiedReposBase)
+                                               .append(repository.getId()).append('/').append(arch)
+                                               .append('/').append("\n");
+                               if (((ThirdPartyRpmRepository) repository).getYumConf() != null)
+                                       buf.append(
+                                                       ((ThirdPartyRpmRepository) repository).getYumConf()
+                                                                       .trim()).append('\n');
+                       }
+               }
+
+               // managed repos
+               addManagedRepository(buf, stagingWorkspace, arch);
+               if (withTestingRepository)
+                       addManagedRepository(buf, testingWorkspace, arch);
+               addManagedRepository(buf, stableWorkspace, arch);
+               return buf.toString();
+       }
+
+       protected void addManagedRepository(StringBuffer buf, String workspace,
+                       String arch) {
+               buf.append('[').append(workspace).append("]\n");
+               buf.append("baseurl=").append(managedReposBase).append(workspace)
+                               .append('/').append(arch).append('/').append("\n");
+               buf.append("gpgcheck=0").append("\n");
+       }
+
+       /** Creates a mock config file. */
+       public File getMockConfigFile(String arch, String branch) {
+               File mockSiteDefaultsFile = new File(mockConfDir, "site-defaults.cfg");
+               File mockLoggingFile = new File(mockConfDir, "logging.ini");
+               File mockConfigFile = new File(mockConfDir, getIdWithArch(arch)
+                               + ".cfg");
+               try {
+                       if (!mockSiteDefaultsFile.exists())
+                               mockSiteDefaultsFile.createNewFile();
+                       if (!mockLoggingFile.exists())
+                               FileUtils.copyFile(new File(mockEtc + "/logging.ini"),
+                                               mockLoggingFile);
+
+                       FileUtils.writeStringToFile(mockConfigFile,
+                                       generateMockConfigFile(arch, branch));
+                       return mockConfigFile;
+               } catch (IOException e) {
+                       throw new SlcException("Cannot write mock config file to "
+                                       + mockConfigFile, e);
+               }
+       }
+
+       /** Creates a yum config file. */
+       public File getYumRepoFile(String arch) {
+               File yumConfigFile = new File(yumConfDir, getIdWithArch(arch) + ".repo");
+               try {
+                       FileUtils.writeStringToFile(yumConfigFile,
+                                       generateYumConfigFile(arch));
+                       return yumConfigFile;
+               } catch (IOException e) {
+                       throw new SlcException("Cannot write yum config file to "
+                                       + yumConfigFile, e);
+               }
+       }
+
+       public File getResultDir(String arch) {
+               return new File(mockVar + "/" + getIdWithArch(arch) + "/result");
+       }
+
+       public File getWorkspaceDir(String workspace) {
+               return new File(rpmBase + "/" + workspace);
+       }
+
+       public File getSourcesDir() {
+               return new File(distBase + "/" + stableWorkspace);
+       }
+
+       public String getMockConfig(String arch) {
+               return getIdWithArch(arch);
+       }
+
+       public String getIdWithArch(String arch) {
+               return id + "-" + arch;
+       }
+
+       public String getGitBaseUrl() {
+               return managedReposBase + gitWorkspace;
+       }
+
+       public void indexWorkspace(String workspace) {
+               Session session = null;
+               try {
+                       session = rpmRepository.login(workspace);
+                       session.getRootNode().accept(
+                                       new NodeIndexerVisitor(new RpmIndexer()));
+                       if (log.isDebugEnabled())
+                               log.debug("Indexed workspace " + workspace);
+               } catch (RepositoryException e) {
+                       throw new SlcException("Cannot index workspace " + workspace, e);
+               } finally {
+                       JcrUtils.logoutQuietly(session);
+               }
+       }
+
+       public Boolean isDeveloperInstance() {
+               return gitDevBaseUrl != null;
+       }
+
+       /** Write (topdir)/rpmmacros and (topdir)/rpmrc */
+       public void writeRpmbuildConfigFiles(File topdir) {
+               writeRpmbuildConfigFiles(topdir, new File(topdir, "rpmmacros"),
+                               new File(topdir, "rpmrc"));
+       }
+
+       public void writeRpmbuildConfigFiles(File topdir, File rpmmacroFile,
+                       File rpmrcFile) {
+               try {
+                       List<String> macroLines = new ArrayList<String>();
+                       macroLines.add("%_topdir " + topdir.getCanonicalPath());
+                       for (String macroKey : rpmmacros.keySet()) {
+                               macroLines.add(macroKey + " " + rpmmacros.get(macroKey));
+                       }
+                       FileUtils.writeLines(rpmmacroFile, macroLines);
+
+                       List<String> rpmrcLines = new ArrayList<String>();
+                       rpmrcLines.add("include: /usr/lib/rpm/rpmrc");
+                       rpmrcLines.add("macrofiles: " + defaultMacroFiles + ":"
+                                       + rpmmacroFile.getCanonicalPath());
+                       FileUtils.writeLines(rpmrcFile, rpmrcLines);
+               } catch (IOException e) {
+                       throw new SlcException("Cannot write rpmbuild config files", e);
+               }
+
+       }
+
+       public Map<String, String> getRpmmacros() {
+               return rpmmacros;
+       }
+
+       public void setRpmmacros(Map<String, String> rpmmacros) {
+               this.rpmmacros = rpmmacros;
+       }
+
+       public String getDefaultMacroFiles() {
+               return defaultMacroFiles;
+       }
+
+       public void setDefaultMacroFiles(String defaultMacroFiles) {
+               this.defaultMacroFiles = defaultMacroFiles;
+       }
+
+       public void setArchs(List<String> archs) {
+               this.archs = archs;
+       }
+
+       public List<String> getArchs() {
+               return archs;
+       }
+
+       public void setRpmBase(String stagingBase) {
+               this.rpmBase = stagingBase;
+       }
+
+       public void setId(String id) {
+               this.id = id;
+       }
+
+       public void setMockVar(String mockVar) {
+               this.mockVar = mockVar;
+       }
+
+       public void setRpmRepository(Repository rpmRepository) {
+               this.rpmRepository = rpmRepository;
+       }
+
+       public void setDistRepository(Repository distRepository) {
+               this.distRepository = distRepository;
+       }
+
+       public void setLocalUrlBase(String localUrlBase) {
+               this.localUrlBase = localUrlBase;
+       }
+
+       public void setYumConfigMainSection(String yumConfigMainSection) {
+               this.yumConfigMainSection = yumConfigMainSection;
+       }
+
+       public void setRepositories(List<RpmRepository> repositories) {
+               this.repositories = repositories;
+       }
+
+       public void setRpmFactoryBaseDir(File rpmFactoryBaseDir) {
+               this.rpmFactoryBaseDir = rpmFactoryBaseDir;
+       }
+
+       public String getStagingWorkspace() {
+               return stagingWorkspace;
+       }
+
+       public String getTestingWorkspace() {
+               return testingWorkspace;
+       }
+
+       public String getStableWorkspace() {
+               return stableWorkspace;
+       }
+
+       public void setWithTestingRepository(Boolean withTestingRepository) {
+               this.withTestingRepository = withTestingRepository;
+       }
+
+       public void setGitDevBaseUrl(String gitBaseUrl) {
+               this.gitDevBaseUrl = gitBaseUrl;
+       }
+}