/ script / lib / create-rpm-package.js
create-rpm-package.js
  1  'use strict';
  2  
  3  const assert = require('assert');
  4  const fs = require('fs-extra');
  5  const path = require('path');
  6  const spawnSync = require('./spawn-sync');
  7  const template = require('lodash.template');
  8  
  9  const CONFIG = require('../config');
 10  
 11  module.exports = function(packagedAppPath) {
 12    console.log(`Creating rpm package for "${packagedAppPath}"`);
 13    const atomExecutableName =
 14      CONFIG.channel === 'stable' ? 'atom' : `atom-${CONFIG.channel}`;
 15    const apmExecutableName =
 16      CONFIG.channel === 'stable' ? 'apm' : `apm-${CONFIG.channel}`;
 17    const appName = CONFIG.appName;
 18    const appDescription = CONFIG.appMetadata.description;
 19    // RPM versions can't have dashes or tildes in them.
 20    // (Ref.: https://twiki.cern.ch/twiki/bin/view/Main/RPMAndDebVersioning)
 21    const appVersion = CONFIG.appMetadata.version.replace(/-/g, '.');
 22    const policyFileName = `atom-${CONFIG.channel}.policy`;
 23  
 24    const rpmPackageDirPath = path.join(CONFIG.homeDirPath, 'rpmbuild');
 25    const rpmPackageBuildDirPath = path.join(rpmPackageDirPath, 'BUILD');
 26    const rpmPackageSourcesDirPath = path.join(rpmPackageDirPath, 'SOURCES');
 27    const rpmPackageSpecsDirPath = path.join(rpmPackageDirPath, 'SPECS');
 28    const rpmPackageRpmsDirPath = path.join(rpmPackageDirPath, 'RPMS');
 29    const rpmPackageApplicationDirPath = path.join(
 30      rpmPackageBuildDirPath,
 31      appName
 32    );
 33    const rpmPackageIconsDirPath = path.join(rpmPackageBuildDirPath, 'icons');
 34  
 35    if (fs.existsSync(rpmPackageDirPath)) {
 36      console.log(
 37        `Deleting existing rpm build directory at "${rpmPackageDirPath}"`
 38      );
 39      fs.removeSync(rpmPackageDirPath);
 40    }
 41  
 42    console.log(
 43      `Creating rpm package directory structure at "${rpmPackageDirPath}"`
 44    );
 45    fs.mkdirpSync(rpmPackageDirPath);
 46    fs.mkdirpSync(rpmPackageBuildDirPath);
 47    fs.mkdirpSync(rpmPackageSourcesDirPath);
 48    fs.mkdirpSync(rpmPackageSpecsDirPath);
 49  
 50    console.log(
 51      `Copying "${packagedAppPath}" to "${rpmPackageApplicationDirPath}"`
 52    );
 53    fs.copySync(packagedAppPath, rpmPackageApplicationDirPath);
 54  
 55    console.log(`Copying icons into "${rpmPackageIconsDirPath}"`);
 56    fs.copySync(
 57      path.join(
 58        CONFIG.repositoryRootPath,
 59        'resources',
 60        'app-icons',
 61        CONFIG.channel,
 62        'png'
 63      ),
 64      rpmPackageIconsDirPath
 65    );
 66  
 67    console.log(`Writing rpm package spec file into "${rpmPackageSpecsDirPath}"`);
 68    const rpmPackageSpecFilePath = path.join(rpmPackageSpecsDirPath, 'atom.spec');
 69    const rpmPackageSpecsTemplate = fs.readFileSync(
 70      path.join(
 71        CONFIG.repositoryRootPath,
 72        'resources',
 73        'linux',
 74        'redhat',
 75        'atom.spec.in'
 76      )
 77    );
 78    const rpmPackageSpecsContents = template(rpmPackageSpecsTemplate)({
 79      appName: appName,
 80      appFileName: atomExecutableName,
 81      apmFileName: apmExecutableName,
 82      description: appDescription,
 83      installDir: '/usr',
 84      version: appVersion,
 85      policyFileName
 86    });
 87    fs.writeFileSync(rpmPackageSpecFilePath, rpmPackageSpecsContents);
 88  
 89    console.log(`Writing desktop entry file into "${rpmPackageBuildDirPath}"`);
 90    const desktopEntryTemplate = fs.readFileSync(
 91      path.join(
 92        CONFIG.repositoryRootPath,
 93        'resources',
 94        'linux',
 95        'atom.desktop.in'
 96      )
 97    );
 98    const desktopEntryContents = template(desktopEntryTemplate)({
 99      appName: appName,
100      appFileName: atomExecutableName,
101      description: appDescription,
102      installDir: '/usr',
103      iconPath: atomExecutableName
104    });
105    fs.writeFileSync(
106      path.join(rpmPackageBuildDirPath, `${atomExecutableName}.desktop`),
107      desktopEntryContents
108    );
109  
110    console.log(`Copying atom.sh into "${rpmPackageBuildDirPath}"`);
111    fs.copySync(
112      path.join(CONFIG.repositoryRootPath, 'atom.sh'),
113      path.join(rpmPackageBuildDirPath, 'atom.sh')
114    );
115  
116    console.log(`Copying atom.policy into "${rpmPackageBuildDirPath}"`);
117    fs.copySync(
118      path.join(CONFIG.repositoryRootPath, 'resources', 'linux', 'atom.policy'),
119      path.join(rpmPackageBuildDirPath, policyFileName)
120    );
121  
122    console.log(`Generating .rpm package from "${rpmPackageDirPath}"`);
123    spawnSync('rpmbuild', ['-ba', '--clean', rpmPackageSpecFilePath]);
124    for (let generatedArch of fs.readdirSync(rpmPackageRpmsDirPath)) {
125      const generatedArchDirPath = path.join(
126        rpmPackageRpmsDirPath,
127        generatedArch
128      );
129      const generatedPackageFileNames = fs.readdirSync(generatedArchDirPath);
130      assert(
131        generatedPackageFileNames.length === 1,
132        'Generated more than one rpm package'
133      );
134      const generatedPackageFilePath = path.join(
135        generatedArchDirPath,
136        generatedPackageFileNames[0]
137      );
138      const outputRpmPackageFilePath = path.join(
139        CONFIG.buildOutputPath,
140        `atom.${generatedArch}.rpm`
141      );
142      console.log(
143        `Copying "${generatedPackageFilePath}" into "${outputRpmPackageFilePath}"`
144      );
145      fs.copySync(generatedPackageFilePath, outputRpmPackageFilePath);
146    }
147  };